From fa7225c82381bac4432a6edf16f53b5370238d85 Mon Sep 17 00:00:00 2001 From: Apple Date: Thu, 22 Sep 2016 17:46:01 +0000 Subject: [PATCH] Security-57740.1.18.tar.gz --- CircleJoinRequested/CircleJoinRequested.m | 273 +- ...m.apple.security.CircleJoinRequested.plist | 10 + CircleJoinRequested/entitlements.plist | 1 + CloudKeychainProxy/CloudKeychainProxy.1 | 79 - ...chainSyncingProxy+IDSProxyReceiveMessage.h | 35 + ...chainSyncingProxy+IDSProxyReceiveMessage.m | 399 + ...KeychainSyncingProxy+IDSProxySendMessage.h | 31 +- ...KeychainSyncingProxy+IDSProxySendMessage.m | 306 + ...IDSKeychainSyncingProxy+IDSProxyThrottle.h | 35 + ...IDSKeychainSyncingProxy+IDSProxyThrottle.m | 397 + .../IDSKeychainSyncingProxy-Info.plist | 4 +- .../IDSPersistentState.h | 2 +- .../IDSPersistentState.m | 4 +- .../IDSProxy.h | 41 +- IDSKeychainSyncingProxy/IDSProxy.m | 415 + ...ecurity.idskeychainsyncingproxy.ios.plist} | 36 +- ...security.idskeychainsyncingproxy.osx.plist | 4 +- .../en.lproj/InfoPlist.strings | 0 ...idskeychainsyncingproxy.entitlements.plist | 8 +- .../idskeychainsyncingproxy.m | 96 +- ISACLProtectedItems/Info.plist | 6 +- KVSKeychainSyncingProxy/CKDAccount.h | 15 + KVSKeychainSyncingProxy/CKDKVSProxy.h | 148 + KVSKeychainSyncingProxy/CKDKVSProxy.m | 1278 +++ KVSKeychainSyncingProxy/CKDKVSStore.h | 32 + KVSKeychainSyncingProxy/CKDKVSStore.m | 208 + .../CKDPersistentState.h | 29 +- KVSKeychainSyncingProxy/CKDPersistentState.m | 133 + KVSKeychainSyncingProxy/CKDSecuritydAccount.h | 19 + KVSKeychainSyncingProxy/CKDSecuritydAccount.m | 55 + KVSKeychainSyncingProxy/CKDStore.h | 28 + .../CloudKeychainProxy-Info.plist | 2 +- .../cloudkeychain.entitlements.plist | 1 - KVSKeychainSyncingProxy/cloudkeychainproxy.m | 420 + ...ple.security.cloudkeychainproxy3.ios.plist | 0 ...ple.security.cloudkeychainproxy3.osx.plist | 2 +- Keychain/KCATableViewController.m | 1 - Keychain/Keychain-Info.plist | 8 +- .../Keychain_114x114.png | Bin .../Keychain_144x144.png | Bin .../Keychain_57x57.png | Bin .../Keychain_72x72.png | Bin KeychainCircle/Info.plist | 26 + KeychainCircle/KCAESGCMDuplexSession.h | 38 + KeychainCircle/KCAESGCMDuplexSession.m | 314 + KeychainCircle/KCAccountKCCircleDelegate.h | 45 + KeychainCircle/KCAccountKCCircleDelegate.m | 77 + KeychainCircle/KCDer.h | 46 + KeychainCircle/KCDer.m | 144 + KeychainCircle/KCError.h | 34 + KeychainCircle/KCError.m | 47 + KeychainCircle/KCJoiningAcceptSession.m | 244 + KeychainCircle/KCJoiningMessages.h | 113 + KeychainCircle/KCJoiningMessages.m | 393 + KeychainCircle/KCJoiningRequestSession.m | 370 + KeychainCircle/KCJoiningSession.h | 197 + KeychainCircle/KCSRPContext.h | 76 + KeychainCircle/KCSRPContext.m | 245 + KeychainCircle/KeychainCircle.h | 9 + KeychainCircle/NSData+SecRandom.h | 11 + KeychainCircle/NSData+SecRandom.m | 26 + KeychainCircle/NSError+KCCreationHelpers.h | 53 + KeychainCircle/NSError+KCCreationHelpers.m | 116 + KeychainCircle/Tests/Info.plist | 24 + KeychainCircle/Tests/KCAESGCMTest.m | 138 + KeychainCircle/Tests/KCDerTest.m | 114 + KeychainCircle/Tests/KCJoiningSessionTest.m | 579 + KeychainCircle/Tests/KCSRPTests.m | 108 + KeychainCircle/Tests/KeychainCircle.plist | 102 + ...KeychainSyncAccountNotification-Info.plist | 2 +- .../KeychainSyncAccountNotification.m | 22 +- Modules/Security.iOS.modulemap | 20 + Modules/Security.macOS.modulemap | 48 + OSX/Breadcrumb/SecBreadcrumb.c | 89 +- ...nife-on-bread.c => bc-10-knife-on-bread.m} | 58 +- ...com.apple.private.alloy.keychainsync.plist | Bin 458 -> 0 bytes .../en.lproj/InfoPlist.strings | 2 - ...idskeychainsyncingproxy.entitlements.plist | 30 - .../KNAppDelegate.m | 18 +- .../KNPersistentState.h | 4 +- .../Keychain Circle Notification-Info.plist | 2 +- .../NSDictionary+compactDescription.m | 2 +- ...ecurity.keychain-circle-notification.plist | 8 +- .../entitlments.plist | 2 + OSX/Keychain/KDAppDelegate.m | 44 +- OSX/Keychain/KDCirclePeer.m | 4 +- OSX/Keychain/KDSecCircle.h | 2 +- OSX/Keychain/KDSecCircle.m | 15 +- OSX/Keychain/Keychain-Info.plist | 2 +- OSX/Modules | 1 + OSX/OSX.xcodeproj/project.pbxproj | 2281 ++-- .../xcshareddata/xcschemes/World.xcscheme | 144 - .../xcschemes/copyHeaders.xcscheme | 89 - .../xcschemes/osx - World.xcscheme | 323 + ...ests.xcscheme => osx - secdtests.xcscheme} | 65 +- ...tests.xcscheme => osx - sectests.xcscheme} | 20 +- .../Info.plist} | 24 +- .../SecurityTests-Entitlements.plist | 47 + OSX/SecurityTestsOSX/main.m | 47 + OSX/SecurityTestsOSX/testlist.h | 7 + OSX/authd/Info.plist | 2 +- OSX/authd/agent.c | 2 +- OSX/authd/authdb.c | 89 +- OSX/authd/authdb.h | 2 +- OSX/authd/authitems.c | 59 +- OSX/authd/authitems.h | 5 +- OSX/authd/authorization.plist | 89 +- OSX/authd/authtoken.c | 19 +- OSX/authd/ccaudit.c | 11 +- OSX/authd/engine.c | 88 +- OSX/authd/process.c | 11 +- OSX/authd/rule.c | 32 +- OSX/authd/rule.h | 12 +- OSX/authd/server.c | 100 +- OSX/authd/session.c | 6 +- .../cloud_keychain_diagnose-Prefix.pch | 5 - OSX/codesign_tests/CaspianTests/CaspianTests | 7 + OSX/config/base.xcconfig | 3 +- OSX/config/security.xcconfig | 1 + OSX/lib/AppWorkaround.plist | 90 - OSX/lib/Info-Security.plist | 8 +- .../en.lproj/authorization.buttons.strings | 4 + .../en.lproj/authorization.prompts.strings | 4 + OSX/lib/framework.sb | 3 + OSX/lib/plugins/csparser-Info.plist | 10 +- OSX/lib/security.exp-in | 606 +- OSX/libsecurity_apple_csp/TODO | 1 - OSX/libsecurity_apple_csp/lib/AppleCSP.cpp | 6 +- .../lib/AppleCSPUtils.cpp | 2 +- .../lib/BlockCryptor.cpp | 6 +- OSX/libsecurity_apple_csp/lib/DH_keys.cpp | 2 +- OSX/libsecurity_apple_csp/lib/DH_keys.h | 2 +- OSX/libsecurity_apple_csp/lib/DH_utils.cpp | 2 +- OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp | 2 +- OSX/libsecurity_apple_csp/lib/FEEKeys.cpp | 10 +- OSX/libsecurity_apple_csp/lib/FEEKeys.h | 3 + .../lib/FEESignatureObject.cpp | 2 +- .../lib/RSA_DSA_keys.cpp | 6 +- OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.h | 3 + .../lib/RSA_DSA_signature.cpp | 2 +- .../lib/RSA_DSA_utils.cpp | 2 +- .../lib/RSA_asymmetric.cpp | 4 +- .../lib/SignatureContext.cpp | 2 +- OSX/libsecurity_apple_csp/lib/ascContext.cpp | 4 +- .../lib/bsafeSymmetric.cpp | 2 +- OSX/libsecurity_apple_csp/lib/cspdebugging.h | 5 +- OSX/libsecurity_apple_csp/lib/desContext.cpp | 2 +- .../project.pbxproj | 69 +- .../open_ssl/bn/bn_prime.c | 5 +- .../open_ssl/openssl/opensslconf.h | 1 + .../open_ssl/opensslUtils/opensslAsn1.cpp | 2 +- .../open_ssl/opensslUtils/opensslUtils.cpp | 2 +- .../lib/SSCSPDLSession.cpp | 15 +- .../lib/SSCSPSession.cpp | 2 +- OSX/libsecurity_apple_cspdl/lib/SSContext.cpp | 2 +- .../lib/SSDLSession.cpp | 33 +- .../lib/SSDatabase.cpp | 88 +- OSX/libsecurity_apple_cspdl/lib/SSDatabase.h | 31 +- OSX/libsecurity_apple_cspdl/lib/SSKey.cpp | 10 +- .../project.pbxproj | 34 +- .../project.pbxproj | 34 +- OSX/libsecurity_apple_x509_cl/TODO | 1 - .../lib/AppleX509CLSession.cpp | 4 +- .../lib/cldebugging.h | 4 +- .../project.pbxproj | 35 +- .../lib/TPCertInfo.cpp | 4 +- .../lib/tpCredRequest.cpp | 2 +- .../lib/tpdebugging.h | 33 +- .../project.pbxproj | 40 +- OSX/libsecurity_asn1/config/base.xcconfig | 3 +- OSX/libsecurity_asn1/config/lib.xcconfig | 20 +- OSX/libsecurity_asn1/lib/SecAsn1Types.h | 6 + OSX/libsecurity_asn1/lib/plarena.h | 2 +- OSX/libsecurity_asn1/lib/secasn1d.c | 4 +- OSX/libsecurity_asn1/lib/secasn1e.c | 39 +- .../project.pbxproj | 232 +- .../lib/Authorization.c | 4 +- .../lib/Authorization.h | 9 +- .../lib/AuthorizationPlugin.h | 10 +- .../lib/AuthorizationTagsPriv.h | 24 + .../lib/trampolineClient.cpp | 12 +- .../project.pbxproj | 21 +- OSX/libsecurity_cdsa_client/lib/aclclient.cpp | 42 +- OSX/libsecurity_cdsa_client/lib/aclclient.h | 8 +- .../lib/cssmclient.cpp | 12 +- OSX/libsecurity_cdsa_client/lib/cssmclient.h | 6 +- OSX/libsecurity_cdsa_client/lib/dlclient.cpp | 52 +- OSX/libsecurity_cdsa_client/lib/dlclient.h | 19 + .../lib/securestorage.cpp | 18 +- .../lib/securestorage.h | 9 +- OSX/libsecurity_cdsa_client/lib/tpclient.cpp | 4 +- .../project.pbxproj | 29 +- .../lib/ACabstractsession.cpp | 69 + .../lib/ACabstractsession.h | 39 + .../lib/CLabstractsession.cpp | 548 + .../lib/CLabstractsession.h | 143 + .../lib/CSPabstractsession.cpp | 847 ++ .../lib/CSPabstractsession.h | 239 + .../lib/CSPsession.cpp | 4 +- .../lib/DLabstractsession.cpp | 333 + .../lib/DLabstractsession.h | 107 + .../lib/DatabaseSession.cpp | 154 +- .../lib/TPabstractsession.cpp | 416 + .../lib/TPabstractsession.h | 140 + OSX/libsecurity_cdsa_plugin/lib/generator.cfg | 59 - OSX/libsecurity_cdsa_plugin/lib/generator.mk | 29 - OSX/libsecurity_cdsa_plugin/lib/generator.pl | 247 - .../project.pbxproj | 141 +- .../lib/AuthorizationData.cpp | 102 +- .../lib/AuthorizationData.h | 15 +- OSX/libsecurity_cdsa_utilities/lib/Schema.m4 | 2 +- .../lib/acl_codesigning.cpp | 6 +- .../lib/acl_preauth.cpp | 6 +- .../lib/acl_secret.cpp | 8 +- .../lib/acl_threshold.cpp | 2 +- .../lib/aclsubject.h | 1 + OSX/libsecurity_cdsa_utilities/lib/context.h | 2 +- .../lib/cssmcred.cpp | 2 +- .../lib/cssmdbname.cpp | 1 + .../lib/cssmerrors.cpp | 7 +- OSX/libsecurity_cdsa_utilities/lib/cssmlist.h | 3 +- OSX/libsecurity_cdsa_utilities/lib/db++.cpp | 10 +- .../lib/handletemplates_defs.h | 2 +- .../lib/objectacl.cpp | 34 +- .../lib/osxverifier.cpp | 20 +- OSX/libsecurity_cdsa_utilities/lib/walkers.h | 4 +- .../project.pbxproj | 24 +- OSX/libsecurity_cdsa_utils/lib/cuDbUtils.cpp | 31 +- OSX/libsecurity_cdsa_utils/lib/cuDbUtils.h | 2 +- OSX/libsecurity_cdsa_utils/lib/cuFileIo.c | 11 +- OSX/libsecurity_cdsa_utils/lib/cuFileIo.h | 7 + .../project.pbxproj | 23 +- .../project.pbxproj | 20 +- OSX/libsecurity_cms/lib/CMSEncoder.cpp | 13 +- .../libsecurity_cms.xcodeproj/project.pbxproj | 30 +- .../regressions/cms-hashagility-test.c | 1 + .../regressions/cms-hashagility-test.h | 1 + .../regressions/cms-trust-settings-test.c | 127 + .../regressions/cms-trust-settings-test.h | 180 + .../regressions/cms_regressions.h | 3 +- .../CodeSigningHelper-Info.plist | 2 +- .../CodeSigningHelper/main.c | 5 + .../CodeSigningHelper/main.cpp | 108 + OSX/libsecurity_codesigning/lib/CSCommon.h | 7 +- OSX/libsecurity_codesigning/lib/Code.cpp | 7 +- .../lib/CodeSigner.cpp | 4 +- .../lib/SecAssessment.cpp | 21 +- .../lib/SecAssessment.h | 6 +- OSX/libsecurity_codesigning/lib/SecCode.cpp | 50 +- OSX/libsecurity_codesigning/lib/SecCode.h | 63 +- OSX/libsecurity_codesigning/lib/SecCodePriv.h | 38 + .../lib/SecCodeSigner.cpp | 2 + .../lib/SecRequirement.h | 4 - .../lib/SecRequirementPriv.h | 12 +- .../lib/SecStaticCode.cpp | 87 +- .../lib/SecStaticCode.h | 40 +- OSX/libsecurity_codesigning/lib/SecTask.c | 56 +- OSX/libsecurity_codesigning/lib/SecTask.h | 15 + OSX/libsecurity_codesigning/lib/SecTaskPriv.h | 10 + .../lib/StaticCode.cpp | 309 +- OSX/libsecurity_codesigning/lib/StaticCode.h | 11 +- .../lib/bundlediskrep.cpp | 220 +- .../lib/bundlediskrep.h | 15 +- .../lib/codedirectory.cpp | 17 +- .../lib/codedirectory.h | 3 +- OSX/libsecurity_codesigning/lib/cs.h | 7 +- OSX/libsecurity_codesigning/lib/cskernel.cpp | 67 +- OSX/libsecurity_codesigning/lib/csprocess.cpp | 17 +- OSX/libsecurity_codesigning/lib/csprocess.h | 11 +- OSX/libsecurity_codesigning/lib/csutilities.h | 2 +- .../lib/dirscanner.cpp | 56 +- OSX/libsecurity_codesigning/lib/dirscanner.h | 4 + .../lib/diskimagerep.cpp | 35 +- OSX/libsecurity_codesigning/lib/diskrep.cpp | 4 + OSX/libsecurity_codesigning/lib/diskrep.h | 1 + .../lib/evaluationmanager.cpp | 102 +- .../lib/evaluationmanager.h | 2 + .../lib/filediskrep.cpp | 5 +- OSX/libsecurity_codesigning/lib/machorep.cpp | 58 +- OSX/libsecurity_codesigning/lib/machorep.h | 4 +- .../lib/piddiskrep.cpp | 35 +- OSX/libsecurity_codesigning/lib/piddiskrep.h | 7 +- OSX/libsecurity_codesigning/lib/policydb.cpp | 34 +- OSX/libsecurity_codesigning/lib/policydb.h | 7 +- .../lib/policyengine.cpp | 171 +- .../lib/policyengine.h | 2 +- OSX/libsecurity_codesigning/lib/reqinterp.cpp | 20 +- OSX/libsecurity_codesigning/lib/reqparser.cpp | 2 + OSX/libsecurity_codesigning/lib/resources.cpp | 33 +- OSX/libsecurity_codesigning/lib/resources.h | 2 +- .../lib/security_codesigning.exp | 7 + OSX/libsecurity_codesigning/lib/signer.cpp | 50 +- OSX/libsecurity_codesigning/lib/signer.h | 3 +- .../lib/signerutils.cpp | 8 +- .../lib/singlediskrep.cpp | 7 +- .../lib/singlediskrep.h | 2 +- OSX/libsecurity_codesigning/lib/syspolicy.sql | 2 + OSX/libsecurity_codesigning/lib/xpcengine.cpp | 32 +- OSX/libsecurity_codesigning/lib/xpcengine.h | 1 + .../project.pbxproj | 93 +- .../project.pbxproj | 30 +- OSX/libsecurity_cryptkit/lib/ckutilities.c | 6 +- .../lib/feeDigitalSignature.c | 6 + OSX/libsecurity_cryptkit/lib/feeECDSA.c | 5 +- OSX/libsecurity_cryptkit/lib/giantIntegers.c | 6 +- OSX/libsecurity_cryptkit/lib/giantIntegers.h | 2 +- .../lib/giantPort_Generic.h | 6 +- OSX/libsecurity_cryptkit/lib/platform.c | 15 +- .../project.pbxproj | 18 +- OSX/libsecurity_cssm/lib/attachment.cpp | 7 +- OSX/libsecurity_cssm/lib/certextensions.h | 5 + OSX/libsecurity_cssm/lib/cssmaci.h | 5 + OSX/libsecurity_cssm/lib/cssmapple.h | 18 +- OSX/libsecurity_cssm/lib/cssmapplePriv.h | 12 + OSX/libsecurity_cssm/lib/cssmcli.h | 5 + OSX/libsecurity_cssm/lib/cssmcspi.h | 5 + OSX/libsecurity_cssm/lib/cssmdli.h | 5 + OSX/libsecurity_cssm/lib/cssmkrapi.h | 5 + OSX/libsecurity_cssm/lib/cssmkrspi.h | 5 + OSX/libsecurity_cssm/lib/cssmspi.h | 4 + OSX/libsecurity_cssm/lib/cssmtpi.h | 5 + OSX/libsecurity_cssm/lib/cssmtype.h | 5 + OSX/libsecurity_cssm/lib/emmspi.h | 5 + OSX/libsecurity_cssm/lib/emmtype.h | 5 + OSX/libsecurity_cssm/lib/manager.cpp | 18 +- OSX/libsecurity_cssm/lib/modload_plugin.cpp | 20 +- OSX/libsecurity_cssm/lib/modload_plugin.h | 2 + OSX/libsecurity_cssm/lib/modloader.cpp | 4 +- OSX/libsecurity_cssm/lib/transition.cpp | 5 - OSX/libsecurity_cssm/lib/x509defs.h | 5 + .../project.pbxproj | 18 +- OSX/libsecurity_filedb/lib/AppleDatabase.cpp | 23 +- OSX/libsecurity_filedb/lib/AppleDatabase.h | 5 + OSX/libsecurity_filedb/lib/AtomicFile.cpp | 184 +- OSX/libsecurity_filedb/lib/AtomicFile.h | 3 - .../project.pbxproj | 36 +- OSX/libsecurity_keychain/lib/ACL.cpp | 42 +- OSX/libsecurity_keychain/lib/Access.cpp | 16 +- .../lib/AppleBaselineEscrowCertificates.h | 42 +- OSX/libsecurity_keychain/lib/CCallbackMgr.cp | 153 +- OSX/libsecurity_keychain/lib/CCallbackMgr.h | 11 +- OSX/libsecurity_keychain/lib/Certificate.cpp | 49 +- .../lib/CertificateRequest.h | 2 +- .../lib/CertificateValues.cpp | 13 + .../lib/CertificateValues.h | 1 + .../lib/DLDBListCFPref.cpp | 48 +- .../lib/DynamicDLDBList.cpp | 10 +- OSX/libsecurity_keychain/lib/Globals.cpp | 3 + OSX/libsecurity_keychain/lib/Identity.cpp | 120 +- OSX/libsecurity_keychain/lib/Identity.h | 7 +- .../lib/IdentityCursor.cpp | 40 +- OSX/libsecurity_keychain/lib/Item.cpp | 269 +- OSX/libsecurity_keychain/lib/Item.h | 16 +- OSX/libsecurity_keychain/lib/KCCursor.cpp | 48 +- OSX/libsecurity_keychain/lib/KCCursor.h | 3 + .../lib/KCEventNotifier.cpp | 2 +- OSX/libsecurity_keychain/lib/KeyItem.cpp | 664 +- OSX/libsecurity_keychain/lib/KeyItem.h | 40 +- OSX/libsecurity_keychain/lib/Keychains.cpp | 431 +- OSX/libsecurity_keychain/lib/Keychains.h | 34 +- OSX/libsecurity_keychain/lib/Policies.cpp | 4 +- OSX/libsecurity_keychain/lib/SecAccess.cpp | 1 - OSX/libsecurity_keychain/lib/SecAccess.h | 2 +- OSX/libsecurity_keychain/lib/SecBasePriv.h | 1 + OSX/libsecurity_keychain/lib/SecBridge.h | 107 +- OSX/libsecurity_keychain/lib/SecCFTypes.cpp | 1 - OSX/libsecurity_keychain/lib/SecCFTypes.h | 1 - .../lib/SecCertificate.cpp | 251 +- OSX/libsecurity_keychain/lib/SecCertificate.h | 37 +- .../lib/SecCertificateP.c | 124 +- .../lib/SecCertificatePriv.h | 99 +- .../lib/SecCertificatePrivP.h | 19 +- .../lib/SecFDERecoveryAsymmetricCrypto.cpp | 11 +- OSX/libsecurity_keychain/lib/SecFrameworkP.c | 109 +- OSX/libsecurity_keychain/lib/SecIdentity.cpp | 87 +- OSX/libsecurity_keychain/lib/SecIdentity.h | 3 +- OSX/libsecurity_keychain/lib/SecImport.cpp | 2 +- .../lib/SecImportExportOpenSSH.cpp | 2 +- .../lib/SecImportExportPkcs8.cpp | 2 +- .../lib/SecImportExportUtils.h | 4 +- OSX/libsecurity_keychain/lib/SecInternal.h | 3 +- OSX/libsecurity_keychain/lib/SecItem.cpp | 921 +- OSX/libsecurity_keychain/lib/SecItem.h | 36 + .../lib/SecItemConstants.c | 8 + OSX/libsecurity_keychain/lib/SecItemPriv.h | 67 +- OSX/libsecurity_keychain/lib/SecKey.cpp | 1904 ++-- OSX/libsecurity_keychain/lib/SecKey.h | 685 +- OSX/libsecurity_keychain/lib/SecKeyPriv.h | 182 +- OSX/libsecurity_keychain/lib/SecKeychain.cpp | 273 +- OSX/libsecurity_keychain/lib/SecKeychain.h | 6 +- .../lib/SecKeychainItem.cpp | 814 +- .../lib/SecKeychainItem.h | 2 +- .../lib/SecKeychainItemExtendedAttributes.cpp | 22 +- .../lib/SecKeychainPriv.h | 16 + .../lib/SecKeychainSearch.cpp | 24 +- OSX/libsecurity_keychain/lib/SecPassword.cpp | 6 +- OSX/libsecurity_keychain/lib/SecPolicy.cpp | 142 +- OSX/libsecurity_keychain/lib/SecPolicy.h | 183 +- OSX/libsecurity_keychain/lib/SecPolicyPriv.h | 1328 ++- OSX/libsecurity_keychain/lib/SecRandom.h | 2 + OSX/libsecurity_keychain/lib/SecTrust.cpp | 960 +- OSX/libsecurity_keychain/lib/SecTrust.h | 57 +- .../lib/SecTrustOSXEntryPoints.cpp | 290 + OSX/libsecurity_keychain/lib/SecTrustPriv.h | 407 +- .../lib/SecTrustSettings.cpp | 166 +- .../lib/SecTrustSettings.h | 4 +- .../lib/SecTrustSettingsCertificates.h | 173 +- .../lib/SecTrustSettingsPriv.h | 21 +- .../lib/StorageManager.cpp | 684 +- OSX/libsecurity_keychain/lib/StorageManager.h | 52 +- OSX/libsecurity_keychain/lib/TokenLogin.cpp | 614 + OSX/libsecurity_keychain/lib/TokenLogin.h | 49 + OSX/libsecurity_keychain/lib/Trust.cpp | 52 +- OSX/libsecurity_keychain/lib/Trust.h | 2 +- .../lib/TrustAdditions.cpp | 48 +- OSX/libsecurity_keychain/lib/TrustItem.cpp | 10 +- .../lib/TrustSettings.cpp | 98 +- .../lib/TrustSettingsSchema.h | 3 +- OSX/libsecurity_keychain/lib/TrustStore.cpp | 12 +- .../lib/TrustedApplication.cpp | 12 +- .../lib/UnlockReferralItem.cpp | 10 +- OSX/libsecurity_keychain/lib/defaultcreds.cpp | 14 +- .../lib/security_keychain.exp | 24 +- .../libDER/Tests/parseTicket.c | 23 - .../libDER/config/base.xcconfig | 3 +- .../libDER/config/lib.xcconfig | 11 +- .../libDER/libDER.xcodeproj/project.pbxproj | 184 +- .../libDER/libDER/DER_CertCrl.h | 12 +- .../libDER/libDER/DER_Decode.c | 215 +- .../libDER/libDER/DER_Decode.h | 49 +- .../libDER/libDER/DER_Digest.h | 12 +- .../libDER/libDER/DER_Encode.c | 7 +- .../libDER/libDER/DER_Encode.h | 13 +- .../libDER/libDER/DER_Keys.h | 12 +- .../libDER/libDER/asn1Types.h | 51 +- .../libDER/libDER/libDER.h | 15 +- .../libDER/libDER/libDER_config.h | 13 +- OSX/libsecurity_keychain/libDER/libDER/oids.c | 85 +- OSX/libsecurity_keychain/libDER/libDER/oids.h | 16 +- .../libDER/libDER/oidsPriv.h | 20 +- .../project.pbxproj | 305 +- .../regressions/kc-01-keychain-creation.c | 35 + .../regressions/kc-02-unlock-noui.c | 36 + .../regressions/kc-03-keychain-list.c | 124 + .../regressions/kc-03-status.c | 43 +- .../regressions/kc-04-is-valid.c | 27 +- .../kc-05-find-existing-items-locked.c | 126 + .../regressions/kc-05-find-existing-items.c | 120 + .../regressions/kc-06-cert-search-email.m | 207 + .../regressions/kc-10-item-add-certificate.c | 18 +- .../regressions/kc-10-item-add-generic.c | 23 +- .../regressions/kc-10-item-add-internet.c | 33 +- .../regressions/kc-12-item-create-keypair.c | 24 +- .../kc-12-key-create-symmetric-and-use.m | 258 + .../regressions/kc-12-key-create-symmetric.c | 77 + .../kc-15-item-update-label-skimaad.m | 169 + .../regressions/kc-15-key-update-valueref.c | 301 + .../regressions/kc-16-item-update-password.c | 94 + .../regressions/kc-18-find-combined.c | 1790 ++- .../regressions}/kc-19-item-copy-internet.c | 53 +- .../regressions/kc-20-identity-find-stress.c | 87 + .../kc-20-identity-key-attributes.c | 101 + .../kc-20-identity-persistent-refs.c | 174 + .../regressions/kc-20-item-find-stress.c | 75 + .../regressions/kc-20-key-find-stress.c | 75 + .../regressions}/kc-21-item-use-callback.c | 67 +- .../regressions/kc-21-item-xattrs.c | 404 + .../regressions/kc-23-key-export-symmetric.m | 142 + .../regressions/kc-24-key-copy-keychains.c | 290 + .../regressions/kc-26-key-import-public.m | 222 + .../regressions/kc-27-key-non-extractable.c | 236 + .../regressions/kc-28-cert-sign.c | 733 ++ .../regressions/kc-28-p12-import.m | 268 + .../regressions/kc-30-xara-helpers.h | 93 +- .../regressions/kc-30-xara-item-helpers.h | 127 +- .../regressions/kc-30-xara-key-helpers.h | 234 +- .../regressions/kc-30-xara-upgrade-helpers.h | 1500 ++- .../regressions/kc-30-xara.c | 590 +- .../regressions/kc-40-seckey.c | 609 - .../regressions/kc-40-seckey.m | 1415 +++ .../{kc-41-sececkey.c => kc-41-sececkey.m} | 111 +- .../regressions/kc-42-trust-revocation.c | 62 +- .../regressions/kc-43-seckey-interop.m | 603 + .../regressions/kc-helpers.h | 253 + .../regressions/kc-identity-helpers.h | 270 + .../regressions/kc-item-helpers.h | 153 + .../regressions/kc-key-helpers.h | 283 + .../regressions/kc-keychain-file-helpers.h | 2384 ++++ .../regressions/keychain_regressions.h | 33 + .../regressions/si-34-one-true-keychain.c | 6 +- .../xpc-tsa/XPCTimeStampingService-Info.plist | 2 +- OSX/libsecurity_keychain/xpc-tsa/main-tsa.m | 6 +- .../xpc/XPCKeychainSandboxCheck-Info.plist | 2 +- .../lib/AppleManifest.cpp | 36 +- .../lib/ManifestInternal.cpp | 40 +- OSX/libsecurity_manifest/lib/SecManifest.cpp | 20 +- .../project.pbxproj | 25 +- OSX/libsecurity_mds/lib/MDSAttrParser.cpp | 21 +- OSX/libsecurity_mds/lib/MDSAttrUtils.h | 4 +- OSX/libsecurity_mds/lib/MDSDatabase.cpp | 12 +- OSX/libsecurity_mds/lib/MDSDatabase.h | 12 +- OSX/libsecurity_mds/lib/MDSDictionary.cpp | 20 +- OSX/libsecurity_mds/lib/MDSDictionary.h | 6 +- OSX/libsecurity_mds/lib/MDSModule.cpp | 2 +- OSX/libsecurity_mds/lib/MDSSession.cpp | 12 +- OSX/libsecurity_mds/lib/mds.h | 5 + OSX/libsecurity_mds/lib/mdsapi.cpp | 2 +- .../libsecurity_mds.xcodeproj/project.pbxproj | 42 +- OSX/libsecurity_ocspd/common/ocspdDebug.h | 42 +- .../project.pbxproj | 28 +- OSX/libsecurity_pkcs12/lib/pkcs12Debug.h | 8 +- OSX/libsecurity_pkcs12/lib/pkcs12Utils.cpp | 12 +- .../project.pbxproj | 21 +- .../lib/SDCSPDLPlugin.cpp | 4 +- OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp | 6 +- OSX/libsecurity_sd_cspdl/lib/SDCSPSession.h | 4 +- OSX/libsecurity_sd_cspdl/lib/SDContext.cpp | 2 +- OSX/libsecurity_sd_cspdl/lib/SDDLSession.cpp | 8 +- .../project.pbxproj | 42 +- OSX/libsecurity_smime/TODO | 9 - OSX/libsecurity_smime/lib/SecCMS.c | 439 +- OSX/libsecurity_smime/lib/SecCMS.h | 67 + OSX/libsecurity_smime/lib/cmscinfo.c | 2 + OSX/libsecurity_smime/lib/cmscipher.c | 7 + OSX/libsecurity_smime/lib/cmsdecode.c | 19 +- OSX/libsecurity_smime/lib/cmsdigdata.c | 6 + OSX/libsecurity_smime/lib/cmsdigest.c | 29 +- OSX/libsecurity_smime/lib/cmsencdata.c | 3 + OSX/libsecurity_smime/lib/cmsmessage.c | 4 +- OSX/libsecurity_smime/lib/cmspubkey.c | 974 +- OSX/libsecurity_smime/lib/cmsrecinfo.c | 4 - OSX/libsecurity_smime/lib/cmsreclist.c | 1 + OSX/libsecurity_smime/lib/cmssigdata.c | 19 +- OSX/libsecurity_smime/lib/cmssiginfo.c | 7 - OSX/libsecurity_smime/lib/cmsutil.c | 8 +- OSX/libsecurity_smime/lib/cryptohi.c | 722 +- OSX/libsecurity_smime/lib/cryptohi.h | 8 + OSX/libsecurity_smime/lib/smimeutil.c | 6 + OSX/libsecurity_smime/lib/tsaSupport.c | 40 +- .../project.pbxproj | 44 +- .../regressions/cms-01-basic.c | 501 + .../regressions/cms-01-basic.h | 1341 +++ .../regressions/smime-cms-test.c | 35 +- .../regressions/smime_regressions.h | 1 + OSX/libsecurity_ssl/config/base.xcconfig | 3 +- OSX/libsecurity_ssl/config/kext.xcconfig | 2 +- OSX/libsecurity_ssl/config/lib.xcconfig | 6 +- OSX/libsecurity_ssl/config/tests.xcconfig | 13 +- OSX/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c | 310 - OSX/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c | 325 - OSX/libsecurity_ssl/lib/SSLRecordInternal.c | 18 +- OSX/libsecurity_ssl/lib/SecureTransport.h | 97 +- OSX/libsecurity_ssl/lib/SecureTransportPriv.h | 40 +- OSX/libsecurity_ssl/lib/appleSession.c | 470 - OSX/libsecurity_ssl/lib/security_ssl.exp | 3 +- OSX/libsecurity_ssl/lib/sslCipherSpecs.c | 14 +- OSX/libsecurity_ssl/lib/sslContext.c | 472 +- OSX/libsecurity_ssl/lib/sslContext.h | 23 +- OSX/libsecurity_ssl/lib/sslCrypto.c | 276 +- OSX/libsecurity_ssl/lib/sslCrypto.h | 1 - OSX/libsecurity_ssl/lib/sslDebug.h | 32 +- OSX/libsecurity_ssl/lib/sslKeychain.c | 1 - OSX/libsecurity_ssl/lib/sslRecord.c | 1 - OSX/libsecurity_ssl/lib/sslTransport.c | 206 +- OSX/libsecurity_ssl/lib/sslTypes.h | 1 - OSX/libsecurity_ssl/lib/sslUtils.c | 140 - OSX/libsecurity_ssl/lib/sslUtils.h | 82 - OSX/libsecurity_ssl/lib/tlsCallbacks.c | 40 +- OSX/libsecurity_ssl/lib/tls_record_internal.h | 1 - .../libsecurity_ssl.xcodeproj/project.pbxproj | 20 +- OSX/libsecurity_ssl/regressions/ssl-39-echo.c | 2 +- .../regressions/ssl-41-clientauth.c | 5 + .../regressions/ssl-42-ciphers.c | 9 +- .../regressions/ssl-43-ciphers.c | 44 +- .../regressions/ssl-44-crashes.c | 16 +- .../regressions/ssl-45-tls12.c | 35 +- .../ssl-46-SSLGetSupportedCiphers.c | 51 +- .../regressions/ssl-47-falsestart.c | 44 +- .../regressions/ssl-48-split.c | 2 +- OSX/libsecurity_ssl/regressions/ssl-49-sni.c | 5 +- .../regressions/ssl-51-state.c | 1 + .../regressions/ssl-52-noconn.c | 2 + .../regressions/ssl-53-clientauth.c | 2 - OSX/libsecurity_ssl/regressions/ssl-54-dhe.c | 3 - .../regressions/ssl-55-sessioncache.c | 132 +- .../regressions/ssl-56-renegotiate.c | 464 + OSX/libsecurity_ssl/regressions/ssl-utils.h | 12 +- .../regressions/ssl_regressions.h | 1 + OSX/libsecurity_ssl/sslViewer/fileIo.c | 116 - OSX/libsecurity_ssl/sslViewer/ioSock.c | 502 - OSX/libsecurity_ssl/sslViewer/ioSock.h | 110 - OSX/libsecurity_ssl/sslViewer/printCert.c | 218 - OSX/libsecurity_ssl/sslViewer/sslAppUtils.cpp | 1592 --- OSX/libsecurity_ssl/sslViewer/sslAppUtils.h | 167 - OSX/libsecurity_ssl/sslViewer/sslServer.1 | 79 - OSX/libsecurity_ssl/sslViewer/sslServer.cpp | 1061 -- OSX/libsecurity_ssl/sslViewer/sslViewer.1 | 79 - OSX/libsecurity_ssl/sslViewer/sslViewer.cpp | 1870 ---- .../sslViewer.xcodeproj/project.pbxproj | 454 - .../libsecurity_transform_core.xcconfig | 1 + .../security_transform_Default.xcconfig | 1 + .../security_transform_Deployment.xcconfig | 1 + .../security_transform_Development.xcconfig | 1 + OSX/libsecurity_transform/custom.h | 4 +- .../lib/SecDigestTransform.h | 2 +- OSX/libsecurity_transform/lib/c++utils.cpp | 2 +- .../project.pbxproj | 26 +- .../unit-tests-Info.plist | 2 +- .../lib/SecTranslocate.cpp | 500 + .../lib/SecTranslocate.h | 218 + .../lib/SecTranslocateClient.cpp | 190 + .../lib/SecTranslocateClient.hpp | 63 + .../lib/SecTranslocateDANotification.cpp | 221 + .../lib/SecTranslocateDANotification.hpp | 50 + .../lib/SecTranslocateInterface.cpp | 95 + .../lib/SecTranslocateInterface.hpp | 56 + .../lib/SecTranslocateLSNotification.cpp | 282 + .../lib/SecTranslocateLSNotification.hpp | 56 + .../lib/SecTranslocateServer.cpp | 167 + .../lib/SecTranslocateServer.hpp | 73 + .../lib/SecTranslocateShared.cpp | 1023 ++ .../lib/SecTranslocateShared.hpp | 89 + .../lib/SecTranslocateUtilities.cpp | 330 + .../lib/SecTranslocateUtilities.hpp | 108 + .../lib/SecTranslocateXPCServer.cpp | 155 + .../lib/SecTranslocateXPCServer.hpp | 51 + .../lib/security_translocate.exp | 25 + .../project.pbxproj | 383 + .../lib/CSPDLTransaction.cpp | 61 +- .../lib/CSPDLTransaction.h | 25 +- .../lib/FileLockTransaction.cpp | 76 + .../lib/FileLockTransaction.h | 69 + OSX/libsecurity_utilities/lib/alloc.h | 9 +- .../lib/casts.h} | 51 +- OSX/libsecurity_utilities/lib/ccaudit.cpp | 2 +- OSX/libsecurity_utilities/lib/cfclass.cpp | 49 +- OSX/libsecurity_utilities/lib/cfmach++.cpp | 8 +- OSX/libsecurity_utilities/lib/cfutilities.cpp | 2 +- OSX/libsecurity_utilities/lib/cfutilities.h | 4 +- .../lib/coderepository.cpp | 8 +- .../lib/coderepository.h | 8 +- OSX/libsecurity_utilities/lib/daemon.cpp | 4 +- OSX/libsecurity_utilities/lib/debugging.cpp | 518 - OSX/libsecurity_utilities/lib/debugging.h | 130 +- .../lib/debugging_internal.cpp | 546 +- .../lib/debugging_internal.h | 125 +- OSX/libsecurity_utilities/lib/errors.cpp | 90 +- OSX/libsecurity_utilities/lib/errors.h | 5 + OSX/libsecurity_utilities/lib/exports | 6 + OSX/libsecurity_utilities/lib/globalizer.h | 2 +- OSX/libsecurity_utilities/lib/hosts.cpp | 2 +- OSX/libsecurity_utilities/lib/iodevices.cpp | 17 +- OSX/libsecurity_utilities/lib/ip++.cpp | 18 +- OSX/libsecurity_utilities/lib/mach++.cpp | 13 +- OSX/libsecurity_utilities/lib/mach++.h | 1 + OSX/libsecurity_utilities/lib/macho++.cpp | 8 +- .../lib/machrunloopserver.cpp | 2 +- OSX/libsecurity_utilities/lib/machserver.cpp | 40 +- OSX/libsecurity_utilities/lib/memutils.h | 2 +- OSX/libsecurity_utilities/lib/muscle++.cpp | 11 +- OSX/libsecurity_utilities/lib/osxcode.cpp | 12 +- OSX/libsecurity_utilities/lib/pcsc++.cpp | 50 +- OSX/libsecurity_utilities/lib/powerwatch.cpp | 40 +- OSX/libsecurity_utilities/lib/refcount.h | 13 +- OSX/libsecurity_utilities/lib/seccfobject.cpp | 30 +- OSX/libsecurity_utilities/lib/seccfobject.h | 29 +- OSX/libsecurity_utilities/lib/selector.cpp | 16 +- OSX/libsecurity_utilities/lib/simpleprefs.cpp | 2 +- OSX/libsecurity_utilities/lib/socks++4.cpp | 6 +- OSX/libsecurity_utilities/lib/socks++5.cpp | 12 +- OSX/libsecurity_utilities/lib/sqlite++.cpp | 5 +- OSX/libsecurity_utilities/lib/superblob.h | 33 +- OSX/libsecurity_utilities/lib/threading.cpp | 15 +- OSX/libsecurity_utilities/lib/threading.h | 27 + OSX/libsecurity_utilities/lib/tqueue.h | 10 +- OSX/libsecurity_utilities/lib/unix++.cpp | 95 +- OSX/libsecurity_utilities/lib/unix++.h | 13 +- OSX/libsecurity_utilities/lib/unixchild.cpp | 78 +- OSX/libsecurity_utilities/lib/vproc++.cpp | 1 + .../project.pbxproj | 121 +- OSX/libsecurityd/lib/SharedMemoryClient.cpp | 38 +- OSX/libsecurityd/lib/eventlistener.cpp | 254 +- OSX/libsecurityd/lib/eventlistener.h | 8 + OSX/libsecurityd/lib/ssblob.cpp | 139 +- OSX/libsecurityd/lib/ssblob.h | 40 +- OSX/libsecurityd/lib/ssclient.cpp | 18 +- OSX/libsecurityd/lib/ssclient.h | 29 +- OSX/libsecurityd/lib/sstransit.cpp | 6 +- OSX/libsecurityd/lib/transition.cpp | 201 +- OSX/libsecurityd/lib/xdr_cssm.c | 2 +- .../libsecurityd.xcodeproj/project.pbxproj | 46 +- OSX/libsecurityd/mig/ucsp.defs | 63 +- .../regressions.xcodeproj/project.pbxproj | 36 +- OSX/regressions/test/testenv.h | 2 + OSX/regressions/test/testenv.m | 63 +- OSX/regressions/test/testmore.c | 81 +- OSX/regressions/test/testpolicy.m | 23 +- .../CKBridge/SOSCloudKeychainClient.c | 215 +- .../CKBridge/SOSCloudKeychainClient.h | 16 +- .../CKBridge/SOSCloudKeychainConstants.c | 6 +- .../CKBridge/SOSCloudKeychainConstants.h | 6 +- .../CKBridge/SOSCloudKeychainLogging.c | 222 + .../CKBridge/SOSCloudKeychainLogging.h | 13 + .../CloudKeychainProxy/CKDKVSProxy.h | 10 +- .../CloudKeychainProxy/CKDKVSProxy.m | 176 +- .../CloudKeychainProxy/CKDUserInteraction.m | 129 - .../cloudkeychain.entitlements.plist | 19 - .../CloudKeychainProxy/cloudkeychainproxy.m | 15 - .../en.lproj/InfoPlist.strings | 2 - OSX/sec/SOSCircle/Empty.c | 0 .../IDSKeychainSyncingProxy/IDSProxy.m | 685 -- ...idskeychainsyncingproxy.entitlements.plist | 30 - .../SOSCircle/Regressions/CKDKeyValueStore.h | 94 - .../SOSCircle/Regressions/CKDKeyValueStore.m | 365 - .../Regressions/SOSRegressionUtilities.c | 2 +- .../SOSCircle/Regressions/SOSTestDataSource.c | 25 +- OSX/sec/SOSCircle/Regressions/SOSTestDevice.c | 14 +- OSX/sec/SOSCircle/Regressions/SOSTestDevice.h | 2 + .../Regressions/sc-130-resignationticket.c | 18 +- OSX/sec/SOSCircle/Regressions/sc-140-hsa2.c | 247 +- .../Regressions/sc-150-backupkeyderivation.c | 4 +- OSX/sec/SOSCircle/Regressions/sc-150-ring.c | 7 + .../Regressions/sc-153-backupslicekeybag.c | 15 +- .../SOSCircle/Regressions/sc-20-keynames.c | 10 +- .../SOSCircle/Regressions/sc-25-soskeygen.c | 25 +- .../Regressions/sc-31-peerinfo-simplefuzz.c | 4 +- OSX/sec/SOSCircle/Regressions/sc-40-circle.c | 17 +- .../Regressions/sc-45-digestvector.c | 9 + .../SOSCircle/SecureObjectSync/SOSAccount.c | 1439 ++- .../SOSCircle/SecureObjectSync/SOSAccount.h | 78 +- .../SecureObjectSync/SOSAccountBackup.c | 138 +- .../SecureObjectSync/SOSAccountCircles.c | 41 +- .../SecureObjectSync/SOSAccountCredentials.c | 35 +- .../SecureObjectSync/SOSAccountFullPeerInfo.c | 21 +- .../SecureObjectSync/SOSAccountLog.c | 51 + .../SecureObjectSync/SOSAccountLog.h | 27 + .../SecureObjectSync/SOSAccountPeers.c | 30 + .../SecureObjectSync/SOSAccountPersistence.c | 55 +- .../SecureObjectSync/SOSAccountPriv.h | 65 +- .../SecureObjectSync/SOSAccountRingUpdate.c | 77 +- .../SecureObjectSync/SOSAccountRings.c | 223 +- .../SecureObjectSync/SOSAccountTransaction.c | 199 + .../SecureObjectSync/SOSAccountTransaction.h | 41 + .../SecureObjectSync/SOSAccountUpdate.c | 123 +- .../SecureObjectSync/SOSAccountViewSync.c | 379 + .../SecureObjectSync/SOSBackupSliceKeyBag.c | 29 +- .../SecureObjectSync/SOSBackupSliceKeyBag.h | 3 + .../SOSCircle/SecureObjectSync/SOSCircle.c | 329 +- .../SOSCircle/SecureObjectSync/SOSCircle.h | 16 +- .../SOSCircle/SecureObjectSync/SOSCircleDer.c | 10 +- .../SecureObjectSync/SOSCloudCircle.c | 208 +- .../SecureObjectSync/SOSCloudCircle.h | 61 +- .../SecureObjectSync/SOSCloudCircleInternal.h | 6 +- OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c | 287 +- OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.h | 9 +- .../SecureObjectSync/SOSDataSource.h | 44 +- .../SecureObjectSync/SOSDigestVector.c | 79 +- .../SecureObjectSync/SOSDigestVector.h | 4 +- .../SecureObjectSync/SOSECWrapUnwrap.c | 2 +- .../SOSCircle/SecureObjectSync/SOSEngine.c | 985 +- .../SOSCircle/SecureObjectSync/SOSEngine.h | 18 +- .../SecureObjectSync/SOSExports.exp-in | 62 +- .../SecureObjectSync/SOSForerunnerSession.c | 1464 --- .../SecureObjectSync/SOSForerunnerSession.h | 380 - .../SecureObjectSync/SOSFullPeerInfo.c | 74 +- .../SecureObjectSync/SOSFullPeerInfo.h | 2 + .../SOSCircle/SecureObjectSync/SOSGenCount.c | 23 +- .../SOSCircle/SecureObjectSync/SOSInternal.c | 31 +- .../SOSCircle/SecureObjectSync/SOSInternal.h | 5 + .../SOSCircle/SecureObjectSync/SOSKVSKeys.c | 73 +- .../SOSCircle/SecureObjectSync/SOSKVSKeys.h | 5 +- OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c | 84 +- OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.h | 4 - .../SOSCircle/SecureObjectSync/SOSPeerCoder.c | 44 +- .../SOSCircle/SecureObjectSync/SOSPeerCoder.h | 29 +- .../SOSCircle/SecureObjectSync/SOSPeerInfo.c | 162 +- .../SOSCircle/SecureObjectSync/SOSPeerInfo.h | 13 +- .../SecureObjectSync/SOSPeerInfoCollections.h | 2 +- .../SecureObjectSync/SOSPeerInfoDER.c | 12 +- .../SecureObjectSync/SOSPeerInfoV2.c | 45 +- .../SecureObjectSync/SOSPeerInfoV2.h | 3 + .../SOSCircle/SecureObjectSync/SOSPersist.h | 94 + .../SecureObjectSync/SOSRingBackup.c | 2 +- .../SOSRingConcordanceTrust.c | 7 +- .../SOSCircle/SecureObjectSync/SOSRingDER.c | 10 +- .../SOSCircle/SecureObjectSync/SOSRingTypes.c | 7 +- .../SOSCircle/SecureObjectSync/SOSRingUtils.c | 17 +- .../SOSCircle/SecureObjectSync/SOSRingUtils.h | 5 + .../SecureObjectSync/SOSSysdiagnose.c | 113 +- .../SOSCircle/SecureObjectSync/SOSTransport.c | 125 +- .../SOSCircle/SecureObjectSync/SOSTransport.h | 4 +- .../SecureObjectSync/SOSTransportCircleKVS.c | 17 +- .../SecureObjectSync/SOSTransportMessage.c | 8 +- .../SecureObjectSync/SOSTransportMessageIDS.c | 202 +- .../SecureObjectSync/SOSTransportMessageIDS.h | 11 +- .../SecureObjectSync/SOSTransportMessageKVS.c | 14 +- OSX/sec/SOSCircle/SecureObjectSync/SOSTypes.h | 3 +- .../SecureObjectSync/SOSUserKeygen.c | 15 +- OSX/sec/SOSCircle/SecureObjectSync/SOSViews.c | 243 +- .../SecureObjectSync/SOSViews.exp-in | 26 + OSX/sec/SOSCircle/SecureObjectSync/SOSViews.h | 18 +- .../SOSCircle/SecureObjectSync/ViewList.list | 40 + .../SOSCircle/Tool/NSFileHandle+Formatting.h | 21 + .../SOSCircle/Tool/NSFileHandle+Formatting.m | 30 + OSX/sec/SOSCircle/Tool/keychain_log.c | 104 +- OSX/sec/SOSCircle/Tool/keychain_sync.c | 188 +- OSX/sec/SOSCircle/Tool/keychain_sync.h | 2 +- OSX/sec/SOSCircle/Tool/keychain_sync_test.h | 15 + OSX/sec/SOSCircle/Tool/keychain_sync_test.m | 90 + OSX/sec/SOSCircle/Tool/secToolFileIO.c | 1 - OSX/sec/SOSCircle/Tool/secToolFileIO.h | 1 - OSX/sec/SOSCircle/Tool/secViewDisplay.c | 148 + .../SOSCircle/Tool/secViewDisplay.h} | 28 +- OSX/sec/SOSCircle/Tool/syncbackup.c | 87 + OSX/sec/SOSCircle/Tool/syncbackup.h | 40 + .../AppleBaselineEscrowCertificates.h | 95 +- .../Regressions/Security_regressions.h | 55 +- .../Regressions/secitem/si-12-item-stress.c | 4 +- .../Regressions/secitem/si-13-item-system.m | 2 +- .../Regressions/secitem/si-15-certificate.c | 20 +- .../secitem/si-15-delete-access-group.m | 88 + .../secitem/si-16-ec-certificate.c | 13 +- .../secitem/si-17-item-system-bluetooth.m | 2 +- .../secitem/si-20-sectrust-activation.c | 942 -- .../Regressions/secitem/si-20-sectrust.c | 206 +- .../Regressions/secitem/si-20-sectrust.h | 84 + .../Regressions/secitem/si-21-sectrust-asr.c | 20 +- .../Regressions/secitem/si-22-sectrust-iap.c | 617 +- .../Regressions/secitem/si-22-sectrust-iap.h | 427 + .../Regressions/secitem/si-23-sectrust-ocsp.c | 4 +- .../secitem/si-24-sectrust-appleid.c | 29 - .../si-24-sectrust-digicert-malaysia.c | 4 +- .../secitem/si-24-sectrust-diginotar.c | 6 +- .../Regressions/secitem/si-24-sectrust-itms.c | 16 +- .../secitem/si-24-sectrust-mobileasset.c | 29 - .../Regressions/secitem/si-24-sectrust-nist.c | 4 +- .../secitem/si-24-sectrust-otatasking.c | 29 - ...st-shoebox.c => si-24-sectrust-passbook.c} | 281 +- .../si-25-sectrust-apple-authentication.c | 700 -- .../secitem/si-25-sectrust-ipsec-eap.c | 778 -- ...ning.c => si-26-sectrust-copyproperties.c} | 31 +- .../secitem/si-27-sectrust-exceptions.c | 194 +- .../secitem/si-28-sectrustsettings.c | 215 - .../secitem/si-28-sectrustsettings.h | 288 + .../secitem/si-28-sectrustsettings.m | 565 + .../secitem/si-29-sectrust-codesigning.c | 695 -- .../secitem/si-33-keychain-backup.c | 10 +- .../Regressions/secitem/si-40-seckey-custom.c | 15 +- .../Regressions/secitem/si-40-seckey.c | 718 +- .../Regressions/secitem/si-41-sececkey.c | 612 +- .../Security/Regressions/secitem/si-60-cms.c | 6 +- .../Regressions/secitem/si-66-smime.c | 4 +- .../secitem/si-67-sectrust-blacklist.c | 21 +- .../Regressions/secitem/si-69-keydesc.c | 4 +- .../secitem/si-70-sectrust-unified.c | 6 +- .../secitem/si-71-mobile-store-policy.c | 16 +- .../secitem/si-73-secpasswordgenerate.c | 1040 +- .../Regressions/secitem/si-74-OTAPKISigner.c | 12 +- .../secitem/si-75-AppleIDRecordSigning.c | 267 - .../secitem/si-76-shared-credentials.c | 4 +- .../secitem/si-79-smp-cert-policy.c | 410 - .../secitem/si-81-sectrust-appletv.c | 558 - .../secitem/si-81-sectrust-server-auth.c | 581 - .../Regressions/secitem/si-82-token-ag.c | 33 + .../secitem/si-83-seccertificate-sighashalg.c | 3 +- .../secitem/si-84-sectrust-atv-appsigning.c | 478 - .../secitem/si-85-sectrust-ssl-policy.c | 101 +- ...-eap-tls.h => si-85-sectrust-ssl-policy.h} | 71 +- .../secitem/si-86-sectrust-eap-tls.c | 69 - .../secitem/si-87-sectrust-name-constraints.c | 16 +- .../secitem/si-88-sectrust-vpnprofile.c | 113 - .../secitem/si-88-sectrust-vpnprofile.h | 450 - .../Security/Regressions/secitem/si-90-emcs.m | 6 - .../Regressions/secitem/si-91-sectrust-ast2.c | 105 - .../Regressions/secitem/si-91-sectrust-ast2.h | 265 - .../secitem/si-92-sectrust-homekit.c | 109 - .../secitem/si-92-sectrust-homekit.h | 409 - .../Regressions/secitem/si-95-cms-basic.c | 508 + .../Regressions/secitem/si-95-cms-basic.h | 1341 +++ .../secitem/si-97-sectrust-path-scoring.h | 685 ++ .../secitem/si-97-sectrust-path-scoring.m | 256 + .../secitem/si_77_SecAccessControl.c | 5 +- .../Regressions/vmdh/vmdh-41-example.c | 7 +- .../Regressions/vmdh/vmdh-42-example2.c | 7 +- OSX/sec/Security/SecAccessControl.c | 41 +- OSX/sec/Security/SecAccessControl.h | 33 +- OSX/sec/Security/SecBase.h | 1 + OSX/sec/Security/SecBasePriv.h | 1 - OSX/sec/Security/SecCFAllocator.c | 64 + .../sec/Security/SecCFAllocator.h | 25 +- OSX/sec/Security/SecCMS.c | 29 +- OSX/sec/Security/SecCMS.h | 8 +- OSX/sec/Security/SecCTKKey.c | 257 +- OSX/sec/Security/SecCTKKeyPriv.h | 2 +- OSX/sec/Security/SecCertificate.c | 738 +- OSX/sec/Security/SecCertificateInternal.h | 17 + OSX/sec/Security/SecCertificatePath.c | 343 +- OSX/sec/Security/SecCertificatePath.h | 18 +- OSX/sec/Security/SecCertificatePriv.h | 43 +- OSX/sec/Security/SecCertificateRequest.c | 2 +- OSX/sec/Security/SecDH.c | 28 +- OSX/sec/Security/SecDigest.c | 100 + OSX/sec/Security/SecECKey.c | 491 +- OSX/sec/Security/SecEMCS.m | 11 +- OSX/sec/Security/SecExports.exp-in | 399 +- OSX/sec/Security/SecFramework.c | 136 +- OSX/sec/Security/SecFrameworkStrings.h | 6 +- OSX/sec/Security/SecItem.c | 500 +- OSX/sec/Security/SecItem.h | 32 +- OSX/sec/Security/SecItemBackup.c | 19 + OSX/sec/Security/SecItemConstants.c | 30 +- OSX/sec/Security/SecItemInternal.h | 6 + OSX/sec/Security/SecItemPriv.h | 97 +- OSX/sec/Security/SecItemShim.h | 64 + OSX/sec/Security/SecKey.c | 1148 +- OSX/sec/Security/SecKey.h | 659 +- OSX/sec/Security/SecKeyAdaptors.c | 1217 ++ OSX/sec/Security/SecKeyInternal.h | 18 + OSX/sec/Security/SecKeyPriv.h | 114 +- OSX/sec/Security/SecOTRFullIdentity.c | 15 +- OSX/sec/Security/SecOTRIdentityPriv.h | 7 +- OSX/sec/Security/SecOTRPublicIdentity.c | 14 +- OSX/sec/Security/SecOTRSession.c | 34 +- OSX/sec/Security/SecOTRSession.h | 1 + OSX/sec/Security/SecOTRSessionAKE.c | 188 +- OSX/sec/Security/SecPasswordGenerate.c | 88 +- OSX/sec/Security/SecPasswordGenerate.h | 7 + OSX/sec/Security/SecPolicy.c | 1994 +++- OSX/sec/Security/SecPolicy.h | 26 +- OSX/sec/Security/SecPolicyInternal.h | 75 +- OSX/sec/Security/SecPolicyLeafCallbacks.c | 822 ++ OSX/sec/Security/SecPolicyPriv.h | 1156 +- OSX/sec/Security/SecRSAKey.c | 778 +- OSX/sec/Security/SecRandom.h | 2 + OSX/sec/Security/SecServerEncryptionSupport.c | 30 +- OSX/sec/Security/SecServerEncryptionSupport.h | 5 +- OSX/sec/Security/SecSharedCredential.c | 28 +- OSX/sec/Security/SecSharedCredential.h | 16 +- .../SecSignatureVerificationSupport.c | 119 + .../SecSignatureVerificationSupport.h | 22 + OSX/sec/Security/SecTrust.c | 661 +- OSX/sec/Security/SecTrust.h | 46 +- OSX/sec/Security/SecTrustInternal.h | 23 +- OSX/sec/Security/SecTrustPriv.h | 244 +- OSX/sec/Security/SecTrustSettings.c | 2 +- OSX/sec/Security/SecTrustSettings.h | 19 +- OSX/sec/Security/SecTrustSettingsPriv.h | 22 +- OSX/sec/Security/SecTrustStore.c | 151 +- OSX/sec/Security/SecTrustStore.h | 8 + OSX/sec/Security/Security.h | 4 +- OSX/sec/Security/SecuritydXPC.c | 21 +- OSX/sec/Security/Tool/SecurityCommands.h | 12 +- OSX/sec/Security/Tool/codesign.c | 1 + OSX/sec/Security/Tool/keychain_find.c | 2 + OSX/sec/Security/Tool/keychain_util.c | 8 +- OSX/sec/Security/Tool/scep.c | 19 +- OSX/sec/Security/Tool/show_certificates.c | 129 + OSX/sec/Security/Tool/verify_cert.c | 77 +- OSX/sec/Security/cssmapple.h | 4 + OSX/sec/SecurityTool/security.1 | 3 + OSX/sec/SecurityTool/whoami.m | 4 +- .../com.apple.security.swcagent.plist | 4 - OSX/sec/SharedWebCredential/swcagent.m | 120 +- OSX/sec/config/base.xcconfig | 3 +- OSX/sec/config/lib-arc-only.xcconfig | 2 +- OSX/sec/config/lib.xcconfig | 10 +- OSX/sec/config/release.xcconfig | 2 +- OSX/sec/ipc/client.c | 26 +- OSX/sec/ipc/com.apple.secd.plist | 2 +- OSX/sec/ipc/com.apple.securityd.plist | 6 +- OSX/sec/ipc/securityd_client.h | 35 +- OSX/sec/ipc/server.c | 884 +- OSX/sec/os_log/README_os_log_prefs.txt | 5 + OSX/sec/os_log/com.apple.securityd.plist | 35 + OSX/sec/sec.xcodeproj/project.pbxproj | 960 +- OSX/sec/securityd/OTATrustUtilities.c | 312 +- OSX/sec/securityd/OTATrustUtilities.h | 5 + .../securityd/Regressions/SOSAccountTesting.h | 186 +- .../Regressions/SOSTransportTestTransports.c | 203 +- .../Regressions/SOSTransportTestTransports.h | 17 +- .../Regressions/SecdTestKeychainUtilities.c | 20 + .../Regressions/SecdTestKeychainUtilities.h | 6 + OSX/sec/securityd/Regressions/secd-01-items.c | 1 + .../Regressions/secd-05-corrupted-items.m | 2 +- .../Regressions/secd-100-initialsync.c | 126 + .../Regressions/secd-130-other-peer-views.c | 186 + .../Regressions/secd-20-keychain_upgrade.m | 5 +- .../securityd/Regressions/secd-200-logstate.c | 209 + .../Regressions/secd-21-transmogrify.m | 16 +- .../Regressions/secd-31-keychain-bad.c | 2 +- .../Regressions/secd-31-keychain-unreadable.c | 2 +- .../Regressions/secd-33-keychain-ctk.c | 662 -- .../Regressions/secd-33-keychain-ctk.m | 1045 ++ .../securityd/Regressions/secd-49-manifests.c | 2 +- .../securityd/Regressions/secd-50-account.c | 2 +- .../Regressions/secd-51-account-inflate.c | 36 +- .../Regressions/secd-52-account-changed.c | 12 +- .../secd-52-offering-gencount-reset.c | 10 +- .../Regressions/secd-55-account-circle.c | 32 +- .../Regressions/secd-56-account-apply.c | 172 +- .../secd-57-1-account-last-standing.c | 169 + .../Regressions/secd-57-account-leave.c | 12 +- .../Regressions/secd-58-password-change.c | 4 +- .../Regressions/secd-59-account-cleanup.c | 6 +- .../secd-60-account-cloud-identity.c | 65 +- ...d-61-account-leave-not-in-kansas-anymore.c | 8 +- .../Regressions/secd-62-account-backup.c | 89 +- .../Regressions/secd-62-account-hsa-join.c | 11 +- .../secd-63-account-resurrection.c | 6 +- .../Regressions/secd-64-circlereset.c | 59 +- .../secd-65-account-retirement-reset.c | 4 +- .../Regressions/secd-70-engine-corrupt.c | 4 + .../Regressions/secd-70-otr-remote.c | 4 +- .../Regressions/secd-71-engine-save-sample1.h | 125 + .../Regressions/secd-71-engine-save.c | 148 + .../Regressions/secd-76-idstransport.c | 313 + .../Regressions/secd-80-views-basic.c | 53 +- .../Regressions/secd-81-item-acl-stress.c | 4 +- .../securityd/Regressions/secd-81-item-acl.c | 4 +- .../Regressions/secd-82-persistent-ref.c | 7 +- .../Regressions/secd-82-secproperties-basic.c | 2 +- .../Regressions/secd-83-item-match-policy.m | 229 + .../Regressions/secd-83-item-match-trusted.m | 51 + .../secd-83-item-match-valid-on-date.m | 68 + .../Regressions/secd-83-item-match.h | 10 + OSX/sec/securityd/Regressions/secd-90-hsa2.c | 143 +- .../Regressions/secd-95-escrow-persistence.c | 12 +- .../secd60-account-cloud-exposure.c | 23 +- .../Regressions/secd_77_ids_messaging.c | 299 + .../securityd/Regressions/secd_regressions.h | 14 +- OSX/sec/securityd/SOSCloudCircleServer.c | 821 +- OSX/sec/securityd/SOSCloudCircleServer.h | 14 + OSX/sec/securityd/SecCAIssuerCache.c | 12 +- OSX/sec/securityd/SecCAIssuerRequest.c | 32 +- OSX/sec/securityd/SecDbItem.c | 15 +- OSX/sec/securityd/SecDbItem.h | 3 +- OSX/sec/securityd/SecDbKeychainItem.c | 93 +- OSX/sec/securityd/SecDbKeychainItem.h | 2 +- OSX/sec/securityd/SecDbQuery.c | 69 +- OSX/sec/securityd/SecDbQuery.h | 10 + OSX/sec/securityd/SecItemBackupServer.c | 2 +- OSX/sec/securityd/SecItemDataSource.c | 139 +- OSX/sec/securityd/SecItemDb.c | 125 +- OSX/sec/securityd/SecItemDb.h | 6 +- OSX/sec/securityd/SecItemSchema.c | 215 +- OSX/sec/securityd/SecItemServer.c | 649 +- OSX/sec/securityd/SecItemServer.h | 8 + OSX/sec/securityd/SecOCSPCache.c | 3 + OSX/sec/securityd/SecOCSPResponse.c | 73 +- OSX/sec/securityd/SecOCSPResponse.h | 6 +- OSX/sec/securityd/SecPolicyServer.c | 2576 +++-- OSX/sec/securityd/SecPolicyServer.h | 12 +- OSX/sec/securityd/SecTrustServer.c | 495 +- OSX/sec/securityd/SecTrustServer.h | 24 +- OSX/sec/securityd/SecTrustStoreServer.c | 136 +- OSX/sec/securityd/SecTrustStoreServer.h | 3 + OSX/sec/securityd/asynchttp.c | 24 +- OSX/sec/securityd/asynchttp.h | 4 +- OSX/sec/securityd/entitlements.plist | 6 +- OSX/sec/securityd/nameconstraints.c | 2 +- OSX/sec/securityd/personalization.c | 28 + .../personalization.h} | 16 +- OSX/sec/securityd/spi.c | 15 + OSX/sectests/SecurityTests-Entitlements.plist | 4 + OSX/sectests/testlist.h | 5 +- OSX/security2/sub_commands.h | 2 + OSX/shared_regressions/shared_regressions.h | 41 +- .../AppleApplicationIntegration2CA.cer | Bin 0 -> 1052 bytes .../AppleApplicationIntegrationCA.cer | Bin .../AppleCodeSigningCA.cer | Bin 0 -> 1042 bytes .../AppleCorporateRootCA.cer | Bin 0 -> 949 bytes .../AppleCorporateVPNClientCA.cer | Bin 0 -> 1096 bytes .../AppleHomeKitServerCA.cer | Bin 0 -> 668 bytes .../AppleMacOSApplicationSigning.cer | Bin 0 -> 1370 bytes .../AppleRootCA.cer | Bin .../AppleRootG2.cer | Bin 0 -> 1430 bytes .../AppleRootG3.cer | Bin 0 -> 583 bytes .../AppleServerAuthentication.cer | Bin 0 -> 1020 bytes .../AppleSoftwareUpdateCA.cer | Bin 0 -> 1047 bytes .../AppleSystemIntegrationCAG3.cer | Bin 0 -> 751 bytes .../AppleWWDR-expired.cer | Bin .../AppleWWDR-test.cer | Bin .../AppleWWDR.cer | Bin 0 -> 1062 bytes .../AppleiPhoneCA.cer | Bin .../AppleiPhoneDeviceCA.cer | Bin 0 -> 877 bytes .../DeveloperIDCA.cer | Bin 0 -> 1032 bytes .../EntrustCAL1C.cer | Bin 0 -> 1270 bytes .../EntrustRootCA.cer | Bin 0 -> 1070 bytes .../FakeAppleRootCA.cer | Bin 0 -> 828 bytes .../InvalidEKUTest16.cer | Bin 0 -> 992 bytes .../PairingRootCA.cer | Bin 0 -> 689 bytes .../PinningPolicyTrustTest.plist | 2020 ++++ .../SSLTrustPolicyTestRootCertificate.cer | Bin 0 -> 987 bytes .../TestAppleGlobalRootCA.cer | Bin 0 -> 630 bytes .../TestAppleRootCA-ECC.cer | Bin 0 -> 555 bytes .../TestAppleRootCA.cer | Bin 0 -> 1232 bytes .../TestAppleRootCAG3.cer | Bin 0 -> 592 bytes .../TestAppleServerAuthentication.cer | Bin 0 -> 1043 bytes .../TestAppleSystemIntegration2CA.cer | Bin 0 -> 1070 bytes .../TestAppleSystemIntegrationCA-ECC.cer | Bin 0 -> 732 bytes .../TestAppleiPhoneDeviceCA.cer | Bin 0 -> 892 bytes .../WiFiIntermediateCA.cer | Bin 0 -> 1115 bytes .../WiFiRootCA.cer | Bin 0 -> 1038 bytes .../WrongPairingRootCA.cer | Bin 0 -> 689 bytes .../apn_legacy.cer | Bin 0 -> 1319 bytes .../apple_corp_vpn_client.cer | Bin 0 -> 1113 bytes .../appleid_authority.cer | Bin .../appleid_record_signing.cer | Bin 0 -> 1301 bytes .../asset_signing.cer | Bin .../si-20-sectrust-policies-data/ast2.cer | Bin 0 -> 1185 bytes .../configuration_profile.cer | Bin 0 -> 1367 bytes .../developer_id.cer | Bin 0 -> 1385 bytes .../developmentupdate.cer | Bin 0 -> 1332 bytes .../device_activation.cer | Bin 0 -> 875 bytes .../device_cert.cer | Bin 0 -> 835 bytes .../si-20-sectrust-policies-data/escrow.cer | Bin 0 -> 2962 bytes .../factory_device_cert.cer | Bin 0 -> 896 bytes .../si-20-sectrust-policies-data/fmip.cer | Bin 0 -> 2479 bytes .../generic_apple_server.cer | Bin 0 -> 1037 bytes .../si-20-sectrust-policies-data/gsa.cer | Bin 0 -> 1030 bytes .../si-20-sectrust-policies-data/homekit.cer | Bin 0 -> 792 bytes .../si-20-sectrust-policies-data/ids.cer | Bin 0 -> 1165 bytes .../ios_app_signing.cer | Bin 0 -> 903 bytes .../ios_provisioning_profile.cer | Bin 0 -> 1021 bytes .../ios_vpn_app_signing.cer | Bin 0 -> 925 bytes .../iphone_developer.cer | Bin 0 -> 1448 bytes .../si-20-sectrust-policies-data/ivpntest.cer | Bin 0 -> 1672 bytes .../ivpntestCA.cer | Bin 0 -> 1180 bytes .../mac_app_store_receipt.cer | Bin 0 -> 1408 bytes .../mac_app_store_receipt_badoid.cer | Bin 0 -> 1406 bytes .../mac_developer.cer | Bin 0 -> 1423 bytes .../osx_provisioning_profile.cer | Bin 0 -> 1334 bytes .../pairing_host_cert.cer | Bin 0 -> 702 bytes .../passbook_cardman.cer | Bin 0 -> 1525 bytes .../passbook_testcard.cer | Bin .../si-20-sectrust-policies-data/smp.cer | Bin 0 -> 714 bytes .../softwaresigning.cer | Bin 0 -> 1343 bytes .../softwareupdate.cer | Bin 0 -> 1328 bytes .../task_signing.cer | Bin .../test_ios_app_signing.cer | Bin 0 -> 1046 bytes .../test_ios_provisioning_profile.cer | Bin 0 -> 1031 bytes .../test_ipsec_gateway.cer | Bin 0 -> 807 bytes .../si-20-sectrust-policies-data/test_smp.cer | Bin 0 -> 712 bytes .../test_tvos_app_signing.cer | Bin 0 -> 1366 bytes .../tvos_app_signing.cer | Bin 0 -> 1379 bytes .../tvos_vpn_profile.cer | Bin 0 -> 1060 bytes .../si-20-sectrust-policies-data/ucrt.cer | Bin 0 -> 839 bytes .../ucrtTestIntermediate.cer | Bin 0 -> 499 bytes .../ucrtTestRootCA.cer | Bin 0 -> 551 bytes .../wifi_user.cer | Bin 0 -> 1305 bytes .../si-20-sectrust-policies.m | 425 + OSX/shared_regressions/si-44-seckey-ec.m | 81 + OSX/shared_regressions/si-44-seckey-gen.m | 94 + OSX/shared_regressions/si-44-seckey-ies.m | 289 + OSX/shared_regressions/si-44-seckey-rsa.m | 153 + .../si-82-sectrust-ct-certs.h | 1029 -- .../si-82-sectrust-ct-data/CA_alpha.crt | Bin 0 -> 715 bytes .../si-82-sectrust-ct-data/CA_beta.crt | Bin 0 -> 715 bytes .../si-82-sectrust-ct-data/CTlogs.plist | 198 + .../bad_hash_ocsp_response.bin | Bin 0 -> 374 bytes .../digicert_sha2_ev_server_ca.crt | Bin 0 -> 1210 bytes .../invalid_ocsp_response.bin | 2 + .../si-82-sectrust-ct-data/pilot_3055998.crt | Bin 0 -> 1534 bytes .../pilot_3055998_issuer.crt | Bin 0 -> 1290 bytes .../si-82-sectrust-ct-data/serverA.crt | Bin 0 -> 744 bytes .../serverA_proof_Alfa_3.bin | Bin 0 -> 118 bytes .../serverA_proof_Bravo_3.bin | Bin 0 -> 118 bytes .../si-82-sectrust-ct-data/serverD.crt | Bin 0 -> 744 bytes .../si-82-sectrust-ct-data/serverD_proof.bin | Bin 0 -> 117 bytes .../si-82-sectrust-ct-data/serverF.crt | Bin 0 -> 887 bytes .../si-82-sectrust-ct-data/server_1601.crt | Bin 0 -> 1008 bytes .../si-82-sectrust-ct-data/server_1603.crt | Bin 0 -> 1011 bytes .../si-82-sectrust-ct-data/server_1604.crt | Bin 0 -> 1132 bytes .../si-82-sectrust-ct-data/server_1701.crt | Bin 0 -> 1133 bytes .../si-82-sectrust-ct-data/server_1704.crt | Bin 0 -> 1133 bytes .../si-82-sectrust-ct-data/server_1705.crt | Bin 0 -> 1253 bytes .../si-82-sectrust-ct-data/server_1801.crt | Bin 0 -> 1251 bytes .../si-82-sectrust-ct-data/server_1804.crt | Bin 0 -> 1252 bytes .../si-82-sectrust-ct-data/server_1805.crt | Bin 0 -> 1375 bytes .../si-82-sectrust-ct-data/server_2001.crt | Bin 0 -> 1372 bytes .../valid_ocsp_response.bin | Bin 0 -> 374 bytes .../whitelist_00008013.crt | Bin 0 -> 1464 bytes .../whitelist_00008013_issuer.crt | Bin 0 -> 1236 bytes .../whitelist_5555bc4f.crt | Bin 0 -> 1594 bytes .../whitelist_5555bc4f_issuer.crt | Bin 0 -> 1210 bytes .../whitelist_aaaae152.crt | Bin 0 -> 1520 bytes .../whitelist_fff9b5f6.crt | Bin 0 -> 1353 bytes .../whitelist_fff9b5f6_issuer.crt | Bin 0 -> 1327 bytes .../www_digicert_com_2015.crt | Bin 0 -> 2144 bytes .../www_digicert_com_2016.crt | Bin 0 -> 2297 bytes .../si-82-sectrust-ct-data/www_paypal_com.crt | Bin 0 -> 1548 bytes .../www_paypal_com_issuer.crt | Bin 0 -> 1512 bytes OSX/shared_regressions/si-82-sectrust-ct.c | 1300 --- OSX/shared_regressions/si-82-sectrust-ct.m | 381 + OSX/tlsnke/README.tlsnke | 3 - OSX/tlsnke/tlsnke.xcodeproj/project.pbxproj | 611 - .../contents.xcworkspacedata | 7 - OSX/tlsnke/tlsnke/tlsnke.h | 104 - OSX/tlsnke/tlsnketest/cert-1.h | 66 - OSX/tlsnke/tlsnketest/dtls_client.c | 276 - OSX/tlsnke/tlsnketest/identity-1.h | 151 - OSX/tlsnke/tlsnketest/main.c | 295 - OSX/tlsnke/tlsnketest/privkey-1.h | 54 - OSX/tlsnke/tlsnketest/ssl-utils.c | 123 - OSX/tlsnke/tlsnketest/st_test.c | 759 -- OSX/tlsnke/tlsnketest/tlssocket.c | 344 - OSX/tlsnke/tlsnketest/tlssocket.h | 59 - .../SecTrustOSXEntryPoints.h} | 47 +- OSX/trustd/com.apple.trustd.agent.plist | 4 - OSX/trustd/entitlements.plist | 12 + OSX/trustd/trustd-Info.plist | 2 +- OSX/utilities/Regressions/su-07-debugging.c | 102 +- OSX/utilities/Regressions/su-16-cfdate-der.c | 6 +- .../Regressions/su-41-secdb-stress.c | 2 + OSX/utilities/config/lib.xcconfig | 4 + OSX/utilities/src/SecAKSWrappers.c | 9 +- OSX/utilities/src/SecAKSWrappers.h | 1 - OSX/utilities/src/SecAppleAnchor.c | 583 +- OSX/utilities/src/SecAppleAnchorPriv.h | 28 +- OSX/utilities/src/SecCFError.c | 3 +- OSX/utilities/src/SecCFWrappers.c | 102 +- OSX/utilities/src/SecCFWrappers.h | 177 +- OSX/utilities/src/SecDb.c | 268 +- OSX/utilities/src/SecDb.h | 4 +- OSX/utilities/src/SecFileLocations.c | 38 +- OSX/utilities/src/SecFileLocations.h | 9 +- OSX/utilities/src/SecInternalRelease.c | 30 +- OSX/utilities/src/SecInternalReleasePriv.h | 27 +- OSX/utilities/src/SecMeta.h | 2 +- OSX/utilities/src/SecdUsage.c | 0 OSX/utilities/src/cloud_keychain_diagnose.c | 1252 --- OSX/utilities/src/debugging.c | 318 +- OSX/utilities/src/debugging.h | 155 +- OSX/utilities/src/der_date.c | 2 +- OSX/utilities/src/fileIo.c | 15 +- OSX/utilities/src/fileIo.h | 7 +- OSX/utilities/src/iCloudKeychainTrace.h | 8 +- OSX/utilities/src/iOSforOSX-SecAttr.c | 2 + OSX/utilities/src/simulate_crash.c | 25 + .../utilities.xcodeproj/project.pbxproj | 34 +- OTAPKIAssetTool/OTAPKIAssetTool.xcconfig | 4 +- README | 3 +- RegressionTests/Security.plist | 41 +- RegressionTests/Security_edumode.plist | 6 - RegressionTests/secbackuptest/secbackuptest.m | 41 +- .../secitemfunctionality.entitlements | 11 + .../secitemfunctionality.m | 554 + .../secitemnotifications.entitlements | 10 + .../secitemnotifications.m | 71 + .../secitemstresstest.entitlements | 11 + .../secitemstresstest/secitemstresstest.m | 246 + Security-Info.plist | 4 +- Security.exp-in | 12 +- Security.xcodeproj/project.pbxproj | 9916 ++++++++--------- .../xcschemes/Security_executables.xcscheme | 87 - .../xcschemes/Security_frameworks.xcscheme | 87 - .../xcschemes/Security_temporary_UI.xcscheme | 87 - .../{Debug.xcscheme => ios - Debug.xcscheme} | 127 +- ...elease.xcscheme => ios - Release.xcscheme} | 62 +- ...ests.xcscheme => ios - secdtests.xcscheme} | 20 +- .../xcshareddata/xcschemes/phase1.xcscheme | 87 - .../xcshareddata/xcschemes/phase2.xcscheme | 87 - SecurityFeatures/CopyHeaders.sh | 13 + SecurityFeatures/ExternalProject.sh | 14 + SecurityFeatures/OSX/SecurityFeatures.h | 35 + SecurityFeatures/README.txt | 18 + .../iOS/SecurityFeatures.h | 18 +- .../Default-568h@2x.png | Bin .../Invalid-asset_signing.crt | Bin 1009 -> 0 bytes SecurityTests/SecurityDevTests-Info.plist | 8 +- .../SecurityTests-Entitlements.plist | 6 +- SecurityTests/SecurityTests-Info.plist | 8 +- .../AppleRootCertificate.crt | Bin 1215 -> 0 bytes .../Invalid-task_signing.crt | Bin 1000 -> 0 bytes .../mobileasset-certs/asset_signing.crt | Bin 1009 -> 0 bytes .../mobileasset-certs/iPhoneCACert.crt | Bin 1015 -> 0 bytes .../regressions/kc/kc-05-retain-release.c | 36 - .../regressions/kc/kc-10-unlock-noui.c | 37 - .../regressions/kc/kc-22-key-symmetric.c | 133 - .../Apple TEST RootCertificate.crt | Bin 1244 -> 0 bytes .../shoebox-certs/AppleRootCertificate.crt | Bin 1215 -> 0 bytes .../InvalidWildcardTest27Test28.cer | Bin 0 -> 991 bytes .../InvalidWildcardTest30.cer | Bin 0 -> 979 bytes .../InvalidWildcardTest31.cer | Bin 0 -> 981 bytes .../InvalidWildcardTest32.cer | Bin 0 -> 983 bytes .../InvalidWildcardTest33.cer | Bin 0 -> 980 bytes .../InvalidWildcardTest34.cer | Bin 0 -> 980 bytes .../ssl-policy-certs/SSLTrustPolicyTest.plist | 107 +- .../ssl-policy-certs/TestDescriptions.txt | 119 +- SecurityTests/testmain.c | 1 - .../SecurityTool.xcodeproj/project.pbxproj | 83 +- SecurityTool/access_utils.c | 2 +- SecurityTool/authz.c | 18 +- SecurityTool/cmsutil.c | 10 +- SecurityTool/cmsutil.h | 2 +- SecurityTool/config/project.xcconfig | 5 +- SecurityTool/createFVMaster.c | 12 +- SecurityTool/db_commands.cpp | 2 +- SecurityTool/display_error_code.c | 4 +- SecurityTool/identity_find.c | 8 +- SecurityTool/identity_prefs.c | 6 +- SecurityTool/key_create.c | 2 +- SecurityTool/keychain_add.c | 146 +- SecurityTool/keychain_create.c | 4 +- SecurityTool/keychain_delete.c | 2 +- SecurityTool/keychain_export.c | 315 +- SecurityTool/keychain_export.h | 1 + SecurityTool/keychain_find.c | 274 +- SecurityTool/keychain_find.h | 4 + SecurityTool/keychain_import.c | 22 +- SecurityTool/keychain_list.c | 135 +- SecurityTool/keychain_list.h | 1 + SecurityTool/keychain_lock.c | 2 +- SecurityTool/keychain_recode.c | 2 +- SecurityTool/keychain_set_settings.c | 12 +- SecurityTool/keychain_show_info.c | 2 +- SecurityTool/keychain_unlock.c | 4 +- SecurityTool/keychain_utilities.c | 29 +- SecurityTool/keychain_utilities.h | 4 +- SecurityTool/leaks.c | 2 +- SecurityTool/readline.c | 23 +- SecurityTool/security.1 | 47 +- SecurityTool/security.c | 133 +- SecurityTool/{security.h => security_tool.h} | 0 SecurityTool/smartcards.h | 10 + SecurityTool/smartcards.m | 91 + SecurityTool/srCdsaUtils.cpp | 2 +- SecurityTool/sub_commands.h | 2 + SecurityTool/translocate.c | 261 + .../fileIo.h => SecurityTool/translocate.h | 29 +- SecurityTool/trust_settings_impexp.c | 10 +- SecurityTool/trusted_cert_add.c | 10 +- SecurityTool/trusted_cert_utils.c | 19 +- SecurityTool/verify_cert.c | 5 +- SecurityTool/verify_cert.h | 2 +- .../SharedWebCredentialViewService-Info.plist | 8 +- WHITEPAPER | 146 - asl/com.apple.securityd | 31 - ckcdiagnose/ckcdiagnose.sh | 12 +- codesign_wrapper/MISBase.h | 44 - codesign_wrapper/MISEntitlement.c | 100 - codesign_wrapper/MISEntitlement.h | 23 - codesign_wrapper/codesign.c | 276 - codesign_wrapper/codesign_wrapper.c | 1034 -- codesign_wrapper/codesign_wrapper.h | 87 - .../dtlsEcho => dtlsEcho}/README | 0 dtlsEcho/dtlsEchoClient.c | 421 + dtlsEcho/dtlsEchoServer.c | 436 + .../com.apple.icloudKeychainStats.plist | 19 - iCloudStat/main.c | 260 - libsecurity_smime/TODO | 9 - libsecurity_smime/lib/cmsasn1.c | 6 +- libsecurity_smime/lib/cmscinfo.c | 13 +- libsecurity_smime/lib/cmsdigdata.c | 6 + libsecurity_smime/lib/cmsencdata.c | 3 + libsecurity_smime/lib/cmslocal.h | 9 + libsecurity_smime/lib/cmspubkey.c | 583 +- libsecurity_smime/lib/cmsrecinfo.c | 102 +- libsecurity_smime/lib/cmssigdata.c | 4 + libsecurity_smime/lib/cmssiginfo.c | 11 +- libsecurity_smime/lib/cmstpriv.h | 2 +- libsecurity_smime/lib/cmsutil.c | 17 + libsecurity_smime/lib/secoid.c | 6 +- libsecurity_smime/lib/smimeutil.c | 6 + .../project.pbxproj | 103 +- ntlm/NtlmGenerator.c | 61 +- ntlm/NtlmGenerator.h | 4 +- ntlm/ntlmBlobPriv.c | 109 +- ntlm/ntlmBlobPriv.h | 17 +- resources/English.lproj/Certificate.strings | Bin 22712 -> 24718 bytes resources/English.lproj/CloudKeychain.strings | Bin 12608 -> 10030 bytes resources/English.lproj/OID.strings | Bin 211564 -> 212512 bytes resources/TrustedLogs.plist | 24 - sbr | 25 - secacltests/sec_acl_stress.c | 7 +- secdtests/secdtests-entitlements.plist | 6 + sectask/SecEntitlements.h | 8 + sectask/SecTask.c | 51 +- sectask/SecTask.h | 17 +- sectask/regressions/sectask-10-sectask.c | 19 +- securityd/config/project.xcconfig | 3 +- securityd/securityd.xcodeproj/project.pbxproj | 121 +- .../KeyStore/KeyStore-Info.plist | 6 +- .../project.pbxproj | 17 +- .../com.apple.securitydservice.sb | 5 +- .../securityd_service/main.c | 86 +- securityd/src/AuthorizationDBPlist.cpp | 416 - securityd/src/AuthorizationDBPlist.h | 83 - securityd/src/AuthorizationEngine.cpp | 366 - securityd/src/AuthorizationEngine.h | 103 - securityd/src/AuthorizationMechEval.cpp | 56 - securityd/src/AuthorizationMechEval.h | 69 - securityd/src/AuthorizationRule.cpp | 224 - securityd/src/AuthorizationRule.h | 161 - securityd/src/SharedMemoryServer.cpp | 33 +- securityd/src/SharedMemoryServer.h | 3 +- securityd/src/acl_keychain.cpp | 99 +- securityd/src/acl_keychain.h | 5 + securityd/src/acls.cpp | 73 +- securityd/src/acls.h | 8 +- securityd/src/agentquery.cpp | 267 +- securityd/src/agentquery.h | 24 +- securityd/src/auditevents.cpp | 2 +- securityd/src/authhost.cpp | 30 +- securityd/src/authhost.h | 12 +- securityd/src/authority.cpp | 319 - securityd/src/authority.h | 132 - securityd/src/ccaudit_extensions.cpp | 2 +- securityd/src/ccaudit_extensions.h | 2 +- securityd/src/child.cpp | 17 +- securityd/src/clientid.cpp | 92 +- securityd/src/clientid.h | 38 +- securityd/src/codesigdb.cpp | 77 +- securityd/src/codesigdb.h | 38 +- securityd/src/connection.cpp | 18 +- securityd/src/connection.h | 14 +- securityd/src/credential.cpp | 2 +- securityd/src/csproxy.cpp | 59 +- securityd/src/csproxy.h | 45 +- securityd/src/database.cpp | 79 +- securityd/src/database.h | 28 +- securityd/src/dbcrypto.cpp | 52 +- securityd/src/dbcrypto.h | 9 +- securityd/src/entropy.cpp | 6 +- securityd/src/kcdatabase.cpp | 452 +- securityd/src/kcdatabase.h | 55 +- securityd/src/kckey.cpp | 6 +- securityd/src/kckey.h | 2 - securityd/src/localkey.cpp | 4 +- securityd/src/main.cpp | 21 +- securityd/src/notifications.cpp | 27 +- securityd/src/pcscmonitor.cpp | 18 +- securityd/src/process.cpp | 77 +- securityd/src/process.h | 10 +- securityd/src/reader.cpp | 22 +- securityd/src/securityd.order | 105 +- securityd/src/server.cpp | 82 +- securityd/src/server.h | 25 +- securityd/src/session.cpp | 368 +- securityd/src/session.h | 74 +- securityd/src/structure.cpp | 2 +- securityd/src/tempdatabase.cpp | 4 +- securityd/src/token.cpp | 48 +- securityd/src/token.h | 2 - securityd/src/tokenaccess.cpp | 10 +- securityd/src/tokenacl.cpp | 2 +- securityd/src/tokencache.cpp | 21 +- securityd/src/tokend.cpp | 16 +- securityd/src/tokendatabase.cpp | 51 +- securityd/src/tokendatabase.h | 10 +- securityd/src/tokenkey.cpp | 2 +- securityd/src/transition.cpp | 401 +- spiralsink114.png | Bin 24752 -> 0 bytes spiralsink57.png | Bin 7978 -> 0 bytes sslViewer/SSLViewer.c | 6 +- sslViewer/ioSock.c | 3 +- sslViewer/sslAppUtils.cpp | 46 + sslViewer/sslAppUtils.h | 3 + sslViewer/sslServer.cpp | 2 +- sslViewer/sslViewer-entitlements.plist | 2 + xcconfig/Security.xcconfig | 10 + 1461 files changed, 97703 insertions(+), 64277 deletions(-) delete mode 100644 CloudKeychainProxy/CloudKeychainProxy.1 create mode 100644 IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.h create mode 100644 IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.m rename OSX/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h => IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.h (60%) create mode 100644 IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.m create mode 100644 IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.h create mode 100644 IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.m rename {OSX/sec/SOSCircle/IDSKeychainSyncingProxy => IDSKeychainSyncingProxy}/IDSPersistentState.h (96%) rename {OSX/sec/SOSCircle/IDSKeychainSyncingProxy => IDSKeychainSyncingProxy}/IDSPersistentState.m (96%) rename {OSX/sec/SOSCircle/IDSKeychainSyncingProxy => IDSKeychainSyncingProxy}/IDSProxy.h (75%) create mode 100644 IDSKeychainSyncingProxy/IDSProxy.m rename IDSKeychainSyncingProxy/{com.apple.security.idskeychainsyncingproxy.plist => com.apple.security.idskeychainsyncingproxy.ios.plist} (79%) rename OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist => IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.osx.plist (97%) rename {CloudKeychainProxy => IDSKeychainSyncingProxy}/en.lproj/InfoPlist.strings (100%) rename {OSX/sec/SOSCircle/IDSKeychainSyncingProxy => IDSKeychainSyncingProxy}/idskeychainsyncingproxy.m (68%) create mode 100644 KVSKeychainSyncingProxy/CKDAccount.h create mode 100644 KVSKeychainSyncingProxy/CKDKVSProxy.h create mode 100644 KVSKeychainSyncingProxy/CKDKVSProxy.m create mode 100644 KVSKeychainSyncingProxy/CKDKVSStore.h create mode 100644 KVSKeychainSyncingProxy/CKDKVSStore.m rename OSX/sec/SOSCircle/osxshim.c => KVSKeychainSyncingProxy/CKDPersistentState.h (68%) create mode 100644 KVSKeychainSyncingProxy/CKDPersistentState.m create mode 100644 KVSKeychainSyncingProxy/CKDSecuritydAccount.h create mode 100644 KVSKeychainSyncingProxy/CKDSecuritydAccount.m create mode 100644 KVSKeychainSyncingProxy/CKDStore.h rename {CloudKeychainProxy => KVSKeychainSyncingProxy}/CloudKeychainProxy-Info.plist (93%) rename {OSX/CloudKeychainProxy => KVSKeychainSyncingProxy}/cloudkeychain.entitlements.plist (96%) create mode 100644 KVSKeychainSyncingProxy/cloudkeychainproxy.m rename CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist => KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist (100%) rename OSX/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist => KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist (98%) rename Keychain_114x114.png => Keychain/Keychain_114x114.png (100%) rename Keychain_144x144.png => Keychain/Keychain_144x144.png (100%) rename Keychain_57x57.png => Keychain/Keychain_57x57.png (100%) rename Keychain_72x72.png => Keychain/Keychain_72x72.png (100%) create mode 100644 KeychainCircle/Info.plist create mode 100644 KeychainCircle/KCAESGCMDuplexSession.h create mode 100644 KeychainCircle/KCAESGCMDuplexSession.m create mode 100644 KeychainCircle/KCAccountKCCircleDelegate.h create mode 100644 KeychainCircle/KCAccountKCCircleDelegate.m create mode 100644 KeychainCircle/KCDer.h create mode 100644 KeychainCircle/KCDer.m create mode 100644 KeychainCircle/KCError.h create mode 100644 KeychainCircle/KCError.m create mode 100644 KeychainCircle/KCJoiningAcceptSession.m create mode 100644 KeychainCircle/KCJoiningMessages.h create mode 100644 KeychainCircle/KCJoiningMessages.m create mode 100644 KeychainCircle/KCJoiningRequestSession.m create mode 100644 KeychainCircle/KCJoiningSession.h create mode 100644 KeychainCircle/KCSRPContext.h create mode 100644 KeychainCircle/KCSRPContext.m create mode 100644 KeychainCircle/KeychainCircle.h create mode 100644 KeychainCircle/NSData+SecRandom.h create mode 100644 KeychainCircle/NSData+SecRandom.m create mode 100644 KeychainCircle/NSError+KCCreationHelpers.h create mode 100644 KeychainCircle/NSError+KCCreationHelpers.m create mode 100644 KeychainCircle/Tests/Info.plist create mode 100644 KeychainCircle/Tests/KCAESGCMTest.m create mode 100644 KeychainCircle/Tests/KCDerTest.m create mode 100644 KeychainCircle/Tests/KCJoiningSessionTest.m create mode 100644 KeychainCircle/Tests/KCSRPTests.m create mode 100644 KeychainCircle/Tests/KeychainCircle.plist create mode 100644 Modules/Security.iOS.modulemap create mode 100644 Modules/Security.macOS.modulemap rename OSX/Breadcrumb/{bc-10-knife-on-bread.c => bc-10-knife-on-bread.m} (53%) delete mode 100644 OSX/IDSKeychainSyncingProxy/com.apple.private.alloy.keychainsync.plist delete mode 100644 OSX/IDSKeychainSyncingProxy/en.lproj/InfoPlist.strings delete mode 100644 OSX/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist create mode 120000 OSX/Modules delete mode 100644 OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme delete mode 100644 OSX/OSX.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme create mode 100644 OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme rename OSX/OSX.xcodeproj/xcshareddata/xcschemes/{secdtests.xcscheme => osx - secdtests.xcscheme} (81%) rename OSX/OSX.xcodeproj/xcshareddata/xcschemes/{sectests.xcscheme => osx - sectests.xcscheme} (82%) rename OSX/{IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist => SecurityTestsOSX/Info.plist} (58%) create mode 100644 OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist create mode 100644 OSX/SecurityTestsOSX/main.m create mode 100644 OSX/SecurityTestsOSX/testlist.h delete mode 100644 OSX/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch delete mode 100644 OSX/lib/AppWorkaround.plist delete mode 100644 OSX/libsecurity_apple_csp/TODO delete mode 100644 OSX/libsecurity_apple_x509_cl/TODO create mode 100644 OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp create mode 100644 OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.h create mode 100644 OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp create mode 100644 OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.h create mode 100644 OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp create mode 100644 OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.h create mode 100644 OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp create mode 100644 OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.h create mode 100644 OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp create mode 100644 OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.h delete mode 100644 OSX/libsecurity_cdsa_plugin/lib/generator.cfg delete mode 100644 OSX/libsecurity_cdsa_plugin/lib/generator.mk delete mode 100644 OSX/libsecurity_cdsa_plugin/lib/generator.pl create mode 100644 OSX/libsecurity_cms/regressions/cms-trust-settings-test.c create mode 100644 OSX/libsecurity_cms/regressions/cms-trust-settings-test.h create mode 100644 OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp create mode 100644 OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp create mode 100644 OSX/libsecurity_keychain/lib/TokenLogin.cpp create mode 100644 OSX/libsecurity_keychain/lib/TokenLogin.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-01-keychain-creation.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-02-unlock-noui.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-03-keychain-list.c rename SecurityTests/regressions/kc/kc-12-status.c => OSX/libsecurity_keychain/regressions/kc-03-status.c (81%) mode change 100755 => 100644 rename SecurityTests/regressions/kc/kc-26-is-valid.c => OSX/libsecurity_keychain/regressions/kc-04-is-valid.c (68%) mode change 100755 => 100644 create mode 100644 OSX/libsecurity_keychain/regressions/kc-05-find-existing-items-locked.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-05-find-existing-items.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-06-cert-search-email.m rename SecurityTests/regressions/kc/kc-16-item-add-certificate.c => OSX/libsecurity_keychain/regressions/kc-10-item-add-certificate.c (95%) rename SecurityTests/regressions/kc/kc-15-item-add-generic.c => OSX/libsecurity_keychain/regressions/kc-10-item-add-generic.c (73%) mode change 100755 => 100644 rename SecurityTests/regressions/kc/kc-18-item-find-internet.c => OSX/libsecurity_keychain/regressions/kc-10-item-add-internet.c (77%) mode change 100755 => 100644 rename SecurityTests/regressions/kc/kc-17-item-find-key.c => OSX/libsecurity_keychain/regressions/kc-12-item-create-keypair.c (87%) mode change 100755 => 100644 create mode 100644 OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric-and-use.m create mode 100644 OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-15-item-update-label-skimaad.m create mode 100644 OSX/libsecurity_keychain/regressions/kc-15-key-update-valueref.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-16-item-update-password.c rename SecurityTests/regressions/kc/kc-51-testSecItemFind.c => OSX/libsecurity_keychain/regressions/kc-18-find-combined.c (59%) rename {SecurityTests/regressions/kc => OSX/libsecurity_keychain/regressions}/kc-19-item-copy-internet.c (63%) mode change 100755 => 100644 create mode 100644 OSX/libsecurity_keychain/regressions/kc-20-identity-find-stress.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-20-identity-key-attributes.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-20-identity-persistent-refs.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-20-item-find-stress.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-20-key-find-stress.c rename {SecurityTests/regressions/kc => OSX/libsecurity_keychain/regressions}/kc-21-item-use-callback.c (54%) create mode 100644 OSX/libsecurity_keychain/regressions/kc-21-item-xattrs.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-23-key-export-symmetric.m create mode 100644 OSX/libsecurity_keychain/regressions/kc-24-key-copy-keychains.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-26-key-import-public.m create mode 100644 OSX/libsecurity_keychain/regressions/kc-27-key-non-extractable.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-28-cert-sign.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-28-p12-import.m delete mode 100644 OSX/libsecurity_keychain/regressions/kc-40-seckey.c create mode 100644 OSX/libsecurity_keychain/regressions/kc-40-seckey.m rename OSX/libsecurity_keychain/regressions/{kc-41-sececkey.c => kc-41-sececkey.m} (83%) create mode 100644 OSX/libsecurity_keychain/regressions/kc-43-seckey-interop.m create mode 100644 OSX/libsecurity_keychain/regressions/kc-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-identity-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-item-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-key-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-keychain-file-helpers.h delete mode 100644 OSX/libsecurity_smime/TODO create mode 100644 OSX/libsecurity_smime/regressions/cms-01-basic.c create mode 100644 OSX/libsecurity_smime/regressions/cms-01-basic.h delete mode 100644 OSX/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c delete mode 100644 OSX/libsecurity_ssl/dtlsEcho/dtlsEchoServer.c delete mode 100644 OSX/libsecurity_ssl/lib/appleSession.c delete mode 100644 OSX/libsecurity_ssl/lib/sslUtils.c delete mode 100644 OSX/libsecurity_ssl/lib/sslUtils.h create mode 100644 OSX/libsecurity_ssl/regressions/ssl-56-renegotiate.c delete mode 100644 OSX/libsecurity_ssl/sslViewer/fileIo.c delete mode 100644 OSX/libsecurity_ssl/sslViewer/ioSock.c delete mode 100644 OSX/libsecurity_ssl/sslViewer/ioSock.h delete mode 100644 OSX/libsecurity_ssl/sslViewer/printCert.c delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslAppUtils.cpp delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslAppUtils.h delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslServer.1 delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslServer.cpp delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslViewer.1 delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslViewer.cpp delete mode 100644 OSX/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocate.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocate.h create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateDANotification.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateDANotification.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateInterface.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp create mode 100644 OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.hpp create mode 100644 OSX/libsecurity_translocate/lib/security_translocate.exp create mode 100644 OSX/libsecurity_translocate/libsecurity_translocate.xcodeproj/project.pbxproj create mode 100644 OSX/libsecurity_utilities/lib/FileLockTransaction.cpp create mode 100644 OSX/libsecurity_utilities/lib/FileLockTransaction.h rename OSX/{libsecurity_ssl/lib/appleSession.h => libsecurity_utilities/lib/casts.h} (55%) delete mode 100644 OSX/libsecurity_utilities/lib/debugging.cpp mode change 100644 => 120000 OSX/libsecurity_utilities/lib/debugging.h create mode 100644 OSX/sec/SOSCircle/CKBridge/SOSCloudKeychainLogging.c create mode 100644 OSX/sec/SOSCircle/CKBridge/SOSCloudKeychainLogging.h delete mode 100644 OSX/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.m delete mode 100644 OSX/sec/SOSCircle/CloudKeychainProxy/cloudkeychain.entitlements.plist delete mode 100644 OSX/sec/SOSCircle/CloudKeychainProxy/en.lproj/InfoPlist.strings delete mode 100644 OSX/sec/SOSCircle/Empty.c delete mode 100644 OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.m delete mode 100644 OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist delete mode 100644 OSX/sec/SOSCircle/Regressions/CKDKeyValueStore.h delete mode 100644 OSX/sec/SOSCircle/Regressions/CKDKeyValueStore.m create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSAccountLog.c create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSAccountLog.h create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSAccountTransaction.c create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSAccountTransaction.h create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSAccountViewSync.c delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSForerunnerSession.c delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSForerunnerSession.h create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSPersist.h create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSViews.exp-in create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/ViewList.list create mode 100644 OSX/sec/SOSCircle/Tool/NSFileHandle+Formatting.h create mode 100644 OSX/sec/SOSCircle/Tool/NSFileHandle+Formatting.m create mode 100644 OSX/sec/SOSCircle/Tool/keychain_sync_test.h create mode 100644 OSX/sec/SOSCircle/Tool/keychain_sync_test.m create mode 100644 OSX/sec/SOSCircle/Tool/secViewDisplay.c rename OSX/{tlsnke/tlsnketest/ssl-utils.h => sec/SOSCircle/Tool/secViewDisplay.h} (71%) create mode 100644 OSX/sec/SOSCircle/Tool/syncbackup.c create mode 100644 OSX/sec/SOSCircle/Tool/syncbackup.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-15-delete-access-group.m delete mode 100644 OSX/sec/Security/Regressions/secitem/si-20-sectrust-activation.c create mode 100644 OSX/sec/Security/Regressions/secitem/si-22-sectrust-iap.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-24-sectrust-appleid.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-24-sectrust-mobileasset.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-24-sectrust-otatasking.c rename OSX/sec/Security/Regressions/secitem/{si-24-sectrust-shoebox.c => si-24-sectrust-passbook.c} (73%) delete mode 100644 OSX/sec/Security/Regressions/secitem/si-25-sectrust-apple-authentication.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-25-sectrust-ipsec-eap.c rename OSX/sec/Security/Regressions/secitem/{si-26-applicationsigning.c => si-26-sectrust-copyproperties.c} (97%) delete mode 100644 OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.c create mode 100644 OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-28-sectrustsettings.m delete mode 100644 OSX/sec/Security/Regressions/secitem/si-29-sectrust-codesigning.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-75-AppleIDRecordSigning.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-79-smp-cert-policy.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-81-sectrust-appletv.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-81-sectrust-server-auth.c create mode 100644 OSX/sec/Security/Regressions/secitem/si-82-token-ag.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-84-sectrust-atv-appsigning.c rename OSX/sec/Security/Regressions/secitem/{si-86-sectrust-eap-tls.h => si-85-sectrust-ssl-policy.h} (53%) delete mode 100644 OSX/sec/Security/Regressions/secitem/si-86-sectrust-eap-tls.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.h delete mode 100644 OSX/sec/Security/Regressions/secitem/si-92-sectrust-homekit.c delete mode 100644 OSX/sec/Security/Regressions/secitem/si-92-sectrust-homekit.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-95-cms-basic.c create mode 100644 OSX/sec/Security/Regressions/secitem/si-95-cms-basic.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-97-sectrust-path-scoring.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-97-sectrust-path-scoring.m create mode 100644 OSX/sec/Security/SecCFAllocator.c rename codesign_wrapper/codesign.h => OSX/sec/Security/SecCFAllocator.h (72%) create mode 100644 OSX/sec/Security/SecDigest.c create mode 100644 OSX/sec/Security/SecItemShim.h create mode 100644 OSX/sec/Security/SecKeyAdaptors.c create mode 100644 OSX/sec/Security/SecPolicyLeafCallbacks.c create mode 100644 OSX/sec/Security/SecSignatureVerificationSupport.c create mode 100644 OSX/sec/Security/SecSignatureVerificationSupport.h create mode 100644 OSX/sec/os_log/README_os_log_prefs.txt create mode 100644 OSX/sec/os_log/com.apple.securityd.plist create mode 100644 OSX/sec/securityd/Regressions/secd-100-initialsync.c create mode 100644 OSX/sec/securityd/Regressions/secd-130-other-peer-views.c create mode 100644 OSX/sec/securityd/Regressions/secd-200-logstate.c delete mode 100644 OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c create mode 100644 OSX/sec/securityd/Regressions/secd-33-keychain-ctk.m create mode 100644 OSX/sec/securityd/Regressions/secd-57-1-account-last-standing.c create mode 100644 OSX/sec/securityd/Regressions/secd-71-engine-save-sample1.h create mode 100644 OSX/sec/securityd/Regressions/secd-71-engine-save.c create mode 100644 OSX/sec/securityd/Regressions/secd-76-idstransport.c create mode 100644 OSX/sec/securityd/Regressions/secd-83-item-match-policy.m create mode 100644 OSX/sec/securityd/Regressions/secd-83-item-match-trusted.m create mode 100644 OSX/sec/securityd/Regressions/secd-83-item-match-valid-on-date.m create mode 100644 OSX/sec/securityd/Regressions/secd-83-item-match.h create mode 100644 OSX/sec/securityd/Regressions/secd_77_ids_messaging.c create mode 100644 OSX/sec/securityd/personalization.c rename OSX/sec/{SOSCircle/IDSKeychainSyncingProxy/idksmain.m => securityd/personalization.h} (77%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleApplicationIntegration2CA.cer rename SecurityTests/AppleID-certs/Apple Application Integration Certification Authority Cert.crt => OSX/shared_regressions/si-20-sectrust-policies-data/AppleApplicationIntegrationCA.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleCodeSigningCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleCorporateRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleCorporateVPNClientCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleHomeKitServerCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleMacOSApplicationSigning.cer rename SecurityTests/AppleID-certs/AppleRootCertificate.crt => OSX/shared_regressions/si-20-sectrust-policies-data/AppleRootCA.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleRootG2.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleRootG3.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleServerAuthentication.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleSoftwareUpdateCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleSystemIntegrationCAG3.cer rename SecurityTests/shoebox-certs/Apple Worldwide Developer Relations Certification Authority Cert.crt => OSX/shared_regressions/si-20-sectrust-policies-data/AppleWWDR-expired.cer (100%) rename SecurityTests/shoebox-certs/Apple Worldwide Developer Relations Certification Authority TEST Cert.crt => OSX/shared_regressions/si-20-sectrust-policies-data/AppleWWDR-test.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleWWDR.cer rename SecurityTests/AppleID-certs/iPhoneCACert.crt => OSX/shared_regressions/si-20-sectrust-policies-data/AppleiPhoneCA.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/AppleiPhoneDeviceCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/DeveloperIDCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/EntrustCAL1C.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/EntrustRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/FakeAppleRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/InvalidEKUTest16.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/PairingRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/PinningPolicyTrustTest.plist create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/SSLTrustPolicyTestRootCertificate.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleGlobalRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleRootCA-ECC.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleRootCAG3.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleServerAuthentication.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleSystemIntegration2CA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleSystemIntegrationCA-ECC.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/TestAppleiPhoneDeviceCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/WiFiIntermediateCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/WiFiRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/WrongPairingRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/apn_legacy.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/apple_corp_vpn_client.cer rename SecurityTests/AppleID-certs/Apple Production ShareServices-7130767241416543643077536561487847634e4d6f773d3d.crt => OSX/shared_regressions/si-20-sectrust-policies-data/appleid_authority.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/appleid_record_signing.cer rename SecurityTests/AppleID-certs/Invalid-asset_signing.crt => OSX/shared_regressions/si-20-sectrust-policies-data/asset_signing.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ast2.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/configuration_profile.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/developer_id.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/developmentupdate.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/device_activation.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/device_cert.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/escrow.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/factory_device_cert.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/fmip.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/generic_apple_server.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/gsa.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/homekit.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ids.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ios_app_signing.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ios_provisioning_profile.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ios_vpn_app_signing.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/iphone_developer.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ivpntest.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ivpntestCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/mac_app_store_receipt.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/mac_app_store_receipt_badoid.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/mac_developer.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/osx_provisioning_profile.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/pairing_host_cert.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/passbook_cardman.cer rename SecurityTests/shoebox-certs/Invalid.com.apple.testcard.crt => OSX/shared_regressions/si-20-sectrust-policies-data/passbook_testcard.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/smp.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/softwaresigning.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/softwareupdate.cer rename SecurityTests/OTATasking-certs/task_signing.crt => OSX/shared_regressions/si-20-sectrust-policies-data/task_signing.cer (100%) create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_ios_app_signing.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_ios_provisioning_profile.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_ipsec_gateway.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_smp.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/test_tvos_app_signing.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/tvos_app_signing.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/tvos_vpn_profile.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ucrt.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ucrtTestIntermediate.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/ucrtTestRootCA.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies-data/wifi_user.cer create mode 100644 OSX/shared_regressions/si-20-sectrust-policies.m create mode 100644 OSX/shared_regressions/si-44-seckey-ec.m create mode 100644 OSX/shared_regressions/si-44-seckey-gen.m create mode 100644 OSX/shared_regressions/si-44-seckey-ies.m create mode 100644 OSX/shared_regressions/si-44-seckey-rsa.m delete mode 100644 OSX/shared_regressions/si-82-sectrust-ct-certs.h create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/CA_alpha.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/CA_beta.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/CTlogs.plist create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/bad_hash_ocsp_response.bin create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/digicert_sha2_ev_server_ca.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/invalid_ocsp_response.bin create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/pilot_3055998.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/pilot_3055998_issuer.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/serverA.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/serverA_proof_Alfa_3.bin create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/serverA_proof_Bravo_3.bin create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/serverD.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/serverD_proof.bin create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/serverF.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1601.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1603.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1604.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1701.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1704.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1705.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1801.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1804.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_1805.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/server_2001.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/valid_ocsp_response.bin create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_00008013.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_00008013_issuer.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_5555bc4f.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_5555bc4f_issuer.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_aaaae152.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_fff9b5f6.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/whitelist_fff9b5f6_issuer.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/www_digicert_com_2015.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/www_digicert_com_2016.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/www_paypal_com.crt create mode 100644 OSX/shared_regressions/si-82-sectrust-ct-data/www_paypal_com_issuer.crt delete mode 100644 OSX/shared_regressions/si-82-sectrust-ct.c create mode 100644 OSX/shared_regressions/si-82-sectrust-ct.m delete mode 100644 OSX/tlsnke/README.tlsnke delete mode 100644 OSX/tlsnke/tlsnke.xcodeproj/project.pbxproj delete mode 100644 OSX/tlsnke/tlsnke.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 OSX/tlsnke/tlsnke/tlsnke.h delete mode 100644 OSX/tlsnke/tlsnketest/cert-1.h delete mode 100644 OSX/tlsnke/tlsnketest/dtls_client.c delete mode 100644 OSX/tlsnke/tlsnketest/identity-1.h delete mode 100644 OSX/tlsnke/tlsnketest/main.c delete mode 100644 OSX/tlsnke/tlsnketest/privkey-1.h delete mode 100644 OSX/tlsnke/tlsnketest/ssl-utils.c delete mode 100644 OSX/tlsnke/tlsnketest/st_test.c delete mode 100644 OSX/tlsnke/tlsnketest/tlssocket.c delete mode 100644 OSX/tlsnke/tlsnketest/tlssocket.h rename OSX/{libsecurity_ssl/sslViewer/printCert.h => trustd/SecTrustOSXEntryPoints.h} (50%) create mode 100644 OSX/trustd/entitlements.plist delete mode 100644 OSX/utilities/src/SecdUsage.c delete mode 100644 OSX/utilities/src/cloud_keychain_diagnose.c create mode 100644 RegressionTests/secitemfunctionality/secitemfunctionality.entitlements create mode 100644 RegressionTests/secitemfunctionality/secitemfunctionality.m create mode 100644 RegressionTests/secitemnotifications/secitemnotifications.entitlements create mode 100644 RegressionTests/secitemnotifications/secitemnotifications.m create mode 100644 RegressionTests/secitemstresstest/secitemstresstest.entitlements create mode 100644 RegressionTests/secitemstresstest/secitemstresstest.m delete mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Security_executables.xcscheme delete mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Security_frameworks.xcscheme delete mode 100644 Security.xcodeproj/xcshareddata/xcschemes/Security_temporary_UI.xcscheme rename Security.xcodeproj/xcshareddata/xcschemes/{Debug.xcscheme => ios - Debug.xcscheme} (93%) rename Security.xcodeproj/xcshareddata/xcschemes/{Release.xcscheme => ios - Release.xcscheme} (93%) rename Security.xcodeproj/xcshareddata/xcschemes/{secdtests.xcscheme => ios - secdtests.xcscheme} (94%) delete mode 100644 Security.xcodeproj/xcshareddata/xcschemes/phase1.xcscheme delete mode 100644 Security.xcodeproj/xcshareddata/xcschemes/phase2.xcscheme create mode 100755 SecurityFeatures/CopyHeaders.sh create mode 100755 SecurityFeatures/ExternalProject.sh create mode 100644 SecurityFeatures/OSX/SecurityFeatures.h create mode 100644 SecurityFeatures/README.txt rename IDSKeychainSyncingProxy/idksmain.m => SecurityFeatures/iOS/SecurityFeatures.h (74%) rename Default-568h@2x.png => SecurityTests/Default-568h@2x.png (100%) delete mode 100644 SecurityTests/OTATasking-certs/Invalid-asset_signing.crt delete mode 100644 SecurityTests/mobileasset-certs/AppleRootCertificate.crt delete mode 100644 SecurityTests/mobileasset-certs/Invalid-task_signing.crt delete mode 100644 SecurityTests/mobileasset-certs/asset_signing.crt delete mode 100644 SecurityTests/mobileasset-certs/iPhoneCACert.crt delete mode 100755 SecurityTests/regressions/kc/kc-05-retain-release.c delete mode 100755 SecurityTests/regressions/kc/kc-10-unlock-noui.c delete mode 100755 SecurityTests/regressions/kc/kc-22-key-symmetric.c delete mode 100644 SecurityTests/shoebox-certs/Apple TEST RootCertificate.crt delete mode 100644 SecurityTests/shoebox-certs/AppleRootCertificate.crt create mode 100644 SecurityTests/ssl-policy-certs/InvalidWildcardTest27Test28.cer create mode 100644 SecurityTests/ssl-policy-certs/InvalidWildcardTest30.cer create mode 100644 SecurityTests/ssl-policy-certs/InvalidWildcardTest31.cer create mode 100644 SecurityTests/ssl-policy-certs/InvalidWildcardTest32.cer create mode 100644 SecurityTests/ssl-policy-certs/InvalidWildcardTest33.cer create mode 100644 SecurityTests/ssl-policy-certs/InvalidWildcardTest34.cer rename SecurityTool/{security.h => security_tool.h} (100%) create mode 100644 SecurityTool/smartcards.h create mode 100644 SecurityTool/smartcards.m create mode 100644 SecurityTool/translocate.c rename OSX/libsecurity_ssl/sslViewer/fileIo.h => SecurityTool/translocate.h (71%) delete mode 100644 WHITEPAPER delete mode 100644 asl/com.apple.securityd delete mode 100644 codesign_wrapper/MISBase.h delete mode 100644 codesign_wrapper/MISEntitlement.c delete mode 100644 codesign_wrapper/MISEntitlement.h delete mode 100644 codesign_wrapper/codesign.c delete mode 100644 codesign_wrapper/codesign_wrapper.c delete mode 100644 codesign_wrapper/codesign_wrapper.h rename {OSX/libsecurity_ssl/dtlsEcho => dtlsEcho}/README (100%) create mode 100644 dtlsEcho/dtlsEchoClient.c create mode 100644 dtlsEcho/dtlsEchoServer.c delete mode 100644 iCloudStat/com.apple.icloudKeychainStats.plist delete mode 100644 iCloudStat/main.c delete mode 100644 libsecurity_smime/TODO delete mode 100644 resources/TrustedLogs.plist delete mode 100755 sbr delete mode 100644 securityd/src/AuthorizationDBPlist.cpp delete mode 100644 securityd/src/AuthorizationDBPlist.h delete mode 100644 securityd/src/AuthorizationEngine.cpp delete mode 100644 securityd/src/AuthorizationEngine.h delete mode 100644 securityd/src/AuthorizationMechEval.cpp delete mode 100644 securityd/src/AuthorizationMechEval.h delete mode 100644 securityd/src/AuthorizationRule.cpp delete mode 100644 securityd/src/AuthorizationRule.h delete mode 100644 securityd/src/authority.cpp delete mode 100644 securityd/src/authority.h delete mode 100644 spiralsink114.png delete mode 100644 spiralsink57.png create mode 100644 xcconfig/Security.xcconfig diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m index 4c8bddd3..ba4bbb13 100644 --- a/CircleJoinRequested/CircleJoinRequested.m +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -25,6 +25,7 @@ #import #include #include "SecureObjectSync/SOSCloudCircle.h" +#include "SecureObjectSync/SOSCloudCircleInternal.h" #include "SecureObjectSync/SOSPeerInfo.h" #include #include @@ -36,9 +37,14 @@ #import "NSDate+TimeIntervalDescription.h" #include #include +#import "os/activity.h" #import #include "utilities/SecCFRelease.h" #include "utilities/debugging.h" +#include "utilities/SecAKSWrappers.h" + +#import "CoreCDP/CDPFollowUpController.h" +#import "CoreCDP/CDPFollowUpContext.h" // As long as we are logging the failure use exit code of zero to make launchd happy #define EXIT_LOGGED_FAILURE(code) xpc_transaction_end(); exit(0) @@ -51,10 +57,64 @@ bool currentAlertIsForKickOut = false; NSMutableDictionary *applicants = nil; volatile NSString *debugState = @"main?"; dispatch_block_t doOnceInMainBlockChain = NULL; +bool _isLocked = true; +bool processApplicantsAfterUnlock = false; +bool _unlockedSinceBoot = false; NSString *castleKeychainUrl = @"prefs:root=CASTLE&path=Keychain/ADVANCED"; NSString *rejoinICDPUrl = @"prefs:root=CASTLE&aaaction=CDP&command=rejoin"; +BOOL processRequests(CFErrorRef *error); + + +static void keybagDidLock() +{ + secnotice("cjr", "keybagDidLock"); +} + +static void keybagDidUnlock() +{ + secnotice("cjr", "keybagDidUnlock"); + + CFErrorRef error = NULL; + + if(processApplicantsAfterUnlock){ + processRequests(&error); + processApplicantsAfterUnlock = false; + } + +} + +static bool updateIsLocked () +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetIsLocked(&_isLocked, &aksError)) { + _isLocked = YES; + secerror("Got error querying lock state: %@", aksError); + CFReleaseSafe(aksError); + return NO; + } + if (!_isLocked) + _unlockedSinceBoot = YES; + return YES; +} + +static void keybagStateChange () +{ + secerror("osactivity initiated"); + os_activity_initiate("keybagStateChanged", OS_ACTIVITY_FLAG_DEFAULT, ^{ + BOOL wasLocked = _isLocked; + if ( updateIsLocked()) { + if (wasLocked == _isLocked) + secerror("still %s ignoring", _isLocked ? "locked" : "unlocked"); + else if (_isLocked) + keybagDidLock(); + else + keybagDidUnlock(); + } + }); +} + static void doOnceInMain(dispatch_block_t block) { if (doOnceInMainBlockChain) { @@ -111,22 +171,22 @@ static NSMutableArray *applicantsInState(ApplicantUIState state) } -static BOOL processRequests(CFErrorRef *error) { +BOOL processRequests(CFErrorRef *error) { NSMutableArray *toAccept = [[applicantsInState(ApplicantAccepted) mapWithBlock:^id(id obj) {return (id)[obj rawPeerInfo];}] mutableCopy]; NSMutableArray *toReject = [[applicantsInState(ApplicantRejected) mapWithBlock:^id(id obj) {return (id)[obj rawPeerInfo];}] mutableCopy]; bool ok = true; if ([toAccept count]) { - NSLog(@"Process accept: %@", toAccept); + secnotice("cjr", "Process accept: %@", toAccept); ok = ok && SOSCCAcceptApplicants((__bridge CFArrayRef) toAccept, error); if (ok) { - NSLog(@"kSOSCCHoldLockForInitialSync"); + secnotice("cjr", "kSOSCCHoldLockForInitialSync"); notify_post(kSOSCCHoldLockForInitialSync); } } if ([toReject count]) { - NSLog(@"Process reject: %@", toReject); + secnotice("cjr", "Process reject: %@", toReject); ok = ok && SOSCCRejectApplicants((__bridge CFArrayRef) toReject, error); } @@ -162,7 +222,7 @@ static void applicantChoice(CFUserNotificationRef userNotification, CFOptionFlag } else if (kCFUserNotificationDefaultResponse == responseFlags) { choice = ApplicantAccepted; } else { - NSLog(@"Unexpected response %lu", responseFlags); + secnotice("cjr", "Unexpected response %lu", responseFlags); choice = ApplicantRejected; } @@ -179,20 +239,26 @@ static void applicantChoice(CFUserNotificationRef userNotification, CFOptionFlag // If this device has ever set up the public key this should work without the password... processed = processRequests(&error); if (processed) { - NSLog(@"Didn't need password to process %@", onScreen); + secnotice("cjr", "Didn't need password to process %@", onScreen); cancelCurrentAlert(true); return; } else { // ...however if the public key gets lost we should "just" fall through to the validate // password path. - NSLog(@"Couldn't process reject without password (e=%@) for %@ (will try with password next)", error, onScreen); + secnotice("cjr", "Couldn't process reject without password (e=%@) for %@ (will try with password next)", error, onScreen); + + if (CFErrorGetCode(error) == -536870174 && CFErrorGetDomain(error) == kSecKernDomain) { + secnotice("cjr", "system is locked, dismiss the notification"); + processApplicantsAfterUnlock = true; + return; + } } CFReleaseNull(error); } NSString *password = (__bridge NSString *) CFUserNotificationGetResponseValue(userNotification, kCFUserNotificationTextFieldValuesKey, 0); if (!password) { - NSLog(@"No password given, retry"); + secnotice("cjr", "No password given, retry"); askAboutAll(true); return; } @@ -204,10 +270,10 @@ static void applicantChoice(CFUserNotificationRef userNotification, CFOptionFlag // failure a few times before we give up. for (int try = 0; try < 5 && !processed; try++) { if (!SOSCCTryUserCredentials(CFSTR(""), (__bridge CFDataRef) passwordBytes, &error)) { - NSLog(@"Try user credentials failed %@", error); + secnotice("cjr", "Try user credentials failed %@", error); if ((error == NULL) || (CFEqual(kSOSErrorDomain, CFErrorGetDomain(error)) && kSOSErrorWrongPassword == CFErrorGetCode(error))) { - NSLog(@"Calling askAboutAll again..."); + secnotice("cjr", "Calling askAboutAll again..."); [onScreen enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { Applicant *applicant = (Applicant*) obj; applicant.applicantUIState = ApplicantWaiting; @@ -221,7 +287,7 @@ static void applicantChoice(CFUserNotificationRef userNotification, CFOptionFlag processed = processRequests(&error); if (!processed) { - NSLog(@"Can't processRequests: %@ for %@", error, onScreen); + secnotice("cjr", "Can't processRequests: %@ for %@", error, onScreen); } CFReleaseNull(error); } @@ -299,7 +365,7 @@ static NSDictionary *createNote(Applicant *applicantToAskAbout) static void askAboutAll(bool passwordFailure) { if ([[MCProfileConnection sharedConnection] effectiveBoolValueForSetting: MCFeatureAccountModificationAllowed] == MCRestrictedBoolExplicitNo) { - NSLog(@"Account modifications not allowed."); + secnotice("cjr", "Account modifications not allowed."); return; } @@ -319,11 +385,11 @@ static void askAboutAll(bool passwordFailure) currentAlertIsForApplicants = true; Applicant *applicantToAskAbout = firstApplicantWaitingOrOnScreen(); - NSLog(@"Asking about: %@ (of: %@)", applicantToAskAbout, applicants); + secnotice("cjr", "Asking about: %@ (of: %@)", applicantToAskAbout, applicants); NSDictionary *noteAttributes = createNote(applicantToAskAbout); if(!noteAttributes) { - NSLog(@"NULL data for %@", applicantToAskAbout); + secnotice("cjr", "NULL data for %@", applicantToAskAbout); cancelCurrentAlert(true); return; } @@ -333,14 +399,14 @@ static void askAboutAll(bool passwordFailure) if (currentAlert) { SInt32 err = CFUserNotificationUpdate(currentAlert, 0, flags, (__bridge CFDictionaryRef) noteAttributes); if (err) { - NSLog(@"CFUserNotificationUpdate err=%d", (int)err); + secnotice("cjr", "CFUserNotificationUpdate err=%d", (int)err); EXIT_LOGGED_FAILURE(EX_SOFTWARE); } } else { SInt32 err = 0; currentAlert = CFUserNotificationCreate(NULL, 0.0, flags, &err, (__bridge CFDictionaryRef) noteAttributes); if (err) { - NSLog(@"Can't make notification for %@ err=%x", applicantToAskAbout, (int)err); + secnotice("cjr", "Can't make notification for %@ err=%x", applicantToAskAbout, (int)err); EXIT_LOGGED_FAILURE(EX_SOFTWARE); } @@ -362,7 +428,7 @@ static void scheduleActivity(int alertInterval) xpc_dictionary_set_string(options, XPC_ACTIVITY_PRIORITY, XPC_ACTIVITY_PRIORITY_UTILITY); xpc_activity_register(kLaunchLaterXPCName, options, ^(xpc_activity_t activity) { - NSLog(@"activity handler fired"); + secnotice("cjr", "activity handler fired"); }); } @@ -377,7 +443,7 @@ static void reminderChoice(CFUserNotificationRef userNotification, CFOptionFlags if (responseFlags == kCFUserNotificationAlternateResponse) { // Use security code BOOL ok = [[LSApplicationWorkspace defaultWorkspace] openSensitiveURL:[NSURL URLWithString:castleKeychainUrl] withOptions:nil]; - NSLog(@"%s iCSC: opening %@ ok=%d", __FUNCTION__, castleKeychainUrl, ok); + secnotice("cjr", "%s iCSC: opening %@ ok=%d", __FUNCTION__, castleKeychainUrl, ok); } } @@ -389,7 +455,7 @@ static bool iCloudResetAvailable() { SecureBackup *backupd = [SecureBackup new]; NSDictionary *backupdResults; NSError *error = [backupd getAccountInfoWithInfo:nil results:&backupdResults]; - NSLog(@"SecureBackup e=%@ r=%@", error, backupdResults); + secnotice("cjr", "SecureBackup e=%@ r=%@", error, backupdResults); return (error == nil && [backupdResults[kSecureBackupIsEnabledKey] isEqualToNumber:@YES]); } @@ -422,7 +488,7 @@ static void postApplicationReminderAlert(NSDate *nowish, PersistentState *state, if (CPIsInternalDevice() && state.defaultPendingApplicationReminderAlertInterval != state.pendingApplicationReminderAlertInterval) { -#if !defined(NDEBUG) +#ifdef DEBUG body = [body stringByAppendingFormat: @"〖debug interval %u; wait time %@〗", state.pendingApplicationReminderAlertInterval, [nowish copyDescriptionOfIntervalSince:state.applicationDate]]; @@ -437,13 +503,12 @@ static void postApplicationReminderAlert(NSDate *nowish, PersistentState *state, (id) kCFUserNotificationAlertTopMostKey : @YES, (__bridge id) SBUserNotificationDontDismissOnUnlock : @YES, (__bridge id) SBUserNotificationDismissOnLock : @NO, - (__bridge id) SBUserNotificationOneButtonPerLine : @YES, }; SInt32 err = 0; currentAlert = CFUserNotificationCreate(NULL, 0.0, kCFUserNotificationPlainAlertLevel, &err, (__bridge CFDictionaryRef) pendingAttributes); if (err) { - NSLog(@"Can't make pending notification err=%x", (int)err); + secnotice("cjr", "Can't make pending notification err=%x", (int)err); } else { currentAlertIsForApplicants = false; currentAlertSource = CFUserNotificationCreateRunLoopSource(NULL, currentAlert, reminderChoice, 0); @@ -453,7 +518,9 @@ static void postApplicationReminderAlert(NSDate *nowish, PersistentState *state, static void kickOutChoice(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) { - NSLog(@"kOC %@ %lu", userNotification, responseFlags); + secnotice("cjr", "kOC %@ %lu", userNotification, responseFlags); + + //default response: continue -> settings pref pane advanced keychain sync page if (responseFlags == kCFUserNotificationDefaultResponse) { // We need to let things unwind to main for the new state to get saved doOnceInMain(^{ @@ -472,9 +539,40 @@ static void kickOutChoice(CFUserNotificationRef userNotification, CFOptionFlags } NSURL *url = [NSURL URLWithString: localICDP ? rejoinICDPUrl : castleKeychainUrl]; BOOL ok = [[LSApplicationWorkspace defaultWorkspace] openSensitiveURL:url withOptions:nil]; - NSLog(@"ok=%d opening %@", ok, url); + secnotice("cjr", "ok=%d opening %@", ok, url); }); } + //alternate response: later -> call CD + else if (responseFlags == kCFUserNotificationAlternateResponse) { + // We need to let things unwind to main for the new state to get saved + doOnceInMain(^{ + CDPFollowUpController *cdpd = [[CDPFollowUpController alloc] init]; + ACAccountStore *store = [ACAccountStore new]; + ACAccount *primary = [store aa_primaryAppleAccount]; + NSString *dsid = [primary aa_personID]; + bool localICDP = false; + if (dsid) { + NSDictionary *options = @{ (__bridge id) kPCSSetupDSID : dsid, }; + PCSIdentitySetRef identity = PCSIdentitySetCreate((__bridge CFDictionaryRef) options, NULL, NULL); + + if (identity) { + localICDP = PCSIdentitySetIsICDP(identity, NULL); + CFRelease(identity); + } + } + if(localICDP){ + NSError *localError = nil; + CDPFollowUpContext *context = [CDPFollowUpContext contextForStateRepair]; + [cdpd postFollowUpWithContext:context error:&localError ]; + if(localError){ + secnotice("cjr", "request to CoreCDP to follow up failed: %@", localError); + } + else + secnotice("cjr", "CoreCDP handling follow up"); + } + }); + + } cancelCurrentAlert(true); } @@ -505,7 +603,7 @@ static void postKickedOutAlert(enum DepartureReason reason) ADClientSetValueForScalarKey(CJRAggdNumCircleDevicesKey, num_peers); debugState = @"pKOA A"; - syslog(LOG_ERR, "DepartureReason %d", reason); + secnotice("cjr", "DepartureReason %d", reason); switch (reason) { case kSOSDiscoveredRetirement: case kSOSLostPrivateKey: @@ -522,6 +620,7 @@ static void postKickedOutAlert(enum DepartureReason reason) return; break; + case kSOSPasswordChanged: case kSOSNeverLeftCircle: case kSOSMembershipRevoked: case kSOSLeftUntrustedCircle: @@ -541,6 +640,7 @@ static void postKickedOutAlert(enum DepartureReason reason) "kSOSNeverAppliedToCircle", "kSOSDiscoveredRetirement", "kSOSLostPrivateKey", + "kSOSPasswordChanged", "unknown reason" }; int idx = (kSOSDepartureReasonError <= reason && reason <= kSOSLostPrivateKey) ? reason : (kSOSLostPrivateKey + 1); @@ -557,13 +657,12 @@ static void postKickedOutAlert(enum DepartureReason reason) (id) kCFUserNotificationAlertTopMostKey : @YES, (__bridge id) SBUserNotificationDismissOnLock : @NO, (__bridge id) SBUserNotificationDontDismissOnUnlock : @YES, - (__bridge id) SBUserNotificationOneButtonPerLine : @YES, }; SInt32 err = 0; - + if (currentAlertIsForKickOut) { debugState = @"pKOA B"; - NSLog(@"Updating existing alert %@ with %@", currentAlert, kickedAttributes); + secnotice("cjr", "Updating existing alert %@ with %@", currentAlert, kickedAttributes); CFUserNotificationUpdate(currentAlert, 0, kCFUserNotificationPlainAlertLevel, (__bridge CFDictionaryRef) kickedAttributes); } else { debugState = @"pKOA C"; @@ -571,24 +670,26 @@ static void postKickedOutAlert(enum DepartureReason reason) CFUserNotificationRef note = CFUserNotificationCreate(NULL, 0.0, kCFUserNotificationPlainAlertLevel, &err, (__bridge CFDictionaryRef) kickedAttributes); assert((note == NULL) == (err != 0)); if (err) { - NSLog(@"Can't make kicked out notification err=%x", (int)err); + secnotice("cjr", "Can't make kicked out notification err=%x", (int)err); + CFReleaseNull(note); } else { currentAlertIsForApplicants = false; currentAlertIsForKickOut = true; currentAlert = note; - NSLog(@"New ko alert %@ a=%@", currentAlert, kickedAttributes); + secnotice("cjr", "New ko alert %@ a=%@", currentAlert, kickedAttributes); currentAlertSource = CFUserNotificationCreateRunLoopSource(NULL, currentAlert, kickOutChoice, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), currentAlertSource, kCFRunLoopDefaultMode); int backupStateChangeToken; notify_register_dispatch("com.apple.EscrowSecurityAlert.reset", &backupStateChangeToken, dispatch_get_main_queue(), ^(int token) { if (currentAlert == note) { - NSLog(@"Backup state might have changed (dS=%@)", debugState); + secnotice("cjr", "Backup state might have changed (dS=%@)", debugState); postKickedOutAlert(reason); } else { - NSLog(@"Backup state may have changed, but we don't care anymore (dS=%@)", debugState); + secnotice("cjr", "Backup state may have changed, but we don't care anymore (dS=%@)", debugState); } }); + debugState = @"pKOA D"; CFRunLoopRun(); debugState = @"pKOA E"; @@ -609,12 +710,11 @@ static bool processEvents() NSDate *nowish = [NSDate date]; PersistentState *state = [PersistentState loadFromStorage]; enum DepartureReason departureReason = SOSCCGetLastDepartureReason(&departError); - NSLog(@"CircleStatus %d -> %d{%d} (s=%p)", state.lastCircleStatus, circleStatus, departureReason, state); - + secnotice("cjr", "CircleStatus %d -> %d{%d} (s=%p)", state.lastCircleStatus, circleStatus, departureReason, state); // Pending application reminder NSTimeInterval timeUntilApplicationAlert = [state.pendingApplicationReminder timeIntervalSinceDate:nowish]; - NSLog(@"Time until pendingApplicationReminder (%@) %f", [state.pendingApplicationReminder debugDescription], timeUntilApplicationAlert); + secnotice("cjr", "Time until pendingApplicationReminder (%@) %f", [state.pendingApplicationReminder debugDescription], timeUntilApplicationAlert); if (circleStatus == kSOSCCRequestPending) { if (timeUntilApplicationAlert <= 0) { debugState = @"reminderAlert"; @@ -624,16 +724,27 @@ static bool processEvents() } } - + if(circleStatus == kSOSCCError && state.lastCircleStatus != kSOSCCError && (departureReason == kSOSNeverLeftCircle)) { + secnotice("cjr", "error from SOSCCThisDeviceIsInCircle: %@", error); + CFIndex errorCode = CFErrorGetCode(error); + if(errorCode == kSOSErrorPublicKeyAbsent){ + secnotice("cjr", "We need the password to re-validate ourselves - it's changed on another device"); + postKickedOutAlert(kSOSPasswordChanged); + state.lastCircleStatus = kSOSCCError; + [state writeToStorage]; + return true; + } + } + // No longer in circle? if ((state.lastCircleStatus == kSOSCCInCircle && (circleStatus == kSOSCCNotInCircle || circleStatus == kSOSCCCircleAbsent)) || (state.lastCircleStatus == kSOSCCCircleAbsent && circleStatus == kSOSCCNotInCircle && state.absentCircleWithNoReason) || state.debugShowLeftReason) { // Used to be in the circle, now we aren't - tell the user why debugState = @"processEvents B"; - - if (state.debugShowLeftReason) { - NSLog(@"debugShowLeftReason: %@", state.debugShowLeftReason); + + if (state.debugShowLeftReason) { + secnotice("cjr", "debugShowLeftReason: %@", state.debugShowLeftReason); departureReason = [state.debugShowLeftReason intValue]; state.debugShowLeftReason = nil; CFReleaseNull(departError); @@ -642,14 +753,14 @@ static bool processEvents() if (departureReason != kSOSDepartureReasonError) { state.absentCircleWithNoReason = (circleStatus == kSOSCCCircleAbsent && departureReason == kSOSNeverLeftCircle); - NSLog(@"Depature reason %d", departureReason); + secnotice("cjr", "Depature reason %d", departureReason); postKickedOutAlert(departureReason); - NSLog(@"pKOA returned (cS %d lCS %d)", circleStatus, state.lastCircleStatus); + secnotice("cjr", "pKOA returned (cS %d lCS %d)", circleStatus, state.lastCircleStatus); } else { - NSLog(@"Couldn't get last departure reason: %@", departError); + secnotice("cjr", "Couldn't get last departure reason: %@", departError); } - } - + + } // Circle applications: pending request(s) started / completed debugState = @"processEvents C"; @@ -658,13 +769,13 @@ static bool processEvents() state.lastCircleStatus = circleStatus; if (lastCircleStatus != kSOSCCRequestPending && circleStatus == kSOSCCRequestPending) { - NSLog(@"Pending request started"); + secnotice("cjr", "Pending request started"); state.applicationDate = nowish; state.pendingApplicationReminder = [nowish dateByAddingTimeInterval: state.pendingApplicationReminderAlertInterval]; scheduleActivity(state.pendingApplicationReminderAlertInterval); } if (lastCircleStatus == kSOSCCRequestPending && circleStatus != kSOSCCRequestPending) { - NSLog(@"Pending request completed"); + secnotice("cjr", "Pending request completed"); state.applicationDate = [NSDate distantPast]; state.pendingApplicationReminder = [NSDate distantFuture]; } @@ -680,31 +791,31 @@ static bool processEvents() debugState = @"processEvents D1"; notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ifyToken, dispatch_get_main_queue(), ^(int token) { if (postedAlert != currentAlert) { - NSLog(@"-- CC after original alert gone (currentAlertIsForApplicants %d, pA %p, cA %p -- %@)", + secnotice("cjr", "-- CC after original alert gone (currentAlertIsForApplicants %d, pA %p, cA %p -- %@)", currentAlertIsForApplicants, postedAlert, currentAlert, currentAlert); notify_cancel(token); } else { - CFErrorRef localError = NULL; + CFErrorRef localError = NULL; SOSCCStatus newCircleStatus = SOSCCThisDeviceIsInCircle(&localError); if (newCircleStatus != kSOSCCRequestPending) { if (newCircleStatus == kSOSCCError) - NSLog(@"No longer pending (nCS=%d, alert=%@) error: %@", newCircleStatus, currentAlert, localError); + secnotice("cjr", "No longer pending (nCS=%d, alert=%@) error: %@", newCircleStatus, currentAlert, localError); else - NSLog(@"No longer pending (nCS=%d, alert=%@)", newCircleStatus, currentAlert); + secnotice("cjr", "No longer pending (nCS=%d, alert=%@)", newCircleStatus, currentAlert); cancelCurrentAlert(true); } else { - NSLog(@"Still pending..."); + secnotice("cjr", "Still pending..."); } CFReleaseNull(localError); } }); debugState = @"processEvents D2"; - NSLog(@"NOTE: currentAlertIsForApplicants %d, token %d", currentAlertIsForApplicants, notifyToken); + secnotice("cjr", "NOTE: currentAlertIsForApplicants %d, token %d", currentAlertIsForApplicants, notifyToken); CFRunLoopRun(); return true; } - debugState = @"processEvents D4"; - NSLog(@"SOSCCThisDeviceIsInCircle status %d, not checking applicants", circleStatus); + debugState = @"processEvents D4"; + secnotice("cjr", "SOSCCThisDeviceIsInCircle status %d, not checking applicants", circleStatus); return false; } @@ -723,7 +834,7 @@ static bool processEvents() int notify_token = -42; debugState = @"processEvents F"; int notify_register_status = notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ify_token, dispatch_get_main_queue(), ^(int token) { - NSLog(@"Notified: %s", kSOSCCCircleChangedNotification); + secnotice("cjr", "Notified: %s", kSOSCCCircleChangedNotification); CFErrorRef circleStatusError = NULL; bool needsUpdate = false; @@ -745,7 +856,7 @@ static bool processEvents() break; default: - NSLog(@"Update to %@ >> %@ with pending order, should work out ok though", existingApplicant, newApplicant); + secnotice("cjr", "Update to %@ >> %@ with pending order, should work out ok though", existingApplicant, newApplicant); break; } } else { @@ -754,7 +865,7 @@ static bool processEvents() } } if (copyPeerError) { - NSLog(@"Could not update peer info array: %@", copyPeerError); + secnotice("cjr", "Could not update peer info array: %@", copyPeerError); CFRelease(copyPeerError); return; } @@ -769,27 +880,27 @@ static bool processEvents() [applicants removeObjectsForKeys:idsToRemoveFromApplicants]; if (newIds.count == 0) { - NSLog(@"All applicants were handled elsewhere"); + secnotice("cjr", "All applicants were handled elsewhere"); cancelCurrentAlert(true); } SOSCCStatus currentCircleStatus = SOSCCThisDeviceIsInCircle(&circleStatusError); if (kSOSCCInCircle != currentCircleStatus) { - NSLog(@"Left circle (%d), not handling remaining %lu applicants", currentCircleStatus, (unsigned long)newIds.count); + secnotice("cjr", "Left circle (%d), not handling remaining %lu applicants", currentCircleStatus, (unsigned long)newIds.count); cancelCurrentAlert(true); } if (needsUpdate) { askAboutAll(false); } else { - NSLog(@"needsUpdate false, not updating alert"); + secnotice("cjr", "needsUpdate false, not updating alert"); } // Log circleStatusError? CFReleaseNull(circleStatusError); }); - NSLog(@"ACC token %d, status %d", notify_token, notify_register_status); + secnotice("cjr", "ACC token %d, status %d", notify_token, notify_register_status); debugState = @"processEvents F2"; if (applicants.count == 0) { - NSLog(@"No applicants"); + secnotice("cjr", "No applicants"); } else { debugState = @"processEvents F3"; askAboutAll(false); @@ -809,24 +920,34 @@ static bool processEvents() int main (int argc, const char * argv[]) { + xpc_transaction_begin(); - + @autoreleasepool { - // NOTE: DISPATCH_QUEUE_PRIORITY_LOW will not actually manage to drain events in a lot of cases (like circleStatus != kSOSCCInCircle) - xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) { - char *event_description = xpc_copy_description(object); - NSLog(@"notifyd event: %s\nAlert (%p) %s %s\ndebugState: %@", event_description, currentAlert, - currentAlertIsForApplicants ? "for applicants" : "!applicants", - currentAlertIsForKickOut ? "KO" : "!KO", debugState); - free(event_description); - }); - - xpc_activity_register(kLaunchLaterXPCName, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { - }); + // NOTE: DISPATCH_QUEUE_PRIORITY_LOW will not actually manage to drain events in a lot of cases (like circleStatus != kSOSCCInCircle) + xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) { + char *event_description = xpc_copy_description(object); + const char *notificationName = xpc_dictionary_get_string(object, "Notification"); + + if (notificationName && strcmp(notificationName, kUserKeybagStateChangeNotification)==0) { + secnotice("cjr", "keybag changed!"); + keybagStateChange(); + } + + secnotice("cjr", "notifyd event: %s\nAlert (%p) %s %s\ndebugState: %@", event_description, currentAlert, + currentAlertIsForApplicants ? "for applicants" : "!applicants", + currentAlertIsForKickOut ? "KO" : "!KO", debugState); + free(event_description); + }); + + xpc_activity_register(kLaunchLaterXPCName, XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) { + }); + int falseInARow = 0; while (falseInARow < 2) { if (processEvents()) { + secnotice("cjr", "Processed events!!!"); falseInARow = 0; } else { falseInARow++; @@ -838,8 +959,8 @@ int main (int argc, const char * argv[]) { } } } - - NSLog(@"Done"); + + secnotice("cjr", "Done"); xpc_transaction_end(); return(0); } diff --git a/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist b/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist index 10ce645e..72e08d7f 100644 --- a/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist +++ b/CircleJoinRequested/com.apple.security.CircleJoinRequested.plist @@ -16,6 +16,16 @@ com.apple.notifyd.matching + com.apple.mobile.keybagd.lock_status + + Notification + com.apple.mobile.keybagd.lock_status + + kPublicKeyNotAvailable + + Notification + com.apple.security.publickeynotavailable + com.apple.mobile.keybagd.first_unlock Notification diff --git a/CircleJoinRequested/entitlements.plist b/CircleJoinRequested/entitlements.plist index ad2e091f..cefdfc48 100644 --- a/CircleJoinRequested/entitlements.plist +++ b/CircleJoinRequested/entitlements.plist @@ -14,6 +14,7 @@ keychain-access-groups + keychain-cloud-circle com.apple.ProtectedCloudStorage diff --git a/CloudKeychainProxy/CloudKeychainProxy.1 b/CloudKeychainProxy/CloudKeychainProxy.1 deleted file mode 100644 index e2565fb7..00000000 --- a/CloudKeychainProxy/CloudKeychainProxy.1 +++ /dev/null @@ -1,79 +0,0 @@ -.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. -.\"See Also: -.\"man mdoc.samples for a complete listing of options -.\"man mdoc for the short list of editing options -.\"/usr/share/misc/mdoc.template -.Dd 1/15/13 \" DATE -.Dt CloudKeychainProxy 1 \" Program name and manual section number -.Os Darwin -.Sh NAME \" Section Header - required - don't modify -.Nm CloudKeychainProxy, -.\" The following lines are read in generating the apropos(man -k) database. Use only key -.\" words here as the database is built based on the words here and in the .ND line. -.Nm Other_name_for_same_program(), -.Nm Yet another name for the same program. -.\" Use .Nm macro to designate other names for the documented program. -.Nd This line parsed for whatis database. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm -.Op Fl abcd \" [-abcd] -.Op Fl a Ar path \" [-a path] -.Op Ar file \" [file] -.Op Ar \" [file ...] -.Ar arg0 \" Underlined argument - use .Ar anywhere to underline -arg2 ... \" Arguments -.Sh DESCRIPTION \" Section Header - required - don't modify -Use the .Nm macro to refer to your program throughout the man page like such: -.Nm -Underlining is accomplished with the .Ar macro like this: -.Ar underlined text . -.Pp \" Inserts a space -A list of items with descriptions: -.Bl -tag -width -indent \" Begins a tagged list -.It item a \" Each item preceded by .It macro -Description of item a -.It item b -Description of item b -.El \" Ends the list -.Pp -A list of flags and their descriptions: -.Bl -tag -width -indent \" Differs from above in tag removed -.It Fl a \"-a flag as a list item -Description of -a flag -.It Fl b -Description of -b flag -.El \" Ends the list -.Pp -.\" .Sh ENVIRONMENT \" May not be needed -.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 -.\" .It Ev ENV_VAR_1 -.\" Description of ENV_VAR_1 -.\" .It Ev ENV_VAR_2 -.\" Description of ENV_VAR_2 -.\" .El -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact -.It Pa /usr/share/file_name -FILE_1 description -.It Pa /Users/joeuser/Library/really_long_file_name -FILE_2 description -.El \" Ends the list -.\" .Sh DIAGNOSTICS \" May not be needed -.\" .Bl -diag -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.\" Please do not reference files that do not exist without filing a bug report -.Xr a 1 , -.Xr b 1 , -.Xr c 1 , -.Xr a 2 , -.Xr b 2 , -.Xr a 3 , -.Xr b 3 -.\" .Sh BUGS \" Document known, unremedied bugs -.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.h b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.h new file mode 100644 index 00000000..68965c9c --- /dev/null +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.h @@ -0,0 +1,35 @@ +/* + * 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@ + */ + + +#import "IDSProxy.h" + +@interface IDSKeychainSyncingProxy (IDSProxyReceiveMessage) +//receive message routines +-(BOOL) checkForFragmentation:(NSDictionary*)message id:(NSString*)fromID data:(NSData*)messageData; +-(NSMutableDictionary*) combineMessage:(NSString*)deviceID peerID:(NSString*)peerID uuid:(NSString*)uuid; +- (void)service:(IDSService *)service account:(IDSAccount *)account incomingMessage:(NSDictionary *)message fromID:(NSString *)fromID context:(IDSMessageContext *)context; +- (void)sendMessageToSecurity:(NSMutableDictionary*)messageAndFromID fromID:(NSString*)fromID; +- (void) handleAllPendingMessage; + +@end diff --git a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.m b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.m new file mode 100644 index 00000000..7e59ef57 --- /dev/null +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyReceiveMessage.m @@ -0,0 +1,399 @@ +/* + * 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@ + */ + + +#import +#import +#import + +#import +#import +#import +#import + +#include +#include +#include +#include + +#import +#import + +#include +#include +#include + +#import "IDSPersistentState.h" +#import "IDSKeychainSyncingProxy+IDSProxyReceiveMessage.h" +#import "IDSKeychainSyncingProxy+IDSProxySendMessage.h" +#import "IDSProxy.h" + +static NSString *const kIDSNumberOfFragments = @"NumberOfIDSMessageFragments"; +static NSString *const kIDSFragmentIndex = @"kFragmentIndex"; +static NSString *const kIDSOperationType = @"IDSMessageOperation"; +static NSString *const kIDSMessageToSendKey = @"MessageToSendKey"; +static NSString *const kIDSMessageUniqueID = @"MessageID"; + +@implementation IDSKeychainSyncingProxy (IDSProxyReceiveMessage) + + +-(int) countNumberOfValidObjects:(NSMutableArray*)fragmentsForDeviceID +{ + __block int count = 0; + [fragmentsForDeviceID enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * _Nonnull stop) { + if(obj != [NSNull null]){ + count++; + } + }]; + return count; +} + +-(BOOL) checkForFragmentation:(NSDictionary*)message id:(NSString*)fromID data:(NSData*)messageData +{ + BOOL handOffMessage = false; + + if([message valueForKey:kIDSNumberOfFragments] != nil){ + NSNumber *idsNumberOfFragments = [message objectForKey:kIDSNumberOfFragments]; + NSNumber *index = [message objectForKey:kIDSFragmentIndex]; + NSString *uuidString = [message objectForKey:kIDSMessageUniqueID]; + + if([IDSKeychainSyncingProxy idsProxy].allFragmentedMessages == nil) + [IDSKeychainSyncingProxy idsProxy].allFragmentedMessages = [NSMutableDictionary dictionary]; + + NSMutableDictionary *uniqueMessages = [[IDSKeychainSyncingProxy idsProxy].allFragmentedMessages objectForKey: fromID]; + if(uniqueMessages == nil) + uniqueMessages = [NSMutableDictionary dictionary]; + + NSMutableArray *fragmentsForDeviceID = [uniqueMessages objectForKey: uuidString]; + if(fragmentsForDeviceID == nil){ + fragmentsForDeviceID = [ [NSMutableArray alloc] initWithCapacity: [idsNumberOfFragments longValue]]; + for (int i = 0; i <[idsNumberOfFragments longValue] ; i++) { + [fragmentsForDeviceID addObject:[NSNull null]]; + } + } + + [fragmentsForDeviceID replaceObjectAtIndex: [index intValue] withObject:messageData ]; + [uniqueMessages setObject: fragmentsForDeviceID forKey:uuidString]; + [[IDSKeychainSyncingProxy idsProxy].allFragmentedMessages setObject:uniqueMessages forKey: fromID]; + + if([self countNumberOfValidObjects:fragmentsForDeviceID] == [idsNumberOfFragments longValue]) + handOffMessage = true; + else + handOffMessage = false; + + } + else //no fragmentation in the message, ready to hand off to securityd + handOffMessage = true; + + return handOffMessage; + +} + +-(NSMutableDictionary*) combineMessage:(NSString*)deviceID peerID:(NSString*)peerID uuid:(NSString*)uuid +{ + NSString *dataKey = [ NSString stringWithUTF8String: kMessageKeyIDSDataMessage ]; + NSString *deviceIDKey = [ NSString stringWithUTF8String: kMessageKeyDeviceID ]; + NSString *peerIDKey = [ NSString stringWithUTF8String: kMessageKeyPeerID ]; + + NSMutableDictionary *uniqueMessage = [[IDSKeychainSyncingProxy idsProxy].allFragmentedMessages objectForKey:deviceID]; + NSMutableArray *messagesForUUID = [uniqueMessage objectForKey:uuid]; + NSMutableData* completeMessage = [NSMutableData data]; + + [messagesForUUID enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSData *messageFragment = (NSData*)obj; + secnotice("IDS Transport","this is our index: %lu and size: %lu", (unsigned long)idx, (unsigned long)[messageFragment length]); + + [completeMessage appendData: messageFragment]; + }]; + [uniqueMessage removeObjectForKey:uuid]; + [[IDSKeychainSyncingProxy idsProxy].allFragmentedMessages removeObjectForKey:deviceID]; + return [NSMutableDictionary dictionaryWithObjectsAndKeys: completeMessage, dataKey, deviceID, deviceIDKey, peerID, peerIDKey, nil]; +} + +-(void) handleTestMessage:(NSString*)operation id:(NSString*)ID +{ + int operationType = [operation intValue]; + switch(operationType){ + case kIDSPeerAvailabilityDone: + { + secnotice("IDS Transport","!received availability response!: %@", ID); + notify_post(kSOSCCPeerAvailable); + //cancel timer! + dispatch_source_t timer = [[IDSKeychainSyncingProxy idsProxy].pingTimers objectForKey:ID]; + if(timer != nil){ + secnotice("IDS Transport", "timer not nil"); + dispatch_cancel(timer); + [[IDSKeychainSyncingProxy idsProxy].pingTimers removeObjectForKey:ID]; + } + //call securityd to sync with device over IDS + __block CFErrorRef cf_error = NULL; + __block bool success = false; + + [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { + + success = SOSCCRequestSyncWithPeerOverIDS(((__bridge CFStringRef)ID), &cf_error); + + if(success){ + secnotice("IDSPing", "sent device ID: %@ to securityd to sync over IDS", ID); + } + else{ + secerror("Could not hand device ID: %@ to securityd, error: %@", ID, cf_error); + } + + return NULL; + }]; + CFReleaseSafe(cf_error); + + break; + } + case kIDSEndPingTestMessage: + secnotice("IDS Transport","received pong message from other device: %@, ping test PASSED", ID); + break; + case kIDSSendOneMessage: + secnotice("IDS Transport","received ping test message, dropping on the floor now"); + break; + + case kIDSPeerAvailability: + case kIDSStartPingTestMessage: + { + char* messageCharS; + if(operationType == kIDSPeerAvailability){ + secnotice("IDS Transport","Received Availability Message from:%@!", ID); + asprintf(&messageCharS, "%d",kIDSPeerAvailabilityDone); + } + else{ + secnotice("IDS Transport","Received PingTest Message from: %@!", ID); + asprintf(&messageCharS, "%d", kIDSEndPingTestMessage); + } + + NSString *operationString = [[NSString alloc] initWithUTF8String:messageCharS]; + NSString* messageString = @"peer availability check finished"; + NSDictionary* messsageDictionary = @{kIDSOperationType:operationString, kIDSMessageToSendKey:messageString}; + NSString *identifier = [NSString string]; + + NSError *localError = NULL; + if (!self.isLocked) + [self sendIDSMessage:messsageDictionary name:ID peer:@"me" identifier:&identifier error:&localError]; + else + secnotice("IDS Transport", "device is locked, not responding to availability check"); + + free(messageCharS); + + break; + } + default: + break; + } +} + +- (void)service:(IDSService *)service account:(IDSAccount *)account incomingMessage:(NSDictionary *)message fromID:(NSString *)fromID context:(IDSMessageContext *)context +{ + secnotice("IDS Transport","message: %@", message); + NSString *dataKey = [ NSString stringWithUTF8String: kMessageKeyIDSDataMessage ]; + NSString *deviceIDKey = [ NSString stringWithUTF8String: kMessageKeyDeviceID ]; + NSString *peerIDKey = [ NSString stringWithUTF8String: kMessageKeyPeerID ]; + NSString *sendersPeerIDKey = [NSString stringWithUTF8String: kMessageKeySendersPeerID]; + + NSString *ID = nil; + uint32_t operationType; + bool hadError = false; + CFStringRef errorMessage = NULL; + __block NSString* myPeerID = @""; + __block NSData *messageData = nil; + + NSString* operationTypeAsString = nil; + NSMutableDictionary *messageDictionary = nil; + + NSArray *devices = [_service devices]; + for(NSUInteger i = 0; i < [ devices count ]; i++){ + IDSDevice *device = devices[i]; + if( [(IDSCopyIDForDevice(device)) containsString: fromID] == YES){ + ID = device.uniqueID; + break; + } + } + secnotice("IDS Transport", "Received message from: %@", ID); + NSString *sendersPeerID = [message objectForKey: sendersPeerIDKey]; + + if(sendersPeerID == nil) + sendersPeerID = [NSString string]; + + + require_action_quiet(ID, fail, hadError = true; errorMessage = CFSTR("require the sender's device ID")); + + operationTypeAsString = [message objectForKey: kIDSOperationType]; + messageDictionary = [message objectForKey: kIDSMessageToSendKey]; + + secnotice("IDS Transport","from peer %@, operation type as string: %@, as integer: %d", ID, operationTypeAsString, [operationTypeAsString intValue]); + operationType = [operationTypeAsString intValue]; + + if(operationType == kIDSPeerAvailabilityDone || operationType == kIDSEndPingTestMessage || operationType == kIDSSendOneMessage || operationType == kIDSPeerAvailability || operationType == kIDSStartPingTestMessage) + { + [self handleTestMessage:operationTypeAsString id:ID]; + } + else if(operationType == kIDSKeychainSyncIDSFragmentation) + { + [messageDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + myPeerID = (NSString*)key; + messageData = (NSData*)obj; + }]; + + BOOL readyToHandOffToSecD = [self checkForFragmentation:message id:ID data:messageData]; + + NSMutableDictionary *messageAndFromID = nil; + + if(readyToHandOffToSecD && ([message objectForKey:kIDSFragmentIndex])!= nil){ + secnotice("IDS Transport","fragmentation: messageData: %@, myPeerID: %@", messageData, myPeerID); + NSString* uuid = [message objectForKey:kIDSMessageUniqueID]; + messageAndFromID = [self combineMessage:ID peerID:myPeerID uuid:uuid]; + } + else if(readyToHandOffToSecD){ + secnotice("IDS Transport","no fragmentation: messageData: %@, myPeerID: %@", messageData, myPeerID); + messageAndFromID = [NSMutableDictionary dictionaryWithObjectsAndKeys: messageData, dataKey, ID, deviceIDKey, myPeerID, peerIDKey, nil]; + } + else + return; + + //set the sender's peer id so we can check it in securityd + [messageAndFromID setObject:sendersPeerID forKey:sendersPeerIDKey]; + + if([IDSKeychainSyncingProxy idsProxy].isLocked){ + //hang on to the message and set the retry deadline + [self.unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; + } + else + [self sendMessageToSecurity:messageAndFromID fromID:fromID]; + } + else + secerror("dropping IDS message"); + +fail: + if(hadError) + secerror("error:%@", errorMessage); +} + + +- (void) handleAllPendingMessage +{ + secnotice("IDS Transport", "Attempting to handle pending messsages"); + if([self.unhandledMessageBuffer count] > 0){ + secnotice("IDS Transport", "handling Message: %@", self.unhandledMessageBuffer); + NSMutableDictionary *copyOfUnhanlded = [NSMutableDictionary dictionaryWithDictionary:self.unhandledMessageBuffer]; + [copyOfUnhanlded enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + NSMutableDictionary *messageAndFromID = (NSMutableDictionary*)obj; + NSString *fromID = (NSString*)key; + //remove the message from the official message buffer (if it fails to get handled it'll be reset again in sendMessageToSecurity) + [self.unhandledMessageBuffer removeObjectForKey: fromID]; + [self sendMessageToSecurity:messageAndFromID fromID:fromID]; + }]; + } +} + +- (bool) shouldPersistMessage:(NSDictionary*) newMessageAndFromID id:(NSString*)fromID +{ + __block bool persistMessage = true; + + //get the dictionary of messages for a particular device id + NSDictionary* messagesForID = [self.unhandledMessageBuffer valueForKey:fromID]; + + //Grab the data blob + CFStringRef dataKey = CFStringCreateWithCString(kCFAllocatorDefault, kMessageKeyIDSDataMessage, kCFStringEncodingASCII); + CFDataRef messageData = asData(CFDictionaryGetValue((__bridge CFDictionaryRef)newMessageAndFromID, dataKey), NULL); + + [messagesForID enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL * stop) { + NSData* queuedMessage = (NSData*)obj; + + if([queuedMessage isEqual:(__bridge NSData*)messageData]) + persistMessage = false; + }]; + + CFReleaseNull(dataKey); + return persistMessage; +} + +-(void)sendMessageToSecurity:(NSMutableDictionary*)messageAndFromID fromID:(NSString*)fromID +{ + __block CFErrorRef cf_error = NULL; + __block HandleIDSMessageReason success = kHandleIDSMessageSuccess; + + [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { + + success = SOSCCHandleIDSMessage(((__bridge CFDictionaryRef)messageAndFromID), &cf_error); + //turns out the error needs to be evaluated as sync_and_do returns bools + if(cf_error != NULL) + { + CFStringRef errorDescription = CFErrorCopyDescription(cf_error); + if (CFStringCompare(errorDescription, CFSTR("The operation couldn’t be completed. (Mach error -536870174 - Kern return error)"), 0) == 0 ) { + success = kHandleIDSMessageLocked; + } + CFReleaseNull(errorDescription); + } + + if(success == kHandleIDSMessageLocked){ + secnotice("IDS Transport","cannot handle messages from: %@ when locked, error:%@", fromID, cf_error); + if(!self.unhandledMessageBuffer) + self.unhandledMessageBuffer = [NSMutableDictionary dictionary]; + + //write message to disk if message is new to the unhandled queue + if([self shouldPersistMessage:messageAndFromID id:fromID]) + [self persistState]; + + [self.unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; + secnotice("IDS Transport", "unhandledMessageBuffer: %@", self.unhandledMessageBuffer); + + return NULL; + } + else if(success == kHandleIDSMessageNotReady){ + secnotice("IDS Transport","not ready to handle message from: %@, error:%@", fromID, cf_error); + if(!self.unhandledMessageBuffer) + self.unhandledMessageBuffer = [NSMutableDictionary dictionary]; + [self.unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; + secnotice("IDS Transport","unhandledMessageBuffer: %@", self.unhandledMessageBuffer); + //set timer + [[IDSKeychainSyncingProxy idsProxy] scheduleRetryRequestTimer]; + + //write message to disk if message is new to the unhandled queue + if([self shouldPersistMessage:messageAndFromID id:fromID]) + [self persistState]; + + return NULL; + } + else if(success == kHandleIDSmessageDeviceIDMismatch){ + secnotice("IDS Transport","message for a ghost! dropping message. error:%@", cf_error); + return NULL; + } + else if(success == kHandleIDSMessageDontHandle){ + secnotice("IDS Transport","error in message, dropping message. error:%@", cf_error); + return NULL; + } + else{ + secnotice("IDS Transport","IDSProxy handled this message %@, from: %@", messageAndFromID, fromID); + return (NSMutableDictionary*)messageAndFromID; + } + + CFReleaseNull(cf_error); + }]; +} + +@end diff --git a/OSX/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.h similarity index 60% rename from OSX/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h rename to IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.h index bd520ca9..516c2a49 100644 --- a/OSX/sec/SOSCircle/CloudKeychainProxy/CKDUserInteraction.h +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * 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, @@ -17,28 +17,17 @@ * 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@ */ -// -// CKDUserInteraction.h -// CloudKeychainProxy -// - -#import -#import - -typedef bool (^CKDUserInteractionBlock) (CFDictionaryRef responses, int64_t flags); -@interface CKDUserInteraction : NSObject -{ - -} -@property (atomic) CFUserNotificationRef userNotificationRef; -@property CFRunLoopSourceRef runLoopSourceRef; +#import "IDSProxy.h" -+ (CKDUserInteraction *) sharedInstance; -- (void)requestShowNotification:(NSDictionary *)infoForUserInfo completion:(CKDUserInteractionBlock)completionf; +@interface IDSKeychainSyncingProxy (IDSProxySendMessage) +-(BOOL) sendFragmentedIDSMessages:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) ourPeerID error:(NSError**) error; +-(BOOL) sendIDSMessage:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) peerID identifier:(NSString **)identifier error:(NSError**) error; +-(void) pingDevices:(NSArray*)list peerID:(NSString*)peerID; +- (void)pingTimerFired:(NSString*)deviceName peerID:(NSString*)peerID identifier:(NSString*)identifier; @end diff --git a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.m b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.m new file mode 100644 index 00000000..870f161e --- /dev/null +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxySendMessage.m @@ -0,0 +1,306 @@ +/* + * 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@ + */ + + +#import +#import + +#import +#import +#import +#import + +#include +#include +#include +#include + +#import +#import + +#include +#include +#include + +#import "IDSProxy.h" +#import "IDSPersistentState.h" +#import "IDSKeychainSyncingProxy+IDSProxySendMessage.h" +#import "IDSKeychainSyncingProxy+IDSProxyThrottle.h" + +#define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" + + +static NSString *const IDSSendMessageOptionForceEncryptionOffKey = @"IDSSendMessageOptionForceEncryptionOff"; + +static NSString *const kIDSNumberOfFragments = @"NumberOfIDSMessageFragments"; +static NSString *const kIDSFragmentIndex = @"kFragmentIndex"; +static NSString *const kIDSOperationType = @"IDSMessageOperation"; +static NSString *const kIDSMessageToSendKey = @"MessageToSendKey"; +static NSString *const kIDSMessageUniqueID = @"MessageID"; +static const int64_t kRetryTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for handling unhandled messages. +static const int64_t timeout = 7; + +static const int64_t kMaxIDSMessagePayloadSize = 64000; + + +@implementation IDSKeychainSyncingProxy (IDSProxySendMessage) + +-(bool) chunkAndSendKeychainPayload:(NSMutableData*)keychainData deviceID:(NSString*)deviceName ourPeerID:(NSString*)ourPeerID theirPeerID:(NSString*) theirPeerID operation:(NSString*)operationTypeAsString error:(NSError**) error +{ + __block BOOL result = false; + + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuid); + + uint64_t keychainDataLength = (uint64_t)[keychainData length]; + NSUInteger tempLength = [keychainData length]; + int fragmentIndex = 0; + int startingPosition = 0; + + int totalNumberOfFragments = ceil((double)((double)keychainDataLength/(double)kMaxIDSMessagePayloadSize)); + secnotice("IDS Transport","Total number of Fragments: %d", totalNumberOfFragments); + + while(tempLength != 0){ + secnotice("IDS Transport","length: %lu", (unsigned long)tempLength); + NSUInteger endlength; + if(tempLength < kMaxIDSMessagePayloadSize) + endlength = tempLength; + else + endlength = kMaxIDSMessagePayloadSize; + + NSData *fragment = [keychainData subdataWithRange:NSMakeRange(startingPosition, endlength)]; + NSMutableDictionary *newFragmentDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:fragment, theirPeerID, nil]; + + NSMutableDictionary* newMessageFragment = [NSMutableDictionary dictionaryWithObjectsAndKeys:deviceName, @"deviceID", + [[NSNumber alloc]initWithInt: totalNumberOfFragments], kIDSNumberOfFragments, + [[NSNumber alloc] initWithInt: fragmentIndex], kIDSFragmentIndex, + newFragmentDictionary,kIDSMessageToSendKey, + operationTypeAsString, kIDSOperationType, + (__bridge NSString*)uuidString, kIDSMessageUniqueID, nil]; + NSString *identifier = [NSString string]; + + secnotice("IDS Transport","sending fragment: %@", newMessageFragment); + result = [self sendIDSMessage:newMessageFragment name:deviceName peer:ourPeerID identifier:&identifier error:error]; + startingPosition+=endlength; + tempLength -= endlength; + fragmentIndex++; + } + CFReleaseNull(uuidString); + CFReleaseNull(uuid); + return result; +} + +-(BOOL) sendFragmentedIDSMessages:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) ourPeerID error:(NSError**) error +{ + + __block BOOL result = false; + + __block NSMutableData *keychainData = nil; + __block NSString *theirPeerID = nil; + secnotice("IDS Transport","fragmenting message! %@", data); + NSString *identifier = [NSString string]; + + NSString* operationTypeAsString = [data objectForKey: kIDSOperationType]; + NSMutableDictionary *messageDictionary = [data objectForKey: kIDSMessageToSendKey]; + + if([operationTypeAsString intValue] == kIDSKeychainSyncIDSFragmentation){ + + [messageDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + keychainData = (NSMutableData*)obj; + theirPeerID = (NSString*)key; + return; + }]; + secnotice("IDS Transport","keychainData length: %lu", (unsigned long)[keychainData length]); + if((uint64_t)[keychainData length] >= kMaxIDSMessagePayloadSize){ + [self chunkAndSendKeychainPayload:keychainData deviceID:deviceName ourPeerID:ourPeerID theirPeerID:theirPeerID operation:operationTypeAsString error:error]; + } + else{ //message is less than the max encryption size, pass it along + secnotice("IDS Transport","sending message, no fragmentation: %@", data); + result = [self sendIDSMessage:data name:deviceName peer:ourPeerID identifier:&identifier error:error]; + } + } + else + result = [self sendIDSMessage:data name:deviceName peer:ourPeerID identifier:&identifier error:error]; + + + + secnotice("IDS Transport","returning result: %d, error: %@", result, *error); + return result; +} + +- (void)pingTimerFired:(NSString*)deviceID peerID:(NSString*)peerID identifier:(NSString*)identifier +{ + secnotice("IDS Transport", "device ID: %@ !!!!!!!!!!!!!!!!Ping timeout is up!!!!!!!!!!!!", deviceID); + //call securityd to sync with device over KVS + __block CFErrorRef cf_error = NULL; + __block bool success = kHandleIDSMessageSuccess; + + dispatch_source_t timer = [[IDSKeychainSyncingProxy idsProxy].pingTimers objectForKey:deviceID]; //remove timer + dispatch_cancel(timer); //cancel timer + + [[IDSKeychainSyncingProxy idsProxy].pingTimers removeObjectForKey:deviceID]; + + [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { + + success = SOSCCRequestSyncWithPeerOverKVS(((__bridge CFStringRef)deviceID), &cf_error); + + if(success){ + secnotice("IDSPing", "sent peerID: %@ to securityd to sync over KVS", deviceID); + } + else{ + secerror("Could not hand peerID: %@ to securityd, error: %@", deviceID, cf_error); + } + + return NULL; + }]; + CFReleaseSafe(cf_error); +} + + +-(void) pingDevices:(NSArray*)list peerID:(NSString*)peerID +{ + NSDictionary *messageDictionary = @{kIDSOperationType : [NSString stringWithFormat:@"%d", kIDSPeerAvailability], kIDSMessageToSendKey : @"checking peers"}; + + [list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * top) { + NSString* deviceID = (NSString*)obj; + NSString* identifier = [NSString string]; + + secnotice("IDS Transport", "sending to id: %@", deviceID); + NSError *localErr = nil; + + [self recordTimestampOfWriteToIDS: messageDictionary deviceName:deviceID peerID:peerID]; //add pings to throttling + NSDictionary *safeValues = [self filterForWritableValues:messageDictionary]; + + if(safeValues != nil && [safeValues count] > 0){ + [self sendIDSMessage:safeValues name:deviceID peer:peerID identifier:&identifier error:&localErr]; + + if(localErr != nil){ + secerror("sending ping to peer %@ had an error: %@", deviceID, localErr); + [self sendKeysCallout:^NSMutableDictionary *(NSMutableDictionary *pending, NSError** error) { + CFErrorRef kvsError = nil; + bool success = SOSCCRequestSyncWithPeerOverKVS(((__bridge CFStringRef)deviceID), &kvsError); + + if(success){ + secnotice("IDSPing", "sent peerID: %@ to securityd to sync over KVS", deviceID); + } + else{ + secerror("Could not hand peerID: %@ to securityd, error: %@", deviceID, kvsError); + } + CFReleaseNull(kvsError); + return NULL; + }]; + } + else{ + dispatch_source_t timer = nil; + if( [self.pingTimers objectForKey:deviceID] == nil){ + timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); + + dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); + dispatch_source_set_event_handler(timer, ^{ + [self pingTimerFired:deviceID peerID:peerID identifier:identifier]; + }); + dispatch_resume(timer); + + [self.pingTimers setObject:timer forKey:deviceID]; + } + } + } + }]; + +} +-(BOOL) sendIDSMessage:(NSDictionary*)data name:(NSString*) deviceName peer:(NSString*) peerID identifier:(NSString **)identifier error:(NSError**) error +{ + BOOL result = true; + NSDictionary *userInfo; + NSInteger code = 0; + + NSString *errorMessage; + NSMutableSet *destinations = [NSMutableSet set]; + NSArray *ListOfIDSDevices = nil; + IDSMessagePriority priority = IDSMessagePriorityHigh; + IDSDevice *device = nil; + BOOL encryptionOff = YES; + NSError *localError = nil; + NSString *sendersPeerIDKey = [ NSString stringWithUTF8String: kMessageKeySendersPeerID]; + + secnotice("backoff","!!writing these keys to IDS!!: %@", data); + + NSDictionary *options = @{IDSSendMessageOptionForceEncryptionOffKey : [NSNumber numberWithBool:encryptionOff] }; + + NSMutableDictionary *dataCopy = [NSMutableDictionary dictionaryWithDictionary: data]; + + [dataCopy setObject:peerID forKey:sendersPeerIDKey]; + + secnotice("IDS Transport", "Sending message from: %@ to: %@", peerID, deviceName); + + require_action_quiet(_service, fail, code = kSecIDSErrorNotRegistered; errorMessage = createErrorString(@"Could not send message to peer: %@: IDS delegate uninitialized, can't use IDS to send this message", deviceName)); + + secnotice("IDS Transport","devices: %@", [_service devices]); + secnotice("IDS Transport", " we have their deviceName: %@", deviceName); + + ListOfIDSDevices = [_service devices]; + + require_action_quiet([ListOfIDSDevices count]> 0, fail, code = kSecIDSErrorNotRegistered; errorMessage=createErrorString(@"Could not send message to peer: %@: IDS devices are not registered yet", deviceName)); + secnotice("IDS Transport","This is our list of devices: %@", ListOfIDSDevices); + + for(NSUInteger i = 0; i < [ ListOfIDSDevices count ]; i++){ + device = ListOfIDSDevices[i]; + if( [ deviceName compare:device.uniqueID ] == 0){ + [destinations addObject: IDSCopyIDForDevice(device)]; + } + } + + require_action_quiet([destinations count] != 0, fail, code = kSecIDSErrorCouldNotFindMatchingAuthToken; errorMessage = createErrorString(@"Could not send message to peer: %@: IDS device ID for peer does not match any devices within an IDS Account", deviceName)); + + result = [_service sendMessage:dataCopy toDestinations:destinations priority:priority options:options identifier:identifier error:&localError ] ; + + require_action_quiet(localError == nil, fail, code = kSecIDSErrorFailedToSend; errorMessage = createErrorString(@"Had an error sending IDS message to peer: %@", deviceName)); + + secnotice("IDS Transport", "identifier: %@", *identifier); + + secnotice("IDS Transport","sent to peer:%@, message: %@", deviceName, dataCopy); + + return result; + +fail: + userInfo = [ NSDictionary dictionaryWithObjectsAndKeys:errorMessage, NSLocalizedDescriptionKey, nil ]; + if(error != nil){ + *error = [NSError errorWithDomain:@"com.apple.security.ids.error" code:code userInfo:userInfo]; + secerror("%@", *error); + } + if(localError != nil) + secerror("%@", localError); + + return false; +} + +- (void)service:(IDSService *)service account:(IDSAccount *)account identifier:(NSString *)identifier didSendWithSuccess:(BOOL)success error:(NSError *)error +{ + if (error) { + NSLog(@"IDSKeychainSyncingProxy didSendWithSuccess identifier=%@ error=%@", identifier, error); + } else { + NSLog(@"IDSKeychainSyncingProxy didSendWithSuccess identifier=%@ Success!", identifier); + } +} + +@end diff --git a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.h b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.h new file mode 100644 index 00000000..a1230294 --- /dev/null +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.h @@ -0,0 +1,35 @@ +/* + * 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@ + */ + + +#import "IDSProxy.h" + +@interface IDSKeychainSyncingProxy (IDSProxyThrottle) + +- (dispatch_source_t)setNewTimer:(int)timeout key:(NSString*)key deviceName:(NSString*)deviceName peerID:(NSString*)peerID; +- (NSDictionary*)filterForWritableValues:(NSDictionary *)values; +- (void)recordTimestampForAppropriateInterval:(NSMutableDictionary**)timeTable key:(NSString*)key consecutiveWrites:(NSNumber**)consecutiveWrites; +- (void)recordTimestampOfWriteToIDS:(NSDictionary *)values deviceName:(NSString*)name peerID:(NSString*)peerid; + + +@end diff --git a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.m b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.m new file mode 100644 index 00000000..ece00909 --- /dev/null +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy+IDSProxyThrottle.m @@ -0,0 +1,397 @@ +/* + * 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@ + */ + + +#import +#import + +#import +#import +#import +#import + +#include +#include +#include +#include + +#import +#import + +#include +#include +#include + +#import "IDSPersistentState.h" +#import "IDSKeychainSyncingProxy+IDSProxySendMessage.h" +#import "IDSKeychainSyncingProxy+IDSProxyThrottle.h" + +static NSString *kExportUnhandledMessages = @"UnhandledMessages"; +static NSString *kMonitorState = @"MonitorState"; + +static NSString *kMonitorPenaltyBoxKey = @"Penalty"; +static NSString *kMonitorMessageKey = @"Message"; +static NSString *kMonitorConsecutiveWrites = @"ConsecutiveWrites"; +static NSString *kMonitorLastWriteTimestamp = @"LastWriteTimestamp"; +static NSString *kMonitorMessageQueue = @"MessageQueue"; +static NSString *kMonitorPenaltyTimer = @"PenaltyTimer"; +static NSString *kMonitorDidWriteDuringPenalty = @"DidWriteDuringPenalty"; + +static NSString *kMonitorTimeTable = @"TimeTable"; +static NSString *kMonitorFirstMinute = @"AFirstMinute"; +static NSString *kMonitorSecondMinute = @"BSecondMinute"; +static NSString *kMonitorThirdMinute = @"CThirdMinute"; +static NSString *kMonitorFourthMinute = @"DFourthMinute"; +static NSString *kMonitorFifthMinute = @"EFifthMinute"; +static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; + +static int max_penalty_timeout = 32; +static int seconds_per_minute = 60; + +static const int64_t kRetryTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for handling unhandled messages. + +@implementation IDSKeychainSyncingProxy (IDSProxyThrottle) + +-(dispatch_source_t)setNewTimer:(int)timeout key:(NSString*)key deviceName:(NSString*)deviceName peerID:(NSString*)peerID +{ + + __block dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); + dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); + dispatch_source_set_event_handler(timer, ^{ + [self penaltyTimerFired:key deviceName:deviceName peerID:peerID]; + }); + dispatch_resume(timer); + return timer; +} + +-(void) increasePenalty:(NSNumber*)currentPenalty key:(NSString*)key keyEntry:(NSMutableDictionary**)keyEntry deviceName:(NSString*)deviceName peerID:(NSString*)peerID +{ + secnotice("backoff", "increasing penalty!"); + int newPenalty = 0; + + if ([currentPenalty intValue] <= 0) + newPenalty = 1; + else + newPenalty = fmin([currentPenalty intValue]*2, max_penalty_timeout); + + secnotice("backoff", "key %@, waiting %d minutes long to send next messages", key, newPenalty); + + NSNumber* penalty_timeout = [[NSNumber alloc]initWithInt:newPenalty]; + dispatch_source_t existingTimer = [*keyEntry objectForKey:kMonitorPenaltyTimer]; + + if(existingTimer != nil){ + [*keyEntry removeObjectForKey:kMonitorPenaltyTimer]; + dispatch_suspend(existingTimer); + dispatch_source_set_timer(existingTimer,dispatch_time(DISPATCH_TIME_NOW, newPenalty * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); + dispatch_resume(existingTimer); + [*keyEntry setObject:existingTimer forKey:kMonitorPenaltyTimer]; + } + else{ + dispatch_source_t timer = [self setNewTimer:newPenalty key:key deviceName:deviceName peerID:peerID]; + [*keyEntry setObject:timer forKey:kMonitorPenaltyTimer]; + } + + [*keyEntry setObject:penalty_timeout forKey:kMonitorPenaltyBoxKey]; + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:*keyEntry forKey:key]; +} + +-(void) decreasePenalty:(NSNumber*)currentPenalty key:(NSString*)key keyEntry:(NSMutableDictionary**)keyEntry deviceName:(NSString*)deviceName peerID:(NSString*)peerID +{ + int newPenalty = 0; + secnotice("backoff","decreasing penalty!"); + if([currentPenalty intValue] == 0 || [currentPenalty intValue] == 1) + newPenalty = 0; + else + newPenalty = [currentPenalty intValue]/2; + + secnotice("backoff","key %@, waiting %d minutes long to send next messages", key, newPenalty); + + NSNumber* penalty_timeout = [[NSNumber alloc]initWithInt:newPenalty]; + + dispatch_source_t existingTimer = [*keyEntry objectForKey:kMonitorPenaltyTimer]; + if(existingTimer != nil){ + [*keyEntry removeObjectForKey:kMonitorPenaltyTimer]; + dispatch_suspend(existingTimer); + if(newPenalty != 0){ + dispatch_source_set_timer(existingTimer,dispatch_time(DISPATCH_TIME_NOW, newPenalty * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); + dispatch_resume(existingTimer); + [*keyEntry setObject:existingTimer forKey:kMonitorPenaltyTimer]; + } + else{ + dispatch_resume(existingTimer); + dispatch_source_cancel(existingTimer); + } + } + else{ + if(newPenalty != 0){ + dispatch_source_t timer = [self setNewTimer:newPenalty key:key deviceName:deviceName peerID:peerID]; + [*keyEntry setObject:timer forKey:kMonitorPenaltyTimer]; + } + } + + [*keyEntry setObject:penalty_timeout forKey:kMonitorPenaltyBoxKey]; + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:*keyEntry forKey:key]; + +} + +- (void)penaltyTimerFired:(NSString*)key deviceName:(NSString*)deviceName peerID:(NSString*)peerID +{ + secnotice("backoff", "key: %@, !!!!!!!!!!!!!!!!penalty timeout is up!!!!!!!!!!!!", key); + NSMutableDictionary *keyEntry = [[IDSKeychainSyncingProxy idsProxy].monitor objectForKey:key]; + if(!keyEntry){ + [self initializeKeyEntry:key]; + keyEntry = [[IDSKeychainSyncingProxy idsProxy].monitor objectForKey:key]; + } + NSMutableArray *queuedMessages = [[IDSKeychainSyncingProxy idsProxy].monitor objectForKey:kMonitorMessageQueue]; + secnotice("backoff","key: %@, queuedMessages: %@", key, queuedMessages); + if(queuedMessages && [queuedMessages count] != 0){ + secnotice("backoff","key: %@, message queue not empty, writing to IDS!", key); + [queuedMessages enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSError* error = nil; + NSDictionary* message = (NSDictionary*) obj; + NSString *identifier = [NSString string]; + [self sendIDSMessage:message name:deviceName peer:peerID identifier:&identifier error:&error]; + }]; + + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:[NSMutableArray array] forKey:kMonitorMessageQueue]; + } + //decrease timeout since we successfully wrote messages out + NSNumber *penalty_timeout = [keyEntry objectForKey:kMonitorPenaltyBoxKey]; + secnotice("backoff", "key: %@, current penalty timeout: %@", key, penalty_timeout); + + NSString* didWriteDuringTimeout = [keyEntry objectForKey:kMonitorDidWriteDuringPenalty]; + if( didWriteDuringTimeout && [didWriteDuringTimeout isEqualToString:@"YES"] ) + { + //increase timeout since we wrote during out penalty timeout + [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry deviceName:deviceName peerID:peerID]; + } + else{ + //decrease timeout since we successfully wrote messages out + [self decreasePenalty:penalty_timeout key:key keyEntry:&keyEntry deviceName:deviceName peerID:peerID]; + } + + //resetting the check + [keyEntry setObject: @"NO" forKey:kMonitorDidWriteDuringPenalty]; + + //recompute the timetable and number of consecutive writes to IDS + NSMutableDictionary *timetableForKey = [keyEntry objectForKey:kMonitorTimeTable]; + if(timetableForKey == nil){ + timetableForKey = [self initializeTimeTable:key]; + } + NSNumber *consecutiveWrites = [keyEntry objectForKey:kMonitorConsecutiveWrites]; + if(consecutiveWrites == nil){ + consecutiveWrites = [[NSNumber alloc] initWithInt:0]; + } + [self recordTimestampForAppropriateInterval:&timetableForKey key:key consecutiveWrites:&consecutiveWrites]; + + [keyEntry setObject:consecutiveWrites forKey:kMonitorConsecutiveWrites]; + [keyEntry setObject:timetableForKey forKey:kMonitorTimeTable]; + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:keyEntry forKey:key]; + +} + +-(NSMutableDictionary*)initializeTimeTable:(NSString*)key +{ + NSDate *currentTime = [NSDate date]; + NSMutableDictionary *firstMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute], kMonitorFirstMinute, @"YES", kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *secondMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 2],kMonitorSecondMinute, @"NO", kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *thirdMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 3], kMonitorThirdMinute, @"NO",kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *fourthMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 4],kMonitorFourthMinute, @"NO", kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *fifthMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 5], kMonitorFifthMinute, @"NO", kMonitorWroteInTimeSlice, nil]; + + NSMutableDictionary *timeTable = [NSMutableDictionary dictionaryWithObjectsAndKeys: firstMinute, kMonitorFirstMinute, + secondMinute, kMonitorSecondMinute, + thirdMinute, kMonitorThirdMinute, + fourthMinute, kMonitorFourthMinute, + fifthMinute, kMonitorFifthMinute, nil]; + return timeTable; +} + +- (void)initializeKeyEntry:(NSString*)key +{ + NSMutableDictionary *timeTable = [[IDSKeychainSyncingProxy idsProxy] initializeTimeTable:key]; + NSDate *currentTime = [NSDate date]; + + NSMutableDictionary *keyEntry = [NSMutableDictionary dictionaryWithObjectsAndKeys: key, kMonitorMessageKey, @0, kMonitorConsecutiveWrites, currentTime, kMonitorLastWriteTimestamp, @0, kMonitorPenaltyBoxKey, timeTable, kMonitorTimeTable,[NSMutableDictionary dictionary], kMonitorMessageQueue, nil]; + + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:keyEntry forKey:key]; + +} + +- (void)recordTimestampForAppropriateInterval:(NSMutableDictionary**)timeTable key:(NSString*)key consecutiveWrites:(NSNumber**)consecutiveWrites +{ + NSDate *currentTime = [NSDate date]; + __block int cWrites = [*consecutiveWrites intValue]; + __block BOOL foundTimeSlot = NO; + __block NSMutableDictionary *previousTable = nil; + + NSArray *sortedTimestampKeys = [[*timeTable allKeys] sortedArrayUsingSelector:@selector(compare:)]; + [sortedTimestampKeys enumerateObjectsUsingBlock:^(id arrayObject, NSUInteger idx, BOOL *stop) + { + if(foundTimeSlot == YES) + return; + + NSString *sortedKey = (NSString*)arrayObject; + + //grab the dictionary containing write information + //(date, boolean to check if a write occured in the timeslice, + NSMutableDictionary *minutesTable = [*timeTable objectForKey: sortedKey]; + if(minutesTable == nil) + minutesTable = [[IDSKeychainSyncingProxy idsProxy] initializeTimeTable:key]; + + NSString *minuteKey = (NSString*)sortedKey; + NSDate *timeStampForSlice = [minutesTable objectForKey:minuteKey]; + + if(timeStampForSlice && [timeStampForSlice compare:currentTime] == NSOrderedDescending){ + foundTimeSlot = YES; + NSString* written = [minutesTable objectForKey:kMonitorWroteInTimeSlice]; + //figure out if we have previously recorded a write in this time slice + if([written isEqualToString:@"NO"]){ + [minutesTable setObject:@"YES" forKey:kMonitorWroteInTimeSlice]; + if(previousTable != nil){ + //if we wrote in the previous time slice count the current time as in the consecutive write count + written = [previousTable objectForKey:kMonitorWroteInTimeSlice]; + if([written isEqualToString:@"YES"]){ + cWrites++; + } + else if ([written isEqualToString:@"NO"]){ + cWrites = 0; + } + } + } + return; + } + previousTable = minutesTable; + }]; + + if(foundTimeSlot == NO){ + //reset the time table + secnotice("backoff","didn't find a time slot, resetting the table"); + + //record if a write occured between the last time slice of + //the time table entries and now. + NSMutableDictionary *lastTable = [*timeTable objectForKey:kMonitorFifthMinute]; + NSDate *lastDate = [lastTable objectForKey:kMonitorFifthMinute]; + + if(lastDate && ((double)[currentTime timeIntervalSinceDate: lastDate] >= seconds_per_minute)){ + *consecutiveWrites = [[NSNumber alloc]initWithInt:0]; + } + else{ + NSString* written = [lastTable objectForKey:kMonitorWroteInTimeSlice]; + if(written && [written isEqualToString:@"YES"]){ + cWrites++; + *consecutiveWrites = [[NSNumber alloc]initWithInt:cWrites]; + } + else{ + *consecutiveWrites = [[NSNumber alloc]initWithInt:0]; + } + } + + *timeTable = [[IDSKeychainSyncingProxy idsProxy] initializeTimeTable:key]; + return; + } + *consecutiveWrites = [[NSNumber alloc]initWithInt:cWrites]; +} +- (void)recordTimestampOfWriteToIDS:(NSDictionary *)values deviceName:(NSString*)name peerID:(NSString*)peerid +{ + if([[IDSKeychainSyncingProxy idsProxy].monitor count] == 0){ + [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + [self initializeKeyEntry: key]; + }]; + } + else{ + [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + NSMutableDictionary *keyEntry = [[IDSKeychainSyncingProxy idsProxy].monitor objectForKey:key]; + if(keyEntry == nil){ + [self initializeKeyEntry: key]; + } + else{ + NSNumber *penalty_timeout = [keyEntry objectForKey:kMonitorPenaltyBoxKey]; + NSDate *lastWriteTimestamp = [keyEntry objectForKey:kMonitorLastWriteTimestamp]; + NSMutableDictionary *timeTable = [keyEntry objectForKey: kMonitorTimeTable]; + NSNumber *existingWrites = [keyEntry objectForKey: kMonitorConsecutiveWrites]; + NSDate *currentTime = [NSDate date]; + + //record the write happened in our timetable structure + [self recordTimestampForAppropriateInterval:&timeTable key:key consecutiveWrites:&existingWrites]; + + int consecutiveWrites = [existingWrites intValue]; + secnotice("backoff","consecutive writes: %d", consecutiveWrites); + [keyEntry setObject:existingWrites forKey:kMonitorConsecutiveWrites]; + [keyEntry setObject:timeTable forKey:kMonitorTimeTable]; + [keyEntry setObject:currentTime forKey:kMonitorLastWriteTimestamp]; + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:keyEntry forKey:key]; + + if( (penalty_timeout && [penalty_timeout intValue] != 0 ) || ((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] <= 60 && consecutiveWrites >= 5)){ + + if( (penalty_timeout == nil || [penalty_timeout intValue] == 0) && consecutiveWrites == 5){ + secnotice("backoff","written for 5 consecutive minutes, time to start throttling"); + [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry deviceName:name peerID:peerid]; + } + else + secnotice("backoff","monitor: keys have been written for 5 or more minutes, recording we wrote during timeout"); + + //record we wrote during a timeout + [keyEntry setObject: @"YES" forKey:kMonitorDidWriteDuringPenalty]; + } + else if((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] <= 60 && consecutiveWrites < 5){ + //for debugging purposes + secnotice("backoff","monitor: still writing freely"); + [keyEntry setObject: @"NO" forKey:kMonitorDidWriteDuringPenalty]; + } + else if([penalty_timeout intValue] != 0 && ((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] > 60 && consecutiveWrites > 5) ){ + + //encountered a write even though we're in throttle mode + [keyEntry setObject: @"YES" forKey:kMonitorDidWriteDuringPenalty]; + } + } + }]; + } +} + +- (NSDictionary*)filterForWritableValues:(NSDictionary *)values +{ + secnotice("backoff", "filterForWritableValues: %@", values); + NSMutableDictionary *keyEntry_operationType = [[IDSKeychainSyncingProxy idsProxy].monitor objectForKey:@"IDSMessageOperation"]; + + secnotice("backoff", "keyEntry_operationType: %@", keyEntry_operationType); + + NSNumber *penalty = [keyEntry_operationType objectForKey:kMonitorPenaltyBoxKey]; + + if(penalty && [penalty intValue] != 0){ + + NSMutableArray *queuedMessage = [[IDSKeychainSyncingProxy idsProxy].monitor objectForKey:kMonitorMessageQueue]; + if(queuedMessage == nil) + queuedMessage = [NSMutableArray array]; + secnotice("backoff", "writing to queuedMessages: %@", queuedMessage); + [queuedMessage addObject:values]; + [[IDSKeychainSyncingProxy idsProxy].monitor setObject:queuedMessage forKey:kMonitorMessageQueue]; + return NULL; + } + + return values; +} + +@end diff --git a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist index 316edd1c..07887652 100644 --- a/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist +++ b/IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist @@ -21,10 +21,12 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 10.0 + 1.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2013 Apple, Inc. All rights reserved. diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSPersistentState.h b/IDSKeychainSyncingProxy/IDSPersistentState.h similarity index 96% rename from OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSPersistentState.h rename to IDSKeychainSyncingProxy/IDSPersistentState.h index 5afb3a73..11a124fa 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSPersistentState.h +++ b/IDSKeychainSyncingProxy/IDSPersistentState.h @@ -35,7 +35,7 @@ + (id)read:(NSURL *)path error:(NSError **)error; + (BOOL)write:(NSURL *)path data:(id)plist error:(NSError **)error; + (NSString *)dictionaryDescription: (NSDictionary *)state; -+ (NSMutableDictionary *)unhandledMessages; ++ (NSMutableDictionary *)idsState; + (void)setUnhandledMessages: (NSDictionary *)unhandledMessages; + (NSURL *)registrationFileURL; diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSPersistentState.m b/IDSKeychainSyncingProxy/IDSPersistentState.m similarity index 96% rename from OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSPersistentState.m rename to IDSKeychainSyncingProxy/IDSPersistentState.m index 294fc341..0bc5b581 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSPersistentState.m +++ b/IDSKeychainSyncingProxy/IDSPersistentState.m @@ -108,7 +108,7 @@ static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.idskeychain return [elements componentsJoinedByString: @" "]; } -+ (NSMutableDictionary *)unhandledMessages ++ (NSMutableDictionary *)idsState { NSError *error = NULL; id stateDictionary = [IDSKeychainSyncingProxyPersistentState read:[[self class] registrationFileURL] error:&error]; @@ -122,7 +122,7 @@ static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.idskeychain + (void)setUnhandledMessages: (NSDictionary *)unhandledMessages { NSError *error = NULL; - secdebug("keyregister", "Write registeredKeys: <%@>", [self dictionaryDescription: unhandledMessages]); + secdebug("IDS unhandled message", "Write unhandled Messages and monitor state: <%@>", [self dictionaryDescription: unhandledMessages]); [IDSKeychainSyncingProxyPersistentState write:[[self class] registrationFileURL] data:unhandledMessages error:&error]; } diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.h b/IDSKeychainSyncingProxy/IDSProxy.h similarity index 75% rename from OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.h rename to IDSKeychainSyncingProxy/IDSProxy.h index 29a88c4f..61e3228a 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.h +++ b/IDSKeychainSyncingProxy/IDSProxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2012-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -32,9 +32,6 @@ #import "SOSCloudKeychainClient.h" #import -#define IDSPROXYSCOPE "IDSProxy" -#define IDSServiceNameKeychainSync "com.apple.private.alloy.keychainsync" - typedef enum { kIDSStartPingTestMessage = 1, kIDSEndPingTestMessage= 2, @@ -42,7 +39,8 @@ typedef enum { kIDSSyncMessagesRaw = 4, kIDSSyncMessagesCompact = 5, kIDSPeerAvailability = 6, - kIDSPeerAvailabilityDone = 7 + kIDSPeerAvailabilityDone = 7, + kIDSKeychainSyncIDSFragmentation = 8 } idsOperation; typedef enum { @@ -51,32 +49,36 @@ typedef enum { kSecIDSErrorFailedToSend=-3, kSecIDSErrorCouldNotFindMatchingAuthToken = -4, kSecIDSErrorDeviceIsLocked = -5, - kSecIDSErrorBatchControllerUninitialized = -6 + kSecIDSErrorNoPeersAvailable = -6 + } idsError; -@interface IDSKeychainSyncingProxy : NSObject +@interface IDSKeychainSyncingProxy : NSObject { - CloudItemsChangedBlock itemsChangedCallback; IDSService *_service; NSString *_deviceID; - NSMutableDictionary *_unhandledMessageBuffer; } @property (retain, nonatomic) NSMutableDictionary *unhandledMessageBuffer; @property (retain, nonatomic) NSMutableDictionary *shadowPendingMessages; +@property (retain, nonatomic) NSMutableDictionary *allFragmentedMessages; +@property (retain, nonatomic) NSMutableDictionary *pingTimers; + +@property (atomic) dispatch_source_t penaltyTimer; +@property (atomic) bool penaltyTimerScheduled; +@property (retain, atomic) NSMutableDictionary *monitor; +@property (retain, atomic) NSDictionary *queuedMessages; @property (atomic) bool isIDSInitDone; @property (atomic) bool isSecDRunningAsRoot; +@property (atomic) bool doesSecDHavePeer; @property (atomic) dispatch_queue_t calloutQueue; @property (atomic) bool isLocked; @property (atomic) bool unlockedSinceBoot; -@property (atomic) dispatch_source_t syncTimer; -@property (atomic) bool syncTimerScheduled; -@property (atomic) dispatch_time_t deadline; -@property (atomic) dispatch_time_t lastSyncTime; +@property (atomic) dispatch_source_t retryTimer; +@property (atomic) bool retryTimerScheduled; @property (atomic) bool inCallout; -@property (atomic) bool oldInCallout; @property (atomic) bool setIDSDeviceID; @property (atomic) bool shadowDoSetIDSDeviceID; @@ -86,13 +88,16 @@ typedef enum { + (IDSKeychainSyncingProxy *) idsProxy; - (id)init; -- (void)setItemsChangedBlock:(CloudItemsChangedBlock)itemsChangedBlock; -- (void)streamEvent:(xpc_object_t)notification; -- (BOOL) sendIDSMessage:(NSDictionary*)data name:(NSString*)deviceName peer:(NSString*) peerID error:(NSError**) error; -- (BOOL) doSetIDSDeviceID: (NSError**)error; +- (void) importIDSState: (NSMutableDictionary*) state; + +- (void) doSetIDSDeviceID; - (void) doIDSInitialization; - (void) calloutWith: (void(^)(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *handledMessages, bool handledPendingMessage, bool handledSettingDeviceID))) callout; - (void) sendKeysCallout: (NSMutableDictionary *(^)(NSMutableDictionary* pending, NSError** error)) handleMessages; +- (void)persistState; +- (void)scheduleRetryRequestTimer; @end + +NSString* createErrorString(NSString* format, ...); diff --git a/IDSKeychainSyncingProxy/IDSProxy.m b/IDSKeychainSyncingProxy/IDSProxy.m new file mode 100644 index 00000000..c5d349f1 --- /dev/null +++ b/IDSKeychainSyncingProxy/IDSProxy.m @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2012-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@ + */ + +// +// IDSProxy.m +// ids-xpc +// + + +#import +#import + +#import +#import +#import +#import + +#include +#include +#include +#include + +#import +#import + +#include +#include +#include + +#import "IDSProxy.h" +#import "IDSKeychainSyncingProxy+IDSProxyReceiveMessage.h" +#import "IDSKeychainSyncingProxy+IDSProxySendMessage.h" +#import "IDSKeychainSyncingProxy+IDSProxyThrottle.h" +#import "IDSPersistentState.h" + +#define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" +#define kSecServerPeerInfoAvailable "com.apple.security.fpiAvailable" + +#define IDSServiceNameKeychainSync "com.apple.private.alloy.keychainsync" +static NSString *kMonitorState = @"MonitorState"; +static NSString *kExportUnhandledMessages = @"UnhandledMessages"; +static const char *kStreamName = "com.apple.notifyd.matching"; + +NSString *const IDSSendMessageOptionForceEncryptionOffKey = @"IDSSendMessageOptionForceEncryptionOff"; +static const int64_t kRetryTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for handling unhandled messages. +static const int64_t kMinMessageRetryDelay = (NSEC_PER_SEC * 8); + +CFStringRef kSOSErrorDomain = CFSTR("com.apple.security.sos.error"); + +CFIndex kSOSErrorPeerNotFound = 1032; +CFIndex SECD_RUN_AS_ROOT_ERROR = 1041; + +#define IDSPROXYSCOPE "IDSProxy" + +@implementation IDSKeychainSyncingProxy + ++ (IDSKeychainSyncingProxy *) idsProxy +{ + static IDSKeychainSyncingProxy *idsProxy; + if (!idsProxy) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + idsProxy = [[self alloc] init]; + }); + } + return idsProxy; +} + +-(NSDictionary*) exportState +{ + return @{ kMonitorState:_monitor, + kExportUnhandledMessages:_unhandledMessageBuffer + }; + +} +- (void)persistState +{ + if([_unhandledMessageBuffer count] > 0){ + [IDSKeychainSyncingProxyPersistentState setUnhandledMessages:[self exportState]]; + } +} + +- (void) importIDSState: (NSMutableDictionary*) state +{ + _unhandledMessageBuffer = state[kExportUnhandledMessages]; + if(!_unhandledMessageBuffer) + _unhandledMessageBuffer = [NSMutableDictionary dictionary]; + + _monitor = state[kMonitorState]; + if(_monitor == nil) + _monitor = [NSMutableDictionary dictionary]; +} + +- (id)init +{ + if (self = [super init]) + { + secnotice("event", "%@ start", self); + + _isIDSInitDone = false; + _service = nil; + _calloutQueue = dispatch_queue_create("IDSCallout", DISPATCH_QUEUE_SERIAL); + _unhandledMessageBuffer = [ [NSMutableDictionary alloc] initWithCapacity: 0]; + _pingTimers = [ [NSMutableDictionary alloc] initWithCapacity: 0]; + + _isSecDRunningAsRoot = false; + _doesSecDHavePeer = true; + + secdebug(IDSPROXYSCOPE, "%@ done", self); + + [self doIDSInitialization]; + if(_isIDSInitDone) + [self doSetIDSDeviceID]; + + + // Register for lock state changes + xpc_set_event_stream_handler(kStreamName, dispatch_get_main_queue(), + ^(xpc_object_t notification){ + [self streamEvent:notification]; + }); + + _retryTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); + dispatch_source_set_timer(_retryTimer, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, kRetryTimerLeeway); + dispatch_source_set_event_handler(_retryTimer, ^{ + [self timerFired]; + }); + dispatch_resume(_retryTimer); + [self importIDSState: [IDSKeychainSyncingProxyPersistentState idsState]]; + + int notificationToken; + notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, dispatch_get_main_queue(), + ^ (int token __unused) + { + secinfo("backoff", "keychain changed, wiping backoff monitor state"); + _monitor = [NSMutableDictionary dictionary]; + }); + int peerInfo; + notify_register_dispatch(kSecServerPeerInfoAvailable, &peerInfo, dispatch_get_main_queue(), + ^ (int token __unused) + { + secinfo("IDS Transport", "secd has a peer info"); + if(_doesSecDHavePeer == false){ + _doesSecDHavePeer = true; + [self doSetIDSDeviceID]; + } + }); + + [self updateUnlockedSinceBoot]; + [self updateIsLocked]; + if (!_isLocked) + [self keybagDidUnlock]; + + + } + return self; +} + +- (void)streamEvent:(xpc_object_t)notification +{ +#if (!TARGET_IPHONE_SIMULATOR) + const char *notificationName = xpc_dictionary_get_string(notification, "Notification"); + if (!notificationName) { + } else if (strcmp(notificationName, kUserKeybagStateChangeNotification)==0) { + return [self keybagStateChange]; + } + const char *eventName = xpc_dictionary_get_string(notification, "XPCEventName"); + char *desc = xpc_copy_description(notification); + secnotice("event", "%@ event: %s name: %s desc: %s", self, eventName, notificationName, desc); + if (desc) + free((void *)desc); +#endif +} + +- (void) keybagDidLock +{ + secnotice("IDS Transport", "%@ locking!", self); +} + +- (void) keybagDidUnlock +{ + secnotice("IDS Transport", "%@ unlocking!", self); + [self handleAllPendingMessage]; +} + +- (BOOL) updateUnlockedSinceBoot +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetHasBeenUnlocked(&_unlockedSinceBoot, &aksError)) { + secerror("%@ Got error from SecAKSGetHasBeenUnlocked: %@", self, aksError); + CFReleaseSafe(aksError); + return NO; + } + return YES; +} + +- (BOOL) updateIsLocked +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetIsLocked(&_isLocked, &aksError)) { + secerror("%@ Got error querying lock state: %@", self, aksError); + CFReleaseSafe(aksError); + return NO; + } + secerror("updateIsLocked: %d", _isLocked); + if (!_isLocked) + _unlockedSinceBoot = YES; + return YES; +} + +- (void) keybagStateChange +{ + os_activity_initiate("keybagStateChanged", OS_ACTIVITY_FLAG_DEFAULT, ^{ + secerror("keybagStateChange! was locked: %d", _isLocked); + BOOL wasLocked = _isLocked; + if ([self updateIsLocked]) { + if (wasLocked == _isLocked) + secdebug("IDS Transport", "%@ still %s ignoring", self, _isLocked ? "locked" : "unlocked"); + else if (_isLocked) + [self keybagDidLock]; + else + [self keybagDidUnlock]; + } + }); +} + + +- (void)timerFired +{ + if(_unhandledMessageBuffer) + secnotice("IDS Transport", "%@ attempting to hand unhandled messages to securityd, here is our message queue: %@", self, _unhandledMessageBuffer); + + if(_isLocked) + _retryTimerScheduled = NO; + else if([_unhandledMessageBuffer count] == 0) + _retryTimerScheduled = NO; + else if (_retryTimerScheduled && !_isLocked) + [self handleAllPendingMessage]; + else + [[IDSKeychainSyncingProxy idsProxy] scheduleRetryRequestTimer]; + +} + +- (void)scheduleRetryRequestTimer +{ + secnotice("IDS Transport", "scheduling unhandled messages timer"); + dispatch_source_set_timer(_retryTimer, dispatch_time(DISPATCH_TIME_NOW, kMinMessageRetryDelay), DISPATCH_TIME_FOREVER, kRetryTimerLeeway); + _retryTimerScheduled = YES; +} + +- (void)doIDSInitialization +{ + + secnotice("IDS Transport", "doIDSInitialization!"); + + _service = [[IDSService alloc] initWithService: @IDSServiceNameKeychainSync]; + + if( _service == nil ){ + _isIDSInitDone = false; + secerror("Could not create ids service"); + } + else{ + secnotice("IDS Transport", "IDS Transport Successfully set up IDS!"); + [_service addDelegate:self queue: dispatch_get_main_queue()]; + + _isIDSInitDone = true; + if(_isSecDRunningAsRoot == false) + [self doSetIDSDeviceID]; + } +} + +- (void) doSetIDSDeviceID +{ + NSInteger code = 0; + NSString *errorMessage = nil; + __block NSString* deviceID; + + if(!_isIDSInitDone){ + [self doIDSInitialization]; + } + require_action_quiet(_isSecDRunningAsRoot == false, fail, errorMessage = @"cannot set IDS device ID, secd is running as root"; code = SECD_RUN_AS_ROOT_ERROR;); + require_action_quiet(_doesSecDHavePeer == true, fail, errorMessage = @"cannot set IDS deviceID, secd does not have a full peer info for account"; code = kSOSErrorPeerNotFound); + require_action_quiet(_isIDSInitDone, fail, errorMessage = @"IDSKeychainSyncingProxy can't set up the IDS service"; code = kSecIDSErrorNotRegistered); + require_action_quiet(!_isLocked, fail, errorMessage = @"IDSKeychainSyncingProxy can't set device ID, device is locked"; code = kSecIDSErrorDeviceIsLocked); + + deviceID = IDSCopyLocalDeviceUniqueID(); + secdebug("IDS Transport", "This is our IDS device ID: %@", deviceID); + + require_action_quiet(deviceID != nil, fail, errorMessage = @"IDSKeychainSyncingProxy could not retrieve device ID from keychain"; code = kSecIDSErrorNoDeviceID); + + if(_inCallout && _isSecDRunningAsRoot == false){ + _shadowDoSetIDSDeviceID = YES; + } + else{ + _setIDSDeviceID = YES; + [self calloutWith:^(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *, bool, bool)) { + CFErrorRef localError = NULL; + bool handledSettingID = false; + handledSettingID = SOSCCSetDeviceID((__bridge CFStringRef) deviceID, &localError); + if(!handledSettingID && localError != NULL){ + + if(CFErrorGetCode(localError) == SECD_RUN_AS_ROOT_ERROR){ + secerror("SETTING RUN AS ROOT ERROR: %@", localError); + _isSecDRunningAsRoot = true; + } + else if (CFErrorGetCode(localError) == -536870174 && CFErrorGetDomain(localError) == kSecKernDomain) { + secnotice("IDS Transport", "system is locked, cannot set device ID, error: %@", localError); + _isLocked = true; + } + else if (CFErrorGetCode(localError) == kSOSErrorPeerNotFound && CFStringCompare(CFErrorGetDomain(localError), kSOSErrorDomain, 0) == 0){ + secnotice("IDS Transport","securityd does not have a peer yet , error: %@", localError); + _doesSecDHavePeer = false; + } + } + CFReleaseNull(localError); + dispatch_async(queue, ^{ + done(nil, NO, handledSettingID); + }); + }]; + } +fail: + if(errorMessage != nil){ + secerror("Setting device ID error: %@, code: %ld", errorMessage, (long)code); + } +} + +- (void) calloutWith: (void(^)(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *handledMessages, bool handledPendingMessage, bool handledSettingDeviceID))) callout +{ + // In IDSKeychainSyncingProxy serial queue + dispatch_queue_t idsproxy_queue = dispatch_get_main_queue(); + + // dispatch_get_global_queue - well-known global concurrent queue + // dispatch_get_main_queue - default queue that is bound to the main thread + xpc_transaction_begin(); + dispatch_async(_calloutQueue, ^{ + __block NSMutableDictionary *myPending; + __block bool myHandlePendingMessage; + __block bool myDoSetDeviceID; + __block bool wasLocked; + dispatch_sync(idsproxy_queue, ^{ + myPending = [_unhandledMessageBuffer copy]; + myHandlePendingMessage = _handleAllPendingMessages; + myDoSetDeviceID = _setIDSDeviceID; + wasLocked = _isLocked; + + _inCallout = YES; + + _shadowHandleAllPendingMessages = NO; + }); + + callout(myPending, myHandlePendingMessage, myDoSetDeviceID, idsproxy_queue, ^(NSMutableDictionary *handledMessages, bool handledPendingMessage, bool handledSetDeviceID) { + secdebug("event", "%@ %s%s before callout handled: %s%s", self, myHandlePendingMessage ? "P" : "p", myDoSetDeviceID ? "D" : "d", handledPendingMessage ? "H" : "h", handledSetDeviceID ? "I" : "i"); + + // In IDSKeychainSyncingProxy's serial queue + _inCallout = NO; + + // Update setting device id + _setIDSDeviceID = ((myDoSetDeviceID && !handledSetDeviceID)); + + _shadowDoSetIDSDeviceID = NO; + + if(_setIDSDeviceID && !_isLocked && _isSecDRunningAsRoot == false && _doesSecDHavePeer) + [self doSetIDSDeviceID]; + + xpc_transaction_end(); + }); + }); +} + +- (void) sendKeysCallout: (NSMutableDictionary*(^)(NSMutableDictionary* pending, NSError** error)) handleMessages { + [self calloutWith: ^(NSMutableDictionary *pending, bool handlePendingMesssages, bool doSetDeviceID, dispatch_queue_t queue, void(^done)(NSMutableDictionary *, bool, bool)) { + NSError* error = NULL; + + NSMutableDictionary* handled = handleMessages(pending, &error); + + dispatch_async(queue, ^{ + if (!handled && error) { + secerror("%@ did not handle message: %@", self, error); + } + + done(handled, NO, NO); + }); + }]; +} + +NSString* createErrorString(NSString* format, ...) +{ + va_list va; + va_start(va, format); + NSString* errorString = ([[NSString alloc] initWithFormat:format arguments:va]); + va_end(va); + return errorString; + +} + +@end diff --git a/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist b/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.ios.plist similarity index 79% rename from IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist rename to IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.ios.plist index 9f09d8bc..2f1f1d6c 100644 --- a/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist +++ b/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.ios.plist @@ -2,10 +2,31 @@ + EnablePressuredExit + + EnvironmentVariables + + DEBUGSCOPE + all + WAIT4DEBUGGER + NO + + Label + com.apple.security.idskeychainsyncingproxy LaunchEvents com.apple.notifyd.matching + com.apple.mobile.keybagd.first_unlock + + Notification + com.apple.mobile.keybagd.first_unlock + + com.apple.mobile.keybagd.lock_status + + Notification + com.apple.mobile.keybagd.lock_status + com.apple.keystore.lockstatus Notification @@ -13,17 +34,6 @@ - Program - /System/Library/Frameworks/Security.framework/IDSKeychainSyncingProxy.bundle/IDSKeychainSyncingProxy - Label - com.apple.security.idskeychainsyncingproxy - EnvironmentVariables - - DEBUGSCOPE - all - WAIT4DEBUGGER - NO - MachServices com.apple.private.alloy.keychainsync-idswake @@ -31,14 +41,14 @@ com.apple.security.idskeychainsyncingproxy + Program + /System/Library/Frameworks/Security.framework/IDSKeychainSyncingProxy.bundle/IDSKeychainSyncingProxy ProgramArguments /System/Library/Frameworks/Security.framework/IDSKeychainSyncingProxy.bundle/IDSKeychainSyncingProxy RunAtLoad - EnablePressuredExit - enabletransactions diff --git a/OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist b/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.osx.plist similarity index 97% rename from OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist rename to IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.osx.plist index 6c9d8691..c60f567d 100644 --- a/OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist +++ b/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.osx.plist @@ -41,7 +41,7 @@ EnablePressuredExit - enabletransactions - + KeepAlive + diff --git a/CloudKeychainProxy/en.lproj/InfoPlist.strings b/IDSKeychainSyncingProxy/en.lproj/InfoPlist.strings similarity index 100% rename from CloudKeychainProxy/en.lproj/InfoPlist.strings rename to IDSKeychainSyncingProxy/en.lproj/InfoPlist.strings diff --git a/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist b/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist index f62eceff..de454689 100644 --- a/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist +++ b/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist @@ -2,14 +2,16 @@ + keychain-cloud-circle + com.apple.wifi.manager-access + com.apple.private.ids.remoteurlconnection + com.apple.private.ids.force-encryption-off com.apple.private.alloy.keychainsync - com.apple.private.ids.remoteurlconnection - com.apple.private.ids.messaging.high-priority com.apple.private.alloy.keychainsync @@ -20,8 +22,8 @@ keychain-access-groups - IMCore apple + IMCore InternetAccounts application-identifier diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m b/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m similarity index 68% rename from OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m rename to IDSKeychainSyncingProxy/idskeychainsyncingproxy.m index 365eedc4..eba2c266 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m +++ b/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m @@ -37,7 +37,8 @@ #include "SOSCloudKeychainConstants.h" -#import "IDSProxy.h" +#import "IDSKeychainSyncingProxy+IDSProxyThrottle.h" +#import "IDSKeychainSyncingProxy+IDSProxySendMessage.h" int idsproxymain(int argc, const char *argv[]); @@ -77,8 +78,39 @@ static void idskeychainsyncingproxy_peer_dictionary_handler(const xpc_connection if(operation && !strcmp(operation, kOperationGetDeviceID)){ - NSError *error; - BOOL object = [[IDSKeychainSyncingProxy idsProxy] doSetIDSDeviceID:&error]; + [[IDSKeychainSyncingProxy idsProxy] doSetIDSDeviceID]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, true); + xpc_connection_send_message(peer, replyMessage); + secdebug(PROXYXPCSCOPE, "Set our IDS Device ID message sent"); + + } + else if (operation && !strcmp(operation, kOperationSendFragmentedIDSMessage)) + { + xpc_object_t xidsMessageData = xpc_dictionary_get_value(event, kMessageKeyValue); + xpc_object_t xDeviceName = xpc_dictionary_get_value(event, kMessageKeyDeviceName); + xpc_object_t xPeerID = xpc_dictionary_get_value(event, kMessageKeyPeerID); + BOOL object = false; + + NSString *deviceName = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xDeviceName)); + NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); + NSDictionary *messageDictionary = (__bridge_transfer NSDictionary*)(_CFXPCCreateCFObjectFromXPCObject(xidsMessageData)); + NSError *error = NULL; + bool isNameString = (CFGetTypeID((__bridge CFTypeRef)(deviceName)) == CFStringGetTypeID()); + bool isPeerIDString = (CFGetTypeID((__bridge CFTypeRef)(peerID)) == CFStringGetTypeID()); + bool isMessageDictionary = (CFGetTypeID((__bridge CFTypeRef)(messageDictionary)) == CFDictionaryGetTypeID()); + + require_quiet(isNameString, xit); + require_quiet(isPeerIDString, xit); + require_quiet(isMessageDictionary, xit); + + [[IDSKeychainSyncingProxy idsProxy] recordTimestampOfWriteToIDS: messageDictionary deviceName:deviceName peerID:peerID]; + NSDictionary *safeValues = [[IDSKeychainSyncingProxy idsProxy] filterForWritableValues:messageDictionary]; + + if(safeValues != nil && [safeValues count] > 0){ + object = [[IDSKeychainSyncingProxy idsProxy] sendFragmentedIDSMessages:safeValues name:deviceName peer:peerID error:&error]; + } + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, object); @@ -87,14 +119,36 @@ static void idskeychainsyncingproxy_peer_dictionary_handler(const xpc_connection xpc_dictionary_set_value(replyMessage, kMessageKeyError, xerrobj); } xpc_connection_send_message(peer, replyMessage); - secdebug(PROXYXPCSCOPE, "Set our IDS Device ID message sent"); + secdebug(PROXYXPCSCOPE, "IDS message sent"); + } + else if(operation && !strcmp(operation, kOperationSendDeviceList)) //IDS device availability check + { + xpc_object_t xidsDeviceList = xpc_dictionary_get_value(event, kMessageKeyValue); + xpc_object_t xPeerID = xpc_dictionary_get_value(event, kMessageKeyPeerID); + + NSArray *idsList = (__bridge_transfer NSArray*)(_CFXPCCreateCFObjectFromXPCObject(xidsDeviceList)); + NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); + + bool isMessageArray = (CFGetTypeID((__bridge CFTypeRef)(idsList)) == CFArrayGetTypeID()); + bool isPeerIDString = (CFGetTypeID((__bridge CFTypeRef)(peerID)) == CFStringGetTypeID()); + + require_quiet(isMessageArray, xit); + require_quiet(isPeerIDString, xit); + + [[IDSKeychainSyncingProxy idsProxy] pingDevices:idsList peerID:peerID]; + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, true); + xpc_connection_send_message(peer, replyMessage); + secdebug(PROXYXPCSCOPE, "IDS device list sent"); } - else if (operation && !strcmp(operation, kOperationSendIDSMessage)) + else if (operation && !strcmp(operation, kOperationSendIDSMessage)) //for IDS tests { xpc_object_t xidsMessageData = xpc_dictionary_get_value(event, kMessageKeyValue); xpc_object_t xDeviceName = xpc_dictionary_get_value(event, kMessageKeyDeviceName); xpc_object_t xPeerID = xpc_dictionary_get_value(event, kMessageKeyPeerID); + BOOL object = false; NSString *deviceName = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xDeviceName)); NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); @@ -103,12 +157,13 @@ static void idskeychainsyncingproxy_peer_dictionary_handler(const xpc_connection bool isNameString = (CFGetTypeID((__bridge CFTypeRef)(deviceName)) == CFStringGetTypeID()); bool isPeerIDString = (CFGetTypeID((__bridge CFTypeRef)(peerID)) == CFStringGetTypeID()); bool isMessageDictionary = (CFGetTypeID((__bridge CFTypeRef)(messageDictionary)) == CFDictionaryGetTypeID()); - + require_quiet(isNameString, xit); require_quiet(isPeerIDString, xit); require_quiet(isMessageDictionary, xit); - BOOL object = [[IDSKeychainSyncingProxy idsProxy] sendIDSMessage:messageDictionary name:deviceName peer:peerID error:&error]; + NSString *identifier = [NSString string]; + object = [[IDSKeychainSyncingProxy idsProxy] sendIDSMessage:messageDictionary name:deviceName peer:peerID identifier:&identifier error:&error]; xpc_object_t replyMessage = xpc_dictionary_create_reply(event); xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, object); @@ -119,8 +174,8 @@ static void idskeychainsyncingproxy_peer_dictionary_handler(const xpc_connection } xpc_connection_send_message(peer, replyMessage); secdebug(PROXYXPCSCOPE, "IDS message sent"); - } + else { char *description = xpc_copy_description(event); @@ -133,22 +188,6 @@ xit: describeXPCObject("handle_operation fail: ", event); } - -static void initializeProxyObjectWithConnection(const xpc_connection_t connection) -{ - [[IDSKeychainSyncingProxy idsProxy] setItemsChangedBlock:^CFArrayRef(CFDictionaryRef values) - { - secdebug(PROXYXPCSCOPE, "IDSKeychainSyncingProxy called back"); - xpc_object_t xobj = _CFXPCCreateXPCObjectFromCFObject(values); - xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); - xpc_dictionary_set_uint64(message, kMessageKeyVersion, kCKDXPCVersion); - xpc_dictionary_set_string(message, kMessageKeyOperation, kMessageOperationItemChanged); - xpc_dictionary_set_value(message, kMessageKeyValue, xobj?xobj:xpc_null_create()); - xpc_connection_send_message(connection, message); // Send message; don't wait for a reply - return NULL; - }]; -} - static void idskeychainsyncingproxy_peer_event_handler(xpc_connection_t peer, xpc_object_t event) { describeXPCObject("peer: ", peer); @@ -183,8 +222,8 @@ static void idskeychainsyncingproxy_event_handler(xpc_connection_t peer) secdebug(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); return; } - initializeProxyObjectWithConnection(peer); - xpc_connection_set_event_handler(peer, ^(xpc_object_t event) + + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { idskeychainsyncingproxy_peer_event_handler(peer, event); }); @@ -227,3 +266,8 @@ int idsproxymain(int argc, const char *argv[]) return EXIT_FAILURE; } + +int main(int argc, const char *argv[]) +{ + return idsproxymain(argc, argv); +} diff --git a/ISACLProtectedItems/Info.plist b/ISACLProtectedItems/Info.plist index 75762714..5cf8ec41 100644 --- a/ISACLProtectedItems/Info.plist +++ b/ISACLProtectedItems/Info.plist @@ -2,14 +2,14 @@ - CFBundleDisplayName - AKPU/ACL protected keychain items CFBundleDevelopmentRegion en + CFBundleDisplayName + AKPU/ACL protected keychain items CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.apple.securityservices.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/KVSKeychainSyncingProxy/CKDAccount.h b/KVSKeychainSyncingProxy/CKDAccount.h new file mode 100644 index 00000000..24cb3979 --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDAccount.h @@ -0,0 +1,15 @@ +// +// CKDAccount.h +// Security +// +// + +#import + +@protocol CKDAccount + +- (NSSet*) keysChanged: (NSDictionary*) keyValues error: (NSError**) error; +- (bool) ensurePeerRegistration: (NSError**) error; +- (bool) syncWithAllPeers: (NSError**) error; + +@end diff --git a/KVSKeychainSyncingProxy/CKDKVSProxy.h b/KVSKeychainSyncingProxy/CKDKVSProxy.h new file mode 100644 index 00000000..e6f2023d --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDKVSProxy.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2012-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@ + */ + +// +// CKDKVSProxy.h +// ckd-xpc + +#import +#import +#import +#import + +#import + +#import "SOSCloudKeychainConstants.h" +#import "SOSCloudKeychainClient.h" + +#import "CKDStore.h" +#import "CKDAccount.h" + +#define XPROXYSCOPE "proxy" + +typedef void (^FreshnessResponseBlock)(bool success, NSError *err); + +@interface UbiqitousKVSProxy : NSObject +{ + id currentiCloudToken; + int callbackMethod; +} + +@property (readonly) NSObject* store; +@property (readonly) NSObject* account; + + +@property (retain, nonatomic) NSMutableSet *alwaysKeys; +@property (retain, nonatomic) NSMutableSet *firstUnlockKeys; +@property (retain, nonatomic) NSMutableSet *unlockedKeys; + +@property (atomic) bool unlockedSinceBoot; +@property (atomic) bool isLocked; +@property (atomic) bool seenKVSStoreChange; + + +@property (retain, nonatomic) NSMutableSet *pendingKeys; +@property (retain, nonatomic) NSMutableSet *shadowPendingKeys; + +@property (retain, nonatomic) NSString *dsid; + +@property (atomic) bool syncWithPeersPending; +@property (atomic) bool shadowSyncWithPeersPending; + +@property (atomic) bool ensurePeerRegistration; +@property (atomic) bool shadowEnsurePeerRegistration; + +@property (atomic) bool inCallout; + +@property (retain, nonatomic) NSMutableArray *freshnessCompletions; +@property (atomic) dispatch_time_t nextFreshnessTime; + +@property (atomic) dispatch_source_t syncTimer; +@property (atomic) bool syncTimerScheduled; + +@property (atomic) dispatch_time_t deadline; +@property (atomic) dispatch_time_t lastSyncTime; + + +@property (atomic) dispatch_queue_t calloutQueue; + +@property (atomic) dispatch_queue_t ckdkvsproxy_queue; +@property (atomic) dispatch_source_t penaltyTimer; +@property (atomic) bool penaltyTimerScheduled; +@property (retain, atomic) NSMutableDictionary *monitor; +@property (retain, atomic) NSDictionary *queuedMessages; + +@property (copy, atomic) dispatch_block_t shadowFlushBlock; + + ++ (UbiqitousKVSProxy *) sharedKVSProxy; +- (NSString *)description; +- (id)init NS_UNAVAILABLE; +- (id)initWithAccount:(NSObject*) account + store:(NSObject*) store NS_DESIGNATED_INITIALIZER; + +// Requests: + +- (void)clearStore; +- (void)synchronizeStore; +- (id) objectForKey: (NSString*) key; +- (NSDictionary*) copyAsDictionary; +- (void)setObjectsFromDictionary:(NSDictionary *)otherDictionary; +- (void)waitForSynchronization:(void (^)(NSDictionary *results, NSError *err))handler; + + +// Callbacks from stores when things happen +- (void)storeKeysChanged: (NSSet*) changedKeys initial: (bool) initial; +- (void)storeAccountChanged; + +- (void)streamEvent:(xpc_object_t)notification; + +- (void)processAllItems; +- (void)requestSyncWithAllPeers; +- (void)requestEnsurePeerRegistration; + +- (void)registerAtTimeKeys:(NSDictionary*)keyparms; + +- (NSSet*) keysForCurrentLockState; +- (void) intersectWithCurrentLockState: (NSMutableSet*) set; + +- (NSMutableSet*) pendKeysAndGetNewlyPended: (NSSet*) keysToPend; + +- (NSMutableSet*) pendingKeysForCurrentLockState; +- (NSMutableSet*) pendKeysAndGetPendingForCurrentLockState: (NSSet*) startingSet; + +- (void)processPendingKeysForCurrentLockState; + +- (void)registerKeys: (NSDictionary*)keys; + +- (void)processKeyChangedEvent:(NSDictionary *)keysChangedInCloud; +- (NSMutableDictionary *)copyValues:(NSSet *)keysOfInterest; + +- (void) doAfterFlush: (dispatch_block_t) block; +- (void) calloutWith: (void(^)(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *handledKeys, bool handledSyncWithPeers, bool handledEnsurePeerRegistration))) callout; +- (void) sendKeysCallout: (NSSet *(^)(NSSet* pending, NSError **error)) handleKeys; + +- (void)recordWriteToKVS:(NSDictionary *)values; +- (NSDictionary*)recordHaltedValuesAndReturnValuesToSafelyWrite:(NSDictionary *)values; + +@end diff --git a/KVSKeychainSyncingProxy/CKDKVSProxy.m b/KVSKeychainSyncingProxy/CKDKVSProxy.m new file mode 100644 index 00000000..213a4a27 --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDKVSProxy.m @@ -0,0 +1,1278 @@ +/* + * Copyright (c) 2012-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@ + */ + +// +// CKDKVSProxy.m +// ckd-xpc +// + +#import + +#import +#import + +#import "CKDKVSProxy.h" +#import "CKDPersistentState.h" +#import "CKDKVSStore.h" +#import "CKDSecuritydAccount.h" + +#include +#include + +#include "SOSCloudKeychainConstants.h" + +#include + +/* + The total space available in your app’s iCloud key-value storage is 1 MB. + The maximum number of keys you can specify is 1024, and the size limit for + each value associated with a key is 1 MB. So, for example, if you store a + single large value of 1 MB for a single key, that consumes your total + available storage. If you store 1 KB of data for each key, you can use + 1,000 key-value pairs. + */ + +static const char *kStreamName = "com.apple.notifyd.matching"; + +static NSString *kKeyKeyParameterKeys = @"KeyParameterKeys"; +static NSString *kKeyCircleKeys = @"CircleKeys"; +static NSString *kKeyMessageKeys = @"MessageKeys"; + +static NSString *kKeyAlwaysKeys = @"AlwaysKeys"; +static NSString *kKeyFirstUnlockKeys = @"FirstUnlockKeys"; +static NSString *kKeyUnlockedKeys = @"UnlockedKeys"; +static NSString *kKeyPendingKeys = @"PendingKeys"; +static NSString *kKeyUnsentChangedKeys = @"unsentChangedKeys"; +static NSString *kKeyUnlockNotificationRequested = @"unlockNotificationRequested"; +static NSString *kKeySyncWithPeersPending = @"SyncWithPeersPending"; +static NSString *kKeyEnsurePeerRegistration = @"EnsurePeerRegistration"; +static NSString *kKeyDSID = @"DSID"; +static NSString *kMonitorState = @"MonitorState"; + +static NSString *kMonitorPenaltyBoxKey = @"Penalty"; +static NSString *kMonitorMessageKey = @"Message"; +static NSString *kMonitorConsecutiveWrites = @"ConsecutiveWrites"; +static NSString *kMonitorLastWriteTimestamp = @"LastWriteTimestamp"; +static NSString *kMonitorMessageQueue = @"MessageQueue"; +static NSString *kMonitorPenaltyTimer = @"PenaltyTimer"; +static NSString *kMonitorDidWriteDuringPenalty = @"DidWriteDuringPenalty"; + +static NSString *kMonitorTimeTable = @"TimeTable"; +static NSString *kMonitorFirstMinute = @"AFirstMinute"; +static NSString *kMonitorSecondMinute = @"BSecondMinute"; +static NSString *kMonitorThirdMinute = @"CThirdMinute"; +static NSString *kMonitorFourthMinute = @"DFourthMinute"; +static NSString *kMonitorFifthMinute = @"EFifthMinute"; +static NSString *kMonitorWroteInTimeSlice = @"TimeSlice"; + +#define kSecServerKeychainChangedNotification "com.apple.security.keychainchanged" + +static int max_penalty_timeout = 32; +static int seconds_per_minute = 60; + +static const int64_t kMinSyncDelay = (NSEC_PER_MSEC * 500); // 500ms minimum delay before a syncWithAllPeers call. +static const int64_t kMaxSyncDelay = (NSEC_PER_SEC * 5); // 5s maximun delay for a given request +static const int64_t kMinSyncInterval = (NSEC_PER_SEC * 15); // 15s minimum time between successive syncWithAllPeers calls. +static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms leeway for sync events. + +static NSString* asNSString(NSObject* object) { + return [object isKindOfClass:[NSString class]] ? (NSString*) object : nil; +} + +@interface NSMutableDictionary (FindAndRemove) +-(NSObject*)extractObjectForKey:(NSString*)key; +@end + +@implementation NSMutableDictionary (FindAndRemove) +-(NSObject*)extractObjectForKey:(NSString*)key { + NSObject* result = [self objectForKey:key]; + [self removeObjectForKey: key]; + return result; +} +@end + +@implementation UbiqitousKVSProxy + +- (void)persistState +{ + [SOSPersistentState setRegisteredKeys:[self exportKeyInterests]]; +} + ++ (UbiqitousKVSProxy *) sharedKVSProxy +{ + static UbiqitousKVSProxy *sharedKVSProxy; + if (!sharedKVSProxy) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedKVSProxy = [[self alloc] initWithAccount: [CKDSecuritydAccount securitydAccount] + store: [CKDKVSStore kvsInterface]]; + }); + } + return sharedKVSProxy; +} + +- (id)initWithAccount:(NSObject*) account + store:(NSObject*) store +{ + if (self = [super init]) + { + secnotice("event", "%@ start", self); + +#if !(TARGET_OS_EMBEDDED) + // rdar://problem/26247270 + if (geteuid() == 0) { + secerror("Cannot run CloudKeychainProxy as root"); + return NULL; + } +#endif + _unlockedSinceBoot = NO; + _isLocked = YES; // until we know for sure + _ensurePeerRegistration = NO; + _syncWithPeersPending = NO; + + + _account = account; + _store = store; + + _calloutQueue = dispatch_queue_create("CKDCallout", DISPATCH_QUEUE_SERIAL); + _ckdkvsproxy_queue = dispatch_get_main_queue(); + + _freshnessCompletions = [NSMutableArray array]; + + _syncTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _ckdkvsproxy_queue); + dispatch_source_set_timer(_syncTimer, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, kSyncTimerLeeway); + dispatch_source_set_event_handler(_syncTimer, ^{ + [self timerFired]; + }); + dispatch_resume(_syncTimer); + + _monitor = [NSMutableDictionary dictionary]; + + int notificationToken; + notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, _ckdkvsproxy_queue, + ^ (int token __unused) + { + secinfo("backoff", "keychain changed, wiping backoff monitor state"); + _monitor = [NSMutableDictionary dictionary]; + }); + + [self importKeyInterests: [SOSPersistentState registeredKeys]]; + + // Register for lock state changes + xpc_set_event_stream_handler(kStreamName, _ckdkvsproxy_queue, + ^(xpc_object_t notification){ + [self streamEvent:notification]; + }); + _dsid = @""; + + [self updateUnlockedSinceBoot]; + [self updateIsLocked]; + if (!_isLocked) + [self keybagDidUnlock]; + + [[self store] connectToProxy: self]; + + secdebug(XPROXYSCOPE, "%@ done", self); + } + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%s%s%s%s%s%s%s%s%s%s%s>", + _isLocked ? "L" : "U", + _unlockedSinceBoot ? "B" : "-", + _seenKVSStoreChange ? "K" : "-", + _syncTimerScheduled ? "T" : "-", + _syncWithPeersPending ? "s" : "-", + _ensurePeerRegistration ? "e" : "-", + [_pendingKeys count] ? "p" : "-", + _inCallout ? "C" : "-", + _shadowSyncWithPeersPending ? "S" : "-", + _shadowEnsurePeerRegistration ? "E" : "-", + [_shadowPendingKeys count] ? "P" : "-"]; +} + +// +// MARK: XPC Function commands +// +- (void) clearStore { + [self.store removeAllObjects]; +} + +- (void)synchronizeStore { + [self.store pushWrites]; +} + +- (id) objectForKey: (NSString*) key { + return [self.store objectForKey: key]; +} +- (NSDictionary*) copyAsDictionary { + return [self.store copyAsDictionary]; +} + +// +// +// +- (void)processAllItems +{ + NSDictionary *allItems = [self.store copyAsDictionary]; + if (allItems) + { + secnotice("event", "%@ sending: %@", self, [[allItems allKeys] componentsJoinedByString: @" "]); + [self processKeyChangedEvent:allItems]; + } + else + secdebug(XPROXYSCOPE, "%@ No items in KVS", self); +} + +- (void)dealloc +{ + secdebug(XPROXYSCOPE, "%@", self); + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:NSUbiquityIdentityDidChangeNotification + object:nil]; +} + +// MARK: Penalty measurement and handling +-(dispatch_source_t)setNewTimer:(int)timeout key:(NSString*)key +{ + __block dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _ckdkvsproxy_queue); + dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, timeout * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kSyncTimerLeeway); + dispatch_source_set_event_handler(timer, ^{ + [self penaltyTimerFired:key]; + }); + dispatch_resume(timer); + return timer; +} + +-(void) increasePenalty:(NSNumber*)currentPenalty key:(NSString*)key keyEntry:(NSMutableDictionary**)keyEntry +{ + secnotice("backoff", "increasing penalty!"); + int newPenalty = 0; + if([currentPenalty intValue] == max_penalty_timeout){ + newPenalty = max_penalty_timeout; + } + else if ([currentPenalty intValue] == 0) + newPenalty = 1; + else + newPenalty = [currentPenalty intValue]*2; + + secnotice("backoff", "key %@, waiting %d minutes long to send next messages", key, newPenalty); + + NSNumber* penalty_timeout = [[NSNumber alloc]initWithInt:newPenalty]; + dispatch_source_t existingTimer = [*keyEntry valueForKey:kMonitorPenaltyTimer]; + + if(existingTimer != nil){ + [*keyEntry removeObjectForKey:kMonitorPenaltyTimer]; + dispatch_suspend(existingTimer); + dispatch_source_set_timer(existingTimer,dispatch_time(DISPATCH_TIME_NOW, newPenalty * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kSyncTimerLeeway); + dispatch_resume(existingTimer); + [*keyEntry setObject:existingTimer forKey:kMonitorPenaltyTimer]; + } + else{ + dispatch_source_t timer = [self setNewTimer:newPenalty key:key]; + [*keyEntry setObject:timer forKey:kMonitorPenaltyTimer]; + } + + [*keyEntry setObject:penalty_timeout forKey:kMonitorPenaltyBoxKey]; + [_monitor setObject:*keyEntry forKey:key]; +} + +-(void) decreasePenalty:(NSNumber*)currentPenalty key:(NSString*)key keyEntry:(NSMutableDictionary**)keyEntry +{ + int newPenalty = 0; + secnotice("backoff","decreasing penalty!"); + if([currentPenalty intValue] == 0 || [currentPenalty intValue] == 1) + newPenalty = 0; + else + newPenalty = [currentPenalty intValue]/2; + + secnotice("backoff","key %@, waiting %d minutes long to send next messages", key, newPenalty); + + NSNumber* penalty_timeout = [[NSNumber alloc]initWithInt:newPenalty]; + + dispatch_source_t existingTimer = [*keyEntry valueForKey:kMonitorPenaltyTimer]; + if(existingTimer != nil){ + [*keyEntry removeObjectForKey:kMonitorPenaltyTimer]; + dispatch_suspend(existingTimer); + if(newPenalty != 0){ + dispatch_source_set_timer(existingTimer,dispatch_time(DISPATCH_TIME_NOW, newPenalty * NSEC_PER_SEC * seconds_per_minute), DISPATCH_TIME_FOREVER, kSyncTimerLeeway); + dispatch_resume(existingTimer); + [*keyEntry setObject:existingTimer forKey:kMonitorPenaltyTimer]; + } + else{ + dispatch_resume(existingTimer); + dispatch_source_cancel(existingTimer); + } + } + else{ + if(newPenalty != 0){ + dispatch_source_t timer = [self setNewTimer:newPenalty key:key]; + [*keyEntry setObject:timer forKey:kMonitorPenaltyTimer]; + } + } + + [*keyEntry setObject:penalty_timeout forKey:kMonitorPenaltyBoxKey]; + [_monitor setObject:*keyEntry forKey:key]; + +} + +- (void)penaltyTimerFired:(NSString*)key +{ + secnotice("backoff", "key: %@, !!!!!!!!!!!!!!!!penalty timeout is up!!!!!!!!!!!!", key); + + NSMutableDictionary *keyEntry = [_monitor objectForKey:key]; + NSMutableDictionary *queuedMessages = [keyEntry objectForKey:kMonitorMessageQueue]; + secnotice("backoff","key: %@, queuedMessages: %@", key, queuedMessages); + if(queuedMessages && [queuedMessages count] != 0){ + secnotice("backoff","key: %@, message queue not empty, writing to KVS!", key); + [self setObjectsFromDictionary:queuedMessages]; + [keyEntry setObject:[NSMutableDictionary dictionary] forKey:kMonitorMessageQueue]; + } + + NSNumber *penalty_timeout = [keyEntry valueForKey:kMonitorPenaltyBoxKey]; + secnotice("backoff", "key: %@, current penalty timeout: %@", key, penalty_timeout); + + NSString* didWriteDuringTimeout = [keyEntry objectForKey:kMonitorDidWriteDuringPenalty]; + if( didWriteDuringTimeout && [didWriteDuringTimeout isEqualToString:@"YES"] ) + { + //increase timeout since we wrote during out penalty timeout + [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry]; + } + else{ + //decrease timeout since we successfully wrote messages out + [self decreasePenalty:penalty_timeout key:key keyEntry:&keyEntry]; + } + + //resetting the check + [keyEntry setObject: @"NO" forKey:kMonitorDidWriteDuringPenalty]; + + //recompute the timetable and number of consecutive writes to KVS + NSMutableDictionary *timetable = [keyEntry valueForKey:kMonitorTimeTable]; + NSNumber *consecutiveWrites = [keyEntry valueForKey:kMonitorConsecutiveWrites]; + [self recordTimestampForAppropriateInterval:&timetable key:key consecutiveWrites:&consecutiveWrites]; + + [keyEntry setObject:consecutiveWrites forKey:kMonitorConsecutiveWrites]; + [keyEntry setObject:timetable forKey:kMonitorTimeTable]; + [_monitor setObject:keyEntry forKey:key]; +} + +-(NSMutableDictionary*)initializeTimeTable:(NSString*)key +{ + NSDate *currentTime = [NSDate date]; + NSMutableDictionary *firstMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute], kMonitorFirstMinute, @"YES", kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *secondMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 2],kMonitorSecondMinute, @"NO", kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *thirdMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 3], kMonitorThirdMinute, @"NO",kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *fourthMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 4],kMonitorFourthMinute, @"NO", kMonitorWroteInTimeSlice, nil]; + NSMutableDictionary *fifthMinute = [NSMutableDictionary dictionaryWithObjectsAndKeys:[currentTime dateByAddingTimeInterval: seconds_per_minute * 5], kMonitorFifthMinute, @"NO", kMonitorWroteInTimeSlice, nil]; + + NSMutableDictionary *timeTable = [NSMutableDictionary dictionaryWithObjectsAndKeys: firstMinute, kMonitorFirstMinute, + secondMinute, kMonitorSecondMinute, + thirdMinute, kMonitorThirdMinute, + fourthMinute, kMonitorFourthMinute, + fifthMinute, kMonitorFifthMinute, nil]; + return timeTable; +} + +- (void)initializeKeyEntry:(NSString*)key +{ + NSMutableDictionary *timeTable = [self initializeTimeTable:key]; + NSDate *currentTime = [NSDate date]; + + NSMutableDictionary *keyEntry = [NSMutableDictionary dictionaryWithObjectsAndKeys: key, kMonitorMessageKey, @0, kMonitorConsecutiveWrites, currentTime, kMonitorLastWriteTimestamp, @0, kMonitorPenaltyBoxKey, timeTable, kMonitorTimeTable,[NSMutableDictionary dictionary], kMonitorMessageQueue, nil]; + + [_monitor setObject:keyEntry forKey:key]; + +} + +- (void)recordTimestampForAppropriateInterval:(NSMutableDictionary**)timeTable key:(NSString*)key consecutiveWrites:(NSNumber**)consecutiveWrites +{ + NSDate *currentTime = [NSDate date]; + __block int cWrites = [*consecutiveWrites intValue]; + __block BOOL foundTimeSlot = NO; + __block NSMutableDictionary *previousTable = nil; + NSArray *sorted = [[*timeTable allKeys] sortedArrayUsingSelector:@selector(compare:)]; + [sorted enumerateObjectsUsingBlock:^(id sortedKey, NSUInteger idx, BOOL *stop) + { + if(foundTimeSlot == YES) + return; + [*timeTable enumerateKeysAndObjectsUsingBlock: ^(id minute, id obj, BOOL *stop2) + { + if(foundTimeSlot == YES) + return; + if([sortedKey isEqualToString:minute]){ + NSMutableDictionary *minutesTable = (NSMutableDictionary*)obj; + NSString *minuteKey = (NSString*)minute; + NSDate *date = [minutesTable valueForKey:minuteKey]; + if([date compare:currentTime] == NSOrderedDescending){ + foundTimeSlot = YES; + NSString* written = [minutesTable valueForKey:kMonitorWroteInTimeSlice]; + if([written isEqualToString:@"NO"]){ + [minutesTable setObject:@"YES" forKey:kMonitorWroteInTimeSlice]; + if(previousTable != nil){ + written = [previousTable valueForKey:kMonitorWroteInTimeSlice]; + if([written isEqualToString:@"YES"]){ + cWrites++; + } + else if ([written isEqualToString:@"NO"]){ + cWrites = 0; + } + } + } + return; + } + previousTable = minutesTable; + } + }]; + }]; + + if(foundTimeSlot == NO){ + //reset the time table + secnotice("backoff","didn't find a time slot, resetting the table"); + NSMutableDictionary *lastTable = [*timeTable valueForKey:kMonitorFifthMinute]; + NSDate *lastDate = [lastTable valueForKey:kMonitorFifthMinute]; + + if((double)[currentTime timeIntervalSinceDate: lastDate] >= seconds_per_minute){ + *consecutiveWrites = [[NSNumber alloc]initWithInt:0]; + } + else{ + NSString* written = [lastTable valueForKey:kMonitorWroteInTimeSlice]; + if([written isEqualToString:@"YES"]){ + cWrites++; + *consecutiveWrites = [[NSNumber alloc]initWithInt:cWrites]; + } + else{ + *consecutiveWrites = [[NSNumber alloc]initWithInt:0]; + } + } + + *timeTable = [self initializeTimeTable:key]; + return; + } + *consecutiveWrites = [[NSNumber alloc]initWithInt:cWrites]; +} +- (void)recordWriteToKVS:(NSDictionary *)values +{ + if([_monitor count] == 0){ + [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + [self initializeKeyEntry: key]; + }]; + } + else{ + [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + NSMutableDictionary *keyEntry = [_monitor objectForKey:key]; + if(keyEntry == nil){ + [self initializeKeyEntry: key]; + } + else{ + NSNumber *penalty_timeout = [keyEntry objectForKey:kMonitorPenaltyBoxKey]; + NSDate *lastWriteTimestamp = [keyEntry objectForKey:kMonitorLastWriteTimestamp]; + NSMutableDictionary *timeTable = [keyEntry objectForKey: kMonitorTimeTable]; + NSNumber *existingWrites = [keyEntry objectForKey: kMonitorConsecutiveWrites]; + NSDate *currentTime = [NSDate date]; + + [self recordTimestampForAppropriateInterval:&timeTable key:key consecutiveWrites:&existingWrites]; + + int consecutiveWrites = [existingWrites intValue]; + secnotice("backoff","consecutive writes: %d", consecutiveWrites); + [keyEntry setObject:existingWrites forKey:kMonitorConsecutiveWrites]; + [keyEntry setObject:timeTable forKey:kMonitorTimeTable]; + [keyEntry setObject:currentTime forKey:kMonitorLastWriteTimestamp]; + [_monitor setObject:keyEntry forKey:key]; + + if([penalty_timeout intValue] != 0 || ((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] <= 60 && consecutiveWrites >= 5)){ + if([penalty_timeout intValue] != 0 && consecutiveWrites == 5){ + secnotice("backoff","written for 5 consecutive minutes, time to start throttling"); + [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry]; + } + else + secnotice("backoff","monitor: keys have been written for 5 or more minutes, recording we wrote during timeout"); + + //record we wrote during a timeout + [keyEntry setObject: @"YES" forKey:kMonitorDidWriteDuringPenalty]; + } + //keep writing freely but record it + else if((double)[currentTime timeIntervalSinceDate: lastWriteTimestamp] <= 60 && consecutiveWrites < 5){ + secnotice("backoff","monitor: still writing freely"); + } + } + }]; + } +} + +- (NSDictionary*)recordHaltedValuesAndReturnValuesToSafelyWrite:(NSDictionary *)values +{ + NSMutableDictionary *SafeMessages = [NSMutableDictionary dictionary]; + [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + NSMutableDictionary *keyEntry = [_monitor objectForKey:key]; + NSNumber *penalty = [keyEntry objectForKey:kMonitorPenaltyBoxKey]; + if([penalty intValue] != 0){ + NSMutableDictionary* existingQueue = [keyEntry valueForKey:kMonitorMessageQueue]; + + [existingQueue setObject:obj forKey:key]; + + [keyEntry setObject:existingQueue forKey:kMonitorMessageQueue]; + [_monitor setObject:keyEntry forKey:key]; + } + else{ + [SafeMessages setObject:obj forKey:key]; + } + }]; + return SafeMessages; +} + +// MARK: Object setting + + +- (void)setStoreObjectsFromDictionary:(NSDictionary *)values +{ + if (values == nil) { + secdebug(XPROXYSCOPE, "%@ NULL? values: %@", self, values); + return; + } + + NSMutableDictionary *mutableValues = [values mutableCopy]; + NSString* newDSID = asNSString([mutableValues extractObjectForKey:(__bridge NSString*) kSOSKVSOfficialDSIDKey]); + if (newDSID) { + _dsid = newDSID; + } + + NSString* requiredDSID = asNSString([mutableValues extractObjectForKey:(__bridge NSString*) kSOSKVSRequiredKey]); + if (requiredDSID) { + if (_dsid == nil || [_dsid isEqualToString: @""]) { + secdebug("dsid", "CloudKeychainProxy setting dsid to :%@ from securityd", requiredDSID); + _dsid = requiredDSID; + } else if (![_dsid isEqual: requiredDSID]) { + secerror("Account DSIDs do not match, cloud keychain proxy: %@, securityd: %@", _dsid, requiredDSID); + secerror("Not going to write these: %@ into KVS!", values); + return; + } else { + secnoticeq("dsid", "DSIDs match, writing"); + } + } + + secnoticeq("keytrace", "%@ sending: %@", self, [[mutableValues allKeys] componentsJoinedByString: @" "]); + [mutableValues enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) + { + if (obj == NULL || obj == [NSNull null]) { + [self.store removeObjectForKey:key]; + } else { + if ([key hasPrefix:@"ak|"]) { // TODO: somewhat of a hack + id oldObj = [self.store objectForKey:key]; + if ([oldObj isEqual: obj]) { + // Fix KVS repeated message undelivery by sending a NULL first (deafness) + secnoticeq("keytrace", "forcing resend of key write: %@", key); + [self.store removeObjectForKey:key]; + } + } + [self.store setObject:obj forKey:key]; + } + }]; + + [self.store pushWrites]; +} + +- (void)setObjectsFromDictionary:(NSDictionary *)values +{ + [[UbiqitousKVSProxy sharedKVSProxy] recordWriteToKVS: values]; + NSDictionary *safeValues = [[UbiqitousKVSProxy sharedKVSProxy] recordHaltedValuesAndReturnValuesToSafelyWrite: values]; + if([safeValues count] !=0){ + [[UbiqitousKVSProxy sharedKVSProxy] setStoreObjectsFromDictionary:safeValues]; + } +} + +- (void)waitForSynchronization:(void (^)(NSDictionary *results, NSError *err))handler +{ + secnoticeq("fresh", "%s Requesting WFS", kWAIT2MINID); + + [_freshnessCompletions addObject: ^(bool success, NSError *error){ + secnoticeq("fresh", "%s WFS Done", kWAIT2MINID); + handler(nil, error); + }]; + + if ([self.freshnessCompletions count] == 1) { + // We can't talk to synchronize on the _ckdkvsproxy_queue or we deadlock, + // bounce to a global concurrent queue + dispatch_after(_nextFreshnessTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSError *error = nil; + bool success = [self.store pullUpdates:&error]; + + dispatch_async(_ckdkvsproxy_queue, ^{ + [self waitForSyncDone: success error: error]; + }); + }); + } +} + +- (void) waitForSyncDone: (bool) success error: (NSError*) error{ + if (success) { + const uint64_t delayBeforeCallingAgainInSeconds = 5ull * NSEC_PER_SEC; + _nextFreshnessTime = dispatch_time(DISPATCH_TIME_NOW, delayBeforeCallingAgainInSeconds); + } + + secnoticeq("fresh", "%s Completing WFS", kWAIT2MINID); + [_freshnessCompletions enumerateObjectsUsingBlock:^(FreshnessResponseBlock _Nonnull block, + NSUInteger idx, + BOOL * _Nonnull stop) { + block(success, error); + }]; + [_freshnessCompletions removeAllObjects]; + +} + +// +// MARK: ----- KVS key lists ----- +// + + +- (NSDictionary*) exportKeyInterests +{ + return @{ kKeyAlwaysKeys:[_alwaysKeys allObjects], + kKeyFirstUnlockKeys:[_firstUnlockKeys allObjects], + kKeyUnlockedKeys:[_unlockedKeys allObjects], + kMonitorState:_monitor, + kKeyPendingKeys:[_pendingKeys allObjects], + kKeySyncWithPeersPending:[NSNumber numberWithBool:_syncWithPeersPending], + kKeyEnsurePeerRegistration:[NSNumber numberWithBool:_ensurePeerRegistration], + kKeyDSID:_dsid + }; +} + +- (void) importKeyInterests: (NSDictionary*) interests +{ + _alwaysKeys = [NSMutableSet setWithArray: interests[kKeyAlwaysKeys]]; + _firstUnlockKeys = [NSMutableSet setWithArray: interests[kKeyFirstUnlockKeys]]; + _unlockedKeys = [NSMutableSet setWithArray: interests[kKeyUnlockedKeys]]; + + _pendingKeys = [NSMutableSet setWithArray: interests[kKeyPendingKeys]]; + _syncWithPeersPending = [interests[kKeySyncWithPeersPending] boolValue]; + _ensurePeerRegistration = [interests[kKeyEnsurePeerRegistration] boolValue]; + _dsid = interests[kKeyDSID]; + _monitor = interests[kMonitorState]; + if(_monitor == nil) + _monitor = [NSMutableDictionary dictionary]; + +} + +- (NSMutableSet *)copyAllKeyInterests +{ + NSMutableSet *allKeys = [NSMutableSet setWithSet: _alwaysKeys]; + [allKeys unionSet: _firstUnlockKeys]; + [allKeys unionSet: _unlockedKeys]; + return allKeys; +} + +-(void)registerAtTimeKeys:(NSDictionary*)keyparms +{ + if (keyparms == nil) + return; + + NSArray *alwaysArray = [keyparms valueForKey: kKeyAlwaysKeys]; + NSArray *firstUnlockedKeysArray = [keyparms valueForKey: kKeyFirstUnlockKeys]; + NSArray *whenUnlockedKeysArray = [keyparms valueForKey: kKeyUnlockedKeys]; + + if(alwaysArray) + [_alwaysKeys unionSet: [NSMutableSet setWithArray: alwaysArray]]; + if(firstUnlockedKeysArray) + [_firstUnlockKeys unionSet: [NSMutableSet setWithArray: firstUnlockedKeysArray]]; + if(whenUnlockedKeysArray) + [_unlockedKeys unionSet: [NSMutableSet setWithArray: whenUnlockedKeysArray]]; +} + + +- (void)registerKeys: (NSDictionary*)keys +{ + secdebug(XPROXYSCOPE, "registerKeys: keys: %@", keys); + + NSMutableSet *allOldKeys = [self copyAllKeyInterests]; + + NSDictionary *keyparms = [keys valueForKey: [NSString stringWithUTF8String: kMessageKeyParameter]]; + NSDictionary *circles = [keys valueForKey: [NSString stringWithUTF8String: kMessageCircle]]; + NSDictionary *messages = [keys valueForKey: [NSString stringWithUTF8String: kMessageMessage]]; + + _alwaysKeys = [NSMutableSet set]; + _firstUnlockKeys = [NSMutableSet set]; + _unlockedKeys = [NSMutableSet set]; + + [self registerAtTimeKeys: keyparms]; + [self registerAtTimeKeys: circles]; + [self registerAtTimeKeys: messages]; + + NSMutableSet *allNewKeys = [self copyAllKeyInterests]; + + // Make sure keys we no longer care about are not pending + [_pendingKeys intersectSet:allNewKeys]; + if (_shadowPendingKeys) { + [_shadowPendingKeys intersectSet:allNewKeys]; + } + + // All new keys only is new keys (remove old keys) + [allNewKeys minusSet:allOldKeys]; + + // Mark new keys pending, they're new! + NSMutableSet *newKeysForCurrentLockState = [self pendKeysAndGetNewlyPended:allNewKeys]; + + [self persistState]; // Before we might call out, save our state so we recover if we crash + + [self intersectWithCurrentLockState: newKeysForCurrentLockState]; + // TODO: Don't processPendingKeysForCurrentLockState if none of the new keys have values. + if ([newKeysForCurrentLockState count] != 0) { + [self processPendingKeysForCurrentLockState]; + } +} + +// MARK: ----- Event Handling ----- + +- (void)streamEvent:(xpc_object_t)notification +{ +#if (!TARGET_IPHONE_SIMULATOR) + const char *notificationName = xpc_dictionary_get_string(notification, "Notification"); + if (!notificationName) { + } else if (strcmp(notificationName, kUserKeybagStateChangeNotification)==0) { + return [self keybagStateChange]; + } else if (strcmp(notificationName, kCloudKeychainStorechangeChangeNotification)==0) { + return [self kvsStoreChange]; + } else if (strcmp(notificationName, kNotifyTokenForceUpdate)==0) { + // DEBUG -- Possibly remove in future + return [self processAllItems]; + } + const char *eventName = xpc_dictionary_get_string(notification, "XPCEventName"); + char *desc = xpc_copy_description(notification); + secnotice("event", "%@ event: %s name: %s desc: %s", self, eventName, notificationName, desc); + if (desc) + free((void *)desc); +#endif +} + +- (void)storeKeysChanged: (NSSet*) changedKeys initial: (bool) initial +{ + // Mark that our store is talking to us, so we don't have to make up for missing anything previous. + _seenKVSStoreChange = YES; + + // Unmark them as pending as they have just changed and we'll process them. + [_pendingKeys minusSet:changedKeys]; + + // Only send values that we're currently interested in. + NSSet *keysOfInterestThatChanged = [self pendKeysAndGetPendingForCurrentLockState:changedKeys]; + NSMutableDictionary *changedValues = [self copyValues:keysOfInterestThatChanged]; + if (initial) + changedValues[(__bridge NSString*)kSOSKVSInitialSyncKey] = @"true"; + + secnotice("event", "%@ keysChangedInCloud: %@ keysOfInterest: %@ initial: %@", + self, + [[changedKeys allObjects] componentsJoinedByString: @" "], + [[changedValues allKeys] componentsJoinedByString: @" "], + initial ? @"YES" : @"NO"); + + if ([changedValues count]) + [self processKeyChangedEvent:changedValues]; +} + +- (void)storeAccountChanged +{ + secnotice("event", "%@", self); + + NSDictionary *changedValues = nil; + if(_dsid) + changedValues = @{ (__bridge NSString*)kSOSKVSAccountChangedKey: _dsid }; + else + changedValues = @{ (__bridge NSString*)kSOSKVSAccountChangedKey: @"true" }; + + [self processKeyChangedEvent:changedValues]; +} + +- (void) doAfterFlush: (dispatch_block_t) block +{ + //Flush any pending communication to Securityd. + if(!_inCallout) + dispatch_async(_calloutQueue, block); + else + _shadowFlushBlock = block; +} + +- (void) calloutWith: (void(^)(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *handledKeys, bool handledSyncWithPeers, bool handledEnsurePeerRegistration))) callout +{ + // In CKDKVSProxy's serial queue + + // dispatch_get_global_queue - well-known global concurrent queue + // dispatch_get_main_queue - default queue that is bound to the main thread + xpc_transaction_begin(); + dispatch_async(_calloutQueue, ^{ + __block NSSet *myPending; + __block bool mySyncWithPeersPending; + __block bool myEnsurePeerRegistration; + __block bool wasLocked; + dispatch_sync(_ckdkvsproxy_queue, ^{ + myPending = [_pendingKeys copy]; + mySyncWithPeersPending = _syncWithPeersPending; + myEnsurePeerRegistration = _ensurePeerRegistration; + wasLocked = _isLocked; + + _inCallout = YES; + + _shadowPendingKeys = [NSMutableSet set]; + _shadowSyncWithPeersPending = NO; + }); + + callout(myPending, mySyncWithPeersPending, myEnsurePeerRegistration, _ckdkvsproxy_queue, ^(NSSet *handledKeys, bool handledSyncWithPeers, bool handledEnsurePeerRegistration) { + secdebug("event", "%@ %s%s before callout handled: %s%s", self, mySyncWithPeersPending ? "S" : "s", myEnsurePeerRegistration ? "E" : "e", handledSyncWithPeers ? "S" : "s", handledEnsurePeerRegistration ? "E" : "e"); + + // In CKDKVSProxy's serial queue + _inCallout = NO; + + // Update ensurePeerRegistration + _ensurePeerRegistration = ((myEnsurePeerRegistration && !handledEnsurePeerRegistration) || _shadowEnsurePeerRegistration); + + _shadowEnsurePeerRegistration = NO; + + if(_ensurePeerRegistration && !_isLocked) + [self doEnsurePeerRegistration]; + + // Update SyncWithPeers stuff. + _syncWithPeersPending = ((mySyncWithPeersPending && (!handledSyncWithPeers)) || _shadowSyncWithPeersPending); + + _shadowSyncWithPeersPending = NO; + if (handledSyncWithPeers) + _lastSyncTime = dispatch_time(DISPATCH_TIME_NOW, 0); + + // Update pendingKeys and handle them + [_pendingKeys removeObject: [NSNull null]]; // Don't let NULL hang around + + [_pendingKeys minusSet: handledKeys]; + bool hadShadowPendingKeys = [_shadowPendingKeys count]; + // Move away shadownPendingKeys first, because pendKeysAndGetPendingForCurrentLockState + // will look at them. See rdar://problem/20733166. + NSSet *oldShadowPendingKeys = _shadowPendingKeys; + _shadowPendingKeys = nil; + + NSSet *filteredKeys = [self pendKeysAndGetPendingForCurrentLockState:oldShadowPendingKeys]; + + secnoticeq("keytrace", "%@ account handled: %@ pending: %@", self, + [[handledKeys allObjects] componentsJoinedByString: @" "], + [[filteredKeys allObjects] componentsJoinedByString: @" "]); + + // Write state to disk + [self persistState]; + + // Handle shadow pended stuff + if (_syncWithPeersPending && !_isLocked) + [self scheduleSyncRequestTimer]; + /* We don't want to call processKeyChangedEvent if we failed to + handle pending keys and the device didn't unlock nor receive + any kvs changes while we were in our callout. + Doing so will lead to securityd and CloudKeychainProxy + talking to each other forever in a tight loop if securityd + repeatedly returns an error processing the same message. + Instead we leave any old pending keys until the next event. */ + + if (hadShadowPendingKeys || (!_isLocked && wasLocked)){ + [self processKeyChangedEvent:[self copyValues:filteredKeys]]; + if(_shadowFlushBlock != NULL) + secerror("Flush block is not null and sending new keys"); + } + if(_shadowFlushBlock != NULL){ + dispatch_async(_calloutQueue, _shadowFlushBlock); + _shadowFlushBlock = NULL; + } + + xpc_transaction_end(); + }); + }); +} + +- (void) sendKeysCallout: (NSSet *(^)(NSSet* pending, NSError** error)) handleKeys { + [self calloutWith: ^(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *, bool, bool)) { + NSError* error = NULL; + + secnotice("CloudKeychainProxy", "send keys: %@", pending); + NSSet * handled = handleKeys(pending, &error); + + dispatch_async(queue, ^{ + if (!handled) { + secerror("%@ ensurePeerRegistration failed: %@", self, error); + } + + done(handled, NO, NO); + }); + }]; +} + +- (void) doEnsurePeerRegistration +{ + NSObject* accountDelegate = [self account]; + [self calloutWith:^(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *, bool, bool)) { + NSError* error = nil; + bool handledEnsurePeerRegistration = [accountDelegate ensurePeerRegistration:&error]; + secnotice("EnsurePeerRegistration", "%@ ensurePeerRegistration called, %@ (%@)", self, handledEnsurePeerRegistration ? @"success" : @"failure", error); + dispatch_async(queue, ^{ + done(nil, NO, handledEnsurePeerRegistration); + }); + }]; +} + +- (void) doSyncWithAllPeers +{ + NSObject* accountDelegate = [self account]; + [self calloutWith:^(NSSet *pending, bool syncWithPeersPending, bool ensurePeerRegistration, dispatch_queue_t queue, void(^done)(NSSet *, bool, bool)) { + NSError* error = NULL; + SyncWithAllPeersReason reason = [accountDelegate syncWithAllPeers: &error]; + dispatch_async(queue, ^{ + bool handledSyncWithPeers = NO; + if (reason == kSyncWithAllPeersSuccess) { + handledSyncWithPeers = YES; + secnotice("event", "%@ syncWithAllPeers succeeded", self); + } else if (reason == kSyncWithAllPeersLocked) { + secnotice("event", "%@ syncWithAllPeers attempted while locked - waiting for unlock", self); + handledSyncWithPeers = NO; + [self updateIsLocked]; + } else if (reason == kSyncWithAllPeersOtherFail) { + // Pretend we handled syncWithPeers, by pushing out the _lastSyncTime + // This will cause us to wait for kMinSyncInterval seconds before + // retrying, so we don't spam securityd if sync is failing + secerror("%@ syncWithAllPeers %@, rescheduling timer", self, error); + _lastSyncTime = dispatch_time(DISPATCH_TIME_NOW, 0); + } else { + secerror("%@ syncWithAllPeers %@, unknown reason: %d", self, error, reason); + } + + done(nil, handledSyncWithPeers, false); + }); + }]; +} + +- (void)timerFired +{ + secnotice("event", "%@ syncWithPeersPending: %d inCallout: %d isLocked: %d", self, _syncWithPeersPending, _inCallout, _isLocked); + _syncTimerScheduled = NO; + if(_ensurePeerRegistration){ + [self doEnsurePeerRegistration]; + } + if (_syncWithPeersPending && !_inCallout && !_isLocked){ + [self doSyncWithAllPeers]; + } +} + +- (dispatch_time_t) nextSyncTime +{ + dispatch_time_t nextSync = dispatch_time(DISPATCH_TIME_NOW, kMinSyncDelay); + + // Don't sync again unless we waited at least kMinSyncInterval + if (_lastSyncTime) { + dispatch_time_t soonest = dispatch_time(_lastSyncTime, kMinSyncInterval); + if (nextSync < soonest || _deadline < soonest) { + secdebug("timer", "%@ backing off", self); + return soonest; + } + } + + // Don't delay more than kMaxSyncDelay after the first request. + if (nextSync > _deadline) { + secdebug("timer", "%@ hit deadline", self); + return _deadline; + } + + // Bump the timer by kMinSyncDelay + if (_syncTimerScheduled) + secdebug("timer", "%@ bumped timer", self); + else + secdebug("timer", "%@ scheduled timer", self); + + return nextSync; +} + +- (void)scheduleSyncRequestTimer +{ + dispatch_source_set_timer(_syncTimer, [self nextSyncTime], DISPATCH_TIME_FOREVER, kSyncTimerLeeway); + _syncTimerScheduled = YES; +} + +- (void)requestSyncWithAllPeers // secd calling SOSCCSyncWithAllPeers invokes this +{ +#if !defined(NDEBUG) + NSString *desc = [self description]; +#endif + + if (!_syncWithPeersPending || (_inCallout && !_shadowSyncWithPeersPending)) + _deadline = dispatch_time(DISPATCH_TIME_NOW, kMaxSyncDelay); + + if (!_syncWithPeersPending) { + _syncWithPeersPending = YES; + [self persistState]; + } + + if (_inCallout) + _shadowSyncWithPeersPending = YES; + else if (!_isLocked) + [self scheduleSyncRequestTimer]; + + secdebug("event", "%@ %@", desc, self); +} + +- (void)requestEnsurePeerRegistration // secd calling SOSCCSyncWithAllPeers invokes this +{ +#if !defined(NDEBUG) + NSString *desc = [self description]; +#endif + + if (_inCallout) { + _shadowEnsurePeerRegistration = YES; + } else { + _ensurePeerRegistration = YES; + if (!_isLocked){ + [self doEnsurePeerRegistration]; + } + [self persistState]; + } + + secdebug("event", "%@ %@", desc, self); +} + + +- (BOOL) updateUnlockedSinceBoot +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetHasBeenUnlocked(&_unlockedSinceBoot, &aksError)) { + secerror("%@ Got error from SecAKSGetHasBeenUnlocked: %@", self, aksError); + CFReleaseSafe(aksError); + return NO; + } + return YES; +} + +- (BOOL) updateIsLocked +{ + CFErrorRef aksError = NULL; + if (!SecAKSGetIsLocked(&_isLocked, &aksError)) { + _isLocked = YES; + secerror("%@ Got error querying lock state: %@", self, aksError); + CFReleaseSafe(aksError); + return NO; + } + if (!_isLocked) + _unlockedSinceBoot = YES; + return YES; +} + +- (void) keybagStateChange +{ + os_activity_initiate("keybagStateChanged", OS_ACTIVITY_FLAG_DEFAULT, ^{ + BOOL wasLocked = _isLocked; + if ([self updateIsLocked]) { + if (wasLocked == _isLocked) + secdebug("event", "%@ still %s ignoring", self, _isLocked ? "locked" : "unlocked"); + else if (_isLocked) + [self keybagDidLock]; + else + [self keybagDidUnlock]; + } + }); +} + +- (void) keybagDidLock +{ + secnotice("event", "%@", self); +} + +- (void) keybagDidUnlock +{ + secnotice("event", "%@", self); + if (_ensurePeerRegistration) { + [self doEnsurePeerRegistration]; + } + + // First send changed keys to securityd so it can proccess updates + [self processPendingKeysForCurrentLockState]; + + // Then, tickle securityd to perform a sync if needed. + if (_syncWithPeersPending && !_syncTimerScheduled) { + [self doSyncWithAllPeers]; + } +} + +- (void) kvsStoreChange { + os_activity_initiate("kvsStoreChange", OS_ACTIVITY_FLAG_DEFAULT, ^{ + if (!_seenKVSStoreChange) { + secnotice("event", "%@ received darwin notification before first NSNotification", self); + // TODO This might not be needed if we always get the NSNotification + // deleived even if we were launched due to a kvsStoreChange + // Send all keys for current lock state to securityd so it can proccess them + [self pendKeysAndGetNewlyPended: [self copyAllKeyInterests]]; + [self processPendingKeysForCurrentLockState]; + } else { + secdebug("event", "%@ ignored, waiting for NSNotification", self); + } + }); +} + +// +// MARK: ----- Key Filtering ----- +// + +- (NSSet*) keysForCurrentLockState +{ + secdebug("filtering", "%@ Filtering: unlockedSinceBoot: %d\n unlocked: %d\n, keysOfInterest: <%@>", self, (int) _unlockedSinceBoot, (int) !_isLocked, [SOSPersistentState dictionaryDescription: [self exportKeyInterests]]); + + NSMutableSet *currentStateKeys = [NSMutableSet setWithSet: _alwaysKeys]; + if (_unlockedSinceBoot) + [currentStateKeys unionSet: _firstUnlockKeys]; + + if (!_isLocked) + [currentStateKeys unionSet: _unlockedKeys]; + + return currentStateKeys; +} + + +- (NSMutableSet*) pendKeysAndGetNewlyPended: (NSSet*) keysToPend +{ + NSMutableSet *filteredKeysToPend = [self copyAllKeyInterests]; + [filteredKeysToPend intersectSet: keysToPend]; + + NSMutableSet *newlyPendedKeys = [filteredKeysToPend mutableCopy]; + [newlyPendedKeys minusSet: _pendingKeys]; + if (_shadowPendingKeys) { + [newlyPendedKeys minusSet: _shadowPendingKeys]; + } + + if (_shadowPendingKeys) { + [_shadowPendingKeys unionSet:filteredKeysToPend]; + } + else{ + [_pendingKeys unionSet:filteredKeysToPend]; + } + + return newlyPendedKeys; +} + +- (void) intersectWithCurrentLockState: (NSMutableSet*) set +{ + [set intersectSet: [self keysForCurrentLockState]]; +} + +- (NSMutableSet*) pendingKeysForCurrentLockState +{ + NSMutableSet * result = [_pendingKeys mutableCopy]; + [self intersectWithCurrentLockState:result]; + return result; +} + +- (NSMutableSet*) pendKeysAndGetPendingForCurrentLockState: (NSSet*) startingSet +{ + [self pendKeysAndGetNewlyPended: startingSet]; + + return [self pendingKeysForCurrentLockState]; +} + +- (NSMutableDictionary *)copyValues:(NSSet*)keysOfInterest +{ + // Grab values from store. + NSObject *store = [self store]; + NSMutableDictionary *changedValues = [NSMutableDictionary dictionaryWithCapacity:0]; + [keysOfInterest enumerateObjectsUsingBlock:^(id obj, BOOL *stop) + { + NSString* key = (NSString*) obj; + id objval = [store objectForKey:key]; + if (!objval) objval = [NSNull null]; + + [changedValues setObject:objval forKey:key]; + secdebug(XPROXYSCOPE, "%@ storeChanged updated value for %@", self, key); + }]; + return changedValues; +} + +/* + During RegisterKeys, separate keys-of-interest into three disjoint sets: + - keys that we always want to be notified about; this means we can get the + value at any time + - keys that require the device to have been unlocked at least once + - keys that require the device to be unlocked now + + Typically, the sets of keys will be: + + - Dk: alwaysKeys + - Ck: firstUnlock + - Ak: unlocked + + The caller is responsible for making sure that the keys in e.g. alwaysKeys are + values that can be handled at any time (that is, not when unlocked) + + Each time we get a notification from ubiquity that keys have changed, we need to + see if anything of interest changed. If we don't care, then done. + + For each key-of-interest that changed, we either notify the client that things + changed, or add it to a pendingNotifications list. If the notification to the + client fails, also add it to the pendingNotifications list. This pending list + should be written to persistent storage and consulted any time we either get an + item changed notification, or get a stream event signalling a change in lock state. + + We can notify the client either through XPC if a connection is set up, or call a + routine in securityd to launch it. + + */ + +- (void)processKeyChangedEvent:(NSDictionary *)changedValues +{ + NSMutableDictionary* filtered = [NSMutableDictionary dictionary]; + + secnotice("processKeyChangedEvent", "changedValues:%@", changedValues); + NSMutableArray* nullKeys = [NSMutableArray array]; + // Remove nulls because we don't want them in securityd. + [changedValues enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + if (obj == [NSNull null]){ + [nullKeys addObject:key]; + }else{ + filtered[key] = obj; + } + }]; + if ([nullKeys count]) + [_pendingKeys minusSet: [NSSet setWithArray: nullKeys]]; + + if([filtered count] != 0 ) { + [self sendKeysCallout:^NSSet *(NSSet *pending, NSError** error) { + secnotice("processing keys", "pending:%@", pending); + NSError *updateError = nil; + return [[self account] keysChanged: filtered error: &updateError]; + }]; + } else { + secnoticeq("keytrace", "%@ null: %@ pending: %@", self, + [nullKeys componentsJoinedByString: @" "], + [[_pendingKeys allObjects] componentsJoinedByString: @" "]); + } +} + +- (void) processPendingKeysForCurrentLockState +{ + [self processKeyChangedEvent: [self copyValues: [self pendingKeysForCurrentLockState]]]; +} + +@end + + diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.h b/KVSKeychainSyncingProxy/CKDKVSStore.h new file mode 100644 index 00000000..6dabc84f --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDKVSStore.h @@ -0,0 +1,32 @@ +// +// CKDKVSStore.h +// + +#import + +#import "CKDStore.h" +#import "CKDKVSProxy.h" + +@interface CKDKVSStore : NSObject + ++ (instancetype)kvsInterface; +- (instancetype)init; + +- (void)connectToProxy: (UbiqitousKVSProxy*) proxy; + +- (NSObject*)objectForKey:(NSString*)key; + +- (void)setObject:(id)obj forKey:(NSString*)key; +- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary; + +- (void)removeObjectForKey:(NSString*)key; +- (void)removeAllObjects; + +- (NSDictionary*) copyAsDictionary; + +- (void)pushWrites; +- (BOOL)pullUpdates:(NSError**) failure; + +- (void)kvsStoreChanged: (NSNotification*) notification; + +@end diff --git a/KVSKeychainSyncingProxy/CKDKVSStore.m b/KVSKeychainSyncingProxy/CKDKVSStore.m new file mode 100644 index 00000000..5ce77181 --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDKVSStore.m @@ -0,0 +1,208 @@ +// +// CKDKVSStore.m +// Security +// +// Created by Mitch Adler on 5/15/16. +// +// + +#import "CKDKVSStore.h" +#import "CKDKVSProxy.h" + +#include "SOSCloudKeychainConstants.h" +#include + +#import +#import +#import "SyncedDefaults/SYDConstants.h" +#include + +//KVS error codes +#define UPDATE_RESUBMIT 4 + +@interface CKDKVSStore () +@property (readwrite, weak) UbiqitousKVSProxy* proxy; +@property (readwrite) NSUbiquitousKeyValueStore* cloudStore; +@end + +@implementation CKDKVSStore + ++ (instancetype)kvsInterface { + return [[CKDKVSStore alloc] init]; +} + +- (instancetype)init { + self = [super init]; + + self->_cloudStore = [NSUbiquitousKeyValueStore defaultStore]; + self->_proxy = nil; + + if (!self.cloudStore) { + secerror("NO NSUbiquitousKeyValueStore defaultStore!!!"); + return nil; + } + + return self; +} + +- (void) connectToProxy: (UbiqitousKVSProxy*) proxy { + _proxy = proxy; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(kvsStoreChanged:) + name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification + object:nil]; + +} + +- (void)setObject:(id)obj forKey:(NSString*)key { + NSUbiquitousKeyValueStore *store = [self cloudStore]; + if (store) + { + id value = [store objectForKey:key]; + if (value) + secdebug("kvsdebug", "%@ key %@ changed: %@ to: %@", self, key, value, obj); + else + secdebug("kvsdebug", "%@ key %@ initialized to: %@", self, key, obj); + [store setObject:obj forKey:key]; + [self pushWrites]; + } else { + secerror("Can't get kvs store, key: %@ not set to: %@", key, obj); + } +} + +- (NSDictionary*) copyAsDictionary { + return [self.cloudStore dictionaryRepresentation]; +} + +- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary { + [otherDictionary enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSObject * _Nonnull obj, BOOL * _Nonnull stop) { + [self setObject:obj forKey:key]; + }]; +} + +- (id)objectForKey:(NSString*)key { + return [self.cloudStore objectForKey:key]; +} + +- (void)removeObjectForKey:(NSString*)key { + return [self.cloudStore removeObjectForKey:key]; +} + +- (void)removeAllObjects { + [[[[self.cloudStore dictionaryRepresentation] allKeys] copy] enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + [self.cloudStore removeObjectForKey:obj]; + }]; +} + +- (void)pushWrites { + [[self cloudStore] synchronize]; +} + +- (void) kvsStoreChanged:(NSNotification *)notification { + /* + Posted when the value of one or more keys in the local key-value store + changed due to incoming data pushed from iCloud. This notification is + sent only upon a change received from iCloud; it is not sent when your + app sets a value. + + The user info dictionary can contain the reason for the notification as + well as a list of which values changed, as follows: + + The value of the NSUbiquitousKeyValueStoreChangeReasonKey key, when + present, indicates why the key-value store changed. Its value is one of + the constants in "Change Reason Values." + + The value of the NSUbiquitousKeyValueStoreChangedKeysKey, when present, + is an array of strings, each the name of a key whose value changed. The + notification object is the NSUbiquitousKeyValueStore object whose contents + changed. + + NSUbiquitousKeyValueStoreInitialSyncChange is only posted if there is any + local value that has been overwritten by a distant value. If there is no + conflict between the local and the distant values when doing the initial + sync (e.g. if the cloud has no data stored or the client has not stored + any data yet), you'll never see that notification. + + NSUbiquitousKeyValueStoreInitialSyncChange implies an initial round trip + with server but initial round trip with server does not imply + NSUbiquitousKeyValueStoreInitialSyncChange. + */ + os_activity_initiate("cloudChanged", OS_ACTIVITY_FLAG_DEFAULT, ^{ + secdebug(XPROXYSCOPE, "%@ KVS Remote changed notification: %@", self, notification); + + NSDictionary *userInfo = [notification userInfo]; + NSNumber *reason = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey]; + NSArray *keysChangedArray = [userInfo objectForKey:NSUbiquitousKeyValueStoreChangedKeysKey]; + NSSet *keysChanged = keysChangedArray ? [NSSet setWithArray: keysChangedArray] : nil; + + if (reason) switch ([reason integerValue]) { + case NSUbiquitousKeyValueStoreInitialSyncChange: + [self.proxy storeKeysChanged: keysChanged initial: YES]; + break; + + case NSUbiquitousKeyValueStoreServerChange: + [self.proxy storeKeysChanged: keysChanged initial: NO]; + break; + + case NSUbiquitousKeyValueStoreQuotaViolationChange: + seccritical("Received NSUbiquitousKeyValueStoreQuotaViolationChange"); + break; + + case NSUbiquitousKeyValueStoreAccountChange: + [self.proxy storeAccountChanged]; + break; + + default: + secinfo("kvsstore", "ignoring unknown notification: %@", reason); + break; + } + }); +} + +// try to synchronize asap, and invoke the handler on completion to take incoming changes. + +static bool isResubmitError(NSError* error) { + return error && (CFErrorGetCode((__bridge CFErrorRef) error) == UPDATE_RESUBMIT) && + (CFErrorGetDomain((__bridge CFErrorRef)error) == __SYDErrorKVSDomain); +} + +- (BOOL) pullUpdates:(NSError **)failure +{ + __block NSError *tempFailure = nil; + const int kMaximumTries = 10; + int tryCount = 0; + // Retry up to 10 times, since we're told this can fail and WE have to deal with it. + + dispatch_semaphore_t freshSemaphore = dispatch_semaphore_create(0); + + do { + ++tryCount; + secnoticeq("fresh", "%s CALLING OUT TO syncdefaultsd SWCH, try %d: %@", kWAIT2MINID, tryCount, self); + + [[self cloudStore] synchronizeWithCompletionHandler:^(NSError *error) { + if (error) { + tempFailure = error; + secnotice("fresh", "%s RETURNING FROM syncdefaultsd SWCH: %@: %@", kWAIT2MINID, self, error); + } else { + 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); + } + dispatch_semaphore_signal(freshSemaphore); + }]; + dispatch_semaphore_wait(freshSemaphore, DISPATCH_TIME_FOREVER); + } while (tryCount < kMaximumTries && isResubmitError(tempFailure)); + + if (isResubmitError(tempFailure)) { + secerrorq("%s %d retry attempts to request freshness exceeded, failing", kWAIT2MINID, tryCount); + } + + if (failure && (*failure == NULL)) { + *failure = tempFailure; + } + + return tempFailure == nil; +} + +@end diff --git a/OSX/sec/SOSCircle/osxshim.c b/KVSKeychainSyncingProxy/CKDPersistentState.h similarity index 68% rename from OSX/sec/SOSCircle/osxshim.c rename to KVSKeychainSyncingProxy/CKDPersistentState.h index 845d8d32..22934752 100644 --- a/OSX/sec/SOSCircle/osxshim.c +++ b/KVSKeychainSyncingProxy/CKDPersistentState.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2012-2014 Apple Inc. All Rights Reserved. - * + * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code @@ -21,20 +21,23 @@ * @APPLE_LICENSE_HEADER_END@ */ +// +// SOSPersistentState.h +// ckdxpc +// -#include -#include - -typedef void *SOSDataSourceFactoryRef; -//typedef void *SOSAccountRef; +#import -// XXX Need to plumb these from security to secd. If we can. +@interface SOSPersistentState : NSObject +{ +} -typedef SOSDataSourceFactoryRef (^AccountDataSourceFactoryBlock)(); ++ (id)read:(NSURL *)path error:(NSError **)error; ++ (BOOL)write:(NSURL *)path data:(id)plist error:(NSError **)error; ++ (NSString *)dictionaryDescription: (NSDictionary *)state; ++ (NSMutableDictionary *)registeredKeys; ++ (void)setRegisteredKeys: (NSDictionary *)keysToRegister; ++ (NSURL *)registrationFileURL; -bool SOSKeychainAccountSetFactoryForAccount(AccountDataSourceFactoryBlock factory); +@end -bool SOSKeychainAccountSetFactoryForAccount(AccountDataSourceFactoryBlock factory) -{ - return false; -} diff --git a/KVSKeychainSyncingProxy/CKDPersistentState.m b/KVSKeychainSyncingProxy/CKDPersistentState.m new file mode 100644 index 00000000..9eb1e17c --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDPersistentState.m @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012-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@ + */ + +// +// SOSPersistentState.m +// ckdxpc +// + +#import +#import +#import +#import +#import +#import +#import +#import + +#import "CKDPersistentState.h" + +#if ! __has_feature(objc_arc) +#error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag +#endif + +// may want to have this hold incoming events in file as well + +// TODO: Sandbox stuff + +static CFStringRef kRegistrationFileName = CFSTR("com.apple.security.cloudkeychainproxy3.keysToRegister.plist"); + +@implementation SOSPersistentState + ++ (BOOL)write:(NSURL *)path data:(id)plist error:(NSError **)error +{ + if (![NSPropertyListSerialization propertyList: plist isValidForFormat: NSPropertyListXMLFormat_v1_0]) + { + secerror("can't save PersistentState as XML"); + return false; + } + + NSData *data = [NSPropertyListSerialization dataWithPropertyList: plist + format: NSPropertyListXMLFormat_v1_0 options: 0 error: error]; + if (data == nil) + { + secerror("error serializing PersistentState to xml: %@", *error); + return false; + } + + BOOL writeStatus = [data writeToURL: path options: NSDataWritingAtomic error: error]; + if (!writeStatus) + secerror("error writing PersistentState to file: %@", *error); + + return writeStatus; +} + ++ (id)read: (NSURL *)path error:(NSError **)error +{ + NSData *data = [NSData dataWithContentsOfURL: path options: 0 error: error]; + if (data == nil) + { + secdebug("keyregister", "error reading PersistentState from %@: %@", path, *error); + return nil; + } + + // Now the deserializing: + + NSPropertyListFormat format; + id plist = [NSPropertyListSerialization propertyListWithData: data + options: NSPropertyListMutableContainersAndLeaves format: &format error: error]; + + if (plist == nil) + secerror("could not deserialize PersistentState from %@: %@", path, *error); + + return plist; +} + ++ (NSURL *)registrationFileURL +{ + return (NSURL *)CFBridgingRelease(SecCopyURLForFileInPreferencesDirectory(kRegistrationFileName)); +} + ++ (NSString *)dictionaryDescription: (NSDictionary *)state +{ + NSMutableArray *elements = [NSMutableArray array]; + [state enumerateKeysAndObjectsUsingBlock: ^(NSString *key, id obj, BOOL *stop) { + [elements addObject: [key stringByAppendingString: @":"]]; + if ([obj isKindOfClass:[NSArray class]]) { + [elements addObject: [(NSArray *)obj componentsJoinedByString: @" "]]; + } else { + [elements addObject: [NSString stringWithFormat:@"%@", obj]]; + } + }]; + return [elements componentsJoinedByString: @" "]; +} + ++ (NSMutableDictionary *)registeredKeys +{ + NSError *error = NULL; + id stateDictionary = [SOSPersistentState read:[[self class] registrationFileURL] error:&error]; + secdebug("keyregister", "Read registeredKeys: <%@>", [self dictionaryDescription: stateDictionary]); + // Ignore older states with an NSArray + if (![stateDictionary isKindOfClass:[NSDictionary class]]) + return NULL; + return [NSMutableDictionary dictionaryWithDictionary:stateDictionary]; +} + ++ (void)setRegisteredKeys: (NSDictionary *)keysToRegister +{ + NSError *error = NULL; + secdebug("keyregister", "Write registeredKeys: <%@>", [self dictionaryDescription: keysToRegister]); + [SOSPersistentState write:[[self class] registrationFileURL] data:keysToRegister error:&error]; +} + +@end diff --git a/KVSKeychainSyncingProxy/CKDSecuritydAccount.h b/KVSKeychainSyncingProxy/CKDSecuritydAccount.h new file mode 100644 index 00000000..930329e6 --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDSecuritydAccount.h @@ -0,0 +1,19 @@ +// +// CKDSecuritydAccount.h +// Security +// +// + + +#include "CKDAccount.h" +#include + +@interface CKDSecuritydAccount : NSObject + ++ (instancetype) securitydAccount; + +- (NSSet*) keysChanged: (NSDictionary*) keyValues error: (NSError**) error; +- (bool) ensurePeerRegistration: (NSError**) error; +- (SyncWithAllPeersReason) syncWithAllPeers: (NSError**) error; + +@end diff --git a/KVSKeychainSyncingProxy/CKDSecuritydAccount.m b/KVSKeychainSyncingProxy/CKDSecuritydAccount.m new file mode 100644 index 00000000..07d98f9e --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDSecuritydAccount.m @@ -0,0 +1,55 @@ +// +// CKDSecuritydAccount+CKDSecuritydAccount_m.m +// Security +// +// + +#import "Foundation/Foundation.h" +#import "CKDSecuritydAccount.h" + +#include +#include + +@implementation CKDSecuritydAccount + ++ (instancetype) securitydAccount +{ + return [[CKDSecuritydAccount alloc] init]; +} + +- (NSSet*) keysChanged: (NSDictionary*)keyValues error: (NSError**) error +{ + CFErrorRef cf_error = NULL; + NSArray* handled = (__bridge_transfer NSArray*) _SecKeychainSyncUpdateMessage((__bridge CFDictionaryRef)keyValues, &cf_error); + NSError *updateError = (__bridge_transfer NSError*)cf_error; + if (error) + *error = updateError; + + return [NSSet setWithArray:handled]; +} + +- (bool) ensurePeerRegistration: (NSError**) error +{ + CFErrorRef localError = NULL; + bool result = SOSCCProcessEnsurePeerRegistration(error ? &localError : NULL); + + if (error && localError) { + *error = (__bridge_transfer NSError*) localError; + } + + return result; +} + +- (SyncWithAllPeersReason) syncWithAllPeers: (NSError**) error +{ + CFErrorRef localError = NULL; + SyncWithAllPeersReason result = SOSCCProcessSyncWithAllPeers(error ? &localError : NULL); + + if (error && localError) { + *error = (__bridge_transfer NSError*) localError; + } + + return result; +} + +@end diff --git a/KVSKeychainSyncingProxy/CKDStore.h b/KVSKeychainSyncingProxy/CKDStore.h new file mode 100644 index 00000000..53dc2679 --- /dev/null +++ b/KVSKeychainSyncingProxy/CKDStore.h @@ -0,0 +1,28 @@ +// +// CKDStore.h +// Security +// +// + +#import + +@class UbiqitousKVSProxy; + +@protocol CKDStore + +- (void)connectToProxy: (UbiqitousKVSProxy*) proxy; + +- (NSObject*)objectForKey:(NSString*)key; + +- (void)setObject:(id)obj forKey:(NSString*)key; +- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary; + +- (void)removeObjectForKey:(NSString*)key; +- (void)removeAllObjects; + +- (NSDictionary*) copyAsDictionary; + +- (void)pushWrites; +- (BOOL)pullUpdates:(NSError**) failure; + +@end diff --git a/CloudKeychainProxy/CloudKeychainProxy-Info.plist b/KVSKeychainSyncingProxy/CloudKeychainProxy-Info.plist similarity index 93% rename from CloudKeychainProxy/CloudKeychainProxy-Info.plist rename to KVSKeychainSyncingProxy/CloudKeychainProxy-Info.plist index 132f0435..5678d775 100644 --- a/CloudKeychainProxy/CloudKeychainProxy-Info.plist +++ b/KVSKeychainSyncingProxy/CloudKeychainProxy-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.apple.security.cloudkeychainproxy3 + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/CloudKeychainProxy/cloudkeychain.entitlements.plist b/KVSKeychainSyncingProxy/cloudkeychain.entitlements.plist similarity index 96% rename from OSX/CloudKeychainProxy/cloudkeychain.entitlements.plist rename to KVSKeychainSyncingProxy/cloudkeychain.entitlements.plist index 46c70ef7..b39e11a1 100644 --- a/OSX/CloudKeychainProxy/cloudkeychain.entitlements.plist +++ b/KVSKeychainSyncingProxy/cloudkeychain.entitlements.plist @@ -11,7 +11,6 @@ keychain-access-groups sync - * com.apple.developer.ubiquity-kvstore-identifier com.apple.security.cloudkeychainproxy3 diff --git a/KVSKeychainSyncingProxy/cloudkeychainproxy.m b/KVSKeychainSyncingProxy/cloudkeychainproxy.m new file mode 100644 index 00000000..ae78aa49 --- /dev/null +++ b/KVSKeychainSyncingProxy/cloudkeychainproxy.m @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2012-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@ + */ + +// +// main.m +// ckd-xpc +// +// + +/* + This XPC service is essentially just a proxy to iCloud KVS, which exists since + the main security code cannot link against Foundation. + + See sendTSARequestWithXPC in tsaSupport.c for how to call the service + + send message to app with xpc_connection_send_message + + For now, build this with: + + ~rc/bin/buildit . --rootsDirectory=/var/tmp -noverify -offline -target CloudKeychainProxy + + and install or upgrade with: + + darwinup install /var/tmp/sec.roots/sec~dst + darwinup upgrade /var/tmp/sec.roots/sec~dst + + You must use darwinup during development to update system caches +*/ + +//------------------------------------------------------------------------------------------------ + +#include + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#include +#include +#include + +#import "CKDKVSProxy.h" + +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); + +int ckdproxymain(int argc, const char *argv[]); + +#define PROXYXPCSCOPE "xpcproxy" + +static void describeXPCObject(char *prefix, xpc_object_t object) +{ +//#ifndef NDEBUG + // This is useful for debugging. + if (object) + { + char *desc = xpc_copy_description(object); + secdebug(PROXYXPCSCOPE, "%s%s\n", prefix, desc); + free(desc); + } + else + secdebug(PROXYXPCSCOPE, "%s\n", prefix); + +//#endif +} + +static void cloudkeychainproxy_peer_dictionary_handler(const xpc_connection_t peer, 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"); + + const char *operation = xpc_dictionary_get_string(event, kMessageKeyOperation); + require_action(operation, xit, result = false); + + // 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); + + // Operations + secdebug(PROXYXPCSCOPE, "Handling %s operation", operation); + + + if (operation && !strcmp(operation, kOperationPUTDictionary)) + { + operation_put_dictionary(event); + } + else if (operation && !strcmp(operation, kOperationGETv2)) + { + operation_get_v2(peer, event); + } + else if (operation && !strcmp(operation, kOperationClearStore)) + { + [[UbiqitousKVSProxy sharedKVSProxy] clearStore]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + } + else if (operation && !strcmp(operation, kOperationSynchronize)) + { + [[UbiqitousKVSProxy sharedKVSProxy] synchronizeStore]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + } + else if (operation && !strcmp(operation, kOperationSynchronizeAndWait)) + { + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + secnotice(XPROXYSCOPE, "%s XPC request: %s", kWAIT2MINID, kOperationSynchronizeAndWait); + + [[UbiqitousKVSProxy sharedKVSProxy] waitForSynchronization:^(__unused NSDictionary *values, NSError *error) + { + secnotice(PROXYXPCSCOPE, "%s Result from [[UbiqitousKVSProxy sharedKVSProxy] waitForSynchronization:]: %@", kWAIT2MINID, error); + + if (replyMessage) // Caller wanted an ACK, so give one + { + 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); + } + }]; + } + else if (operation && !strcmp(operation, kOperationRegisterKeys)) + { + xpc_object_t xkeysToRegisterDict = xpc_dictionary_get_value(event, kMessageKeyValue); + + xpc_object_t xKTRallkeys = xpc_dictionary_get_value(xkeysToRegisterDict, kMessageAllKeys); + + NSDictionary *KTRallkeys = (__bridge_transfer NSDictionary *)(_CFXPCCreateCFObjectFromXPCObject(xKTRallkeys)); + + [[UbiqitousKVSProxy sharedKVSProxy] registerKeys: KTRallkeys]; + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + + secdebug(PROXYXPCSCOPE, "RegisterKeys message sent"); + } + else if (operation && !strcmp(operation, kOperationRequestSyncWithAllPeers)) + { + [[UbiqitousKVSProxy sharedKVSProxy] requestSyncWithAllPeers]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + secdebug(PROXYXPCSCOPE, "RequestSyncWithAllPeers reply sent"); + } + else if (operation && !strcmp(operation, kOperationRequestEnsurePeerRegistration)) + { + [[UbiqitousKVSProxy sharedKVSProxy] requestEnsurePeerRegistration]; + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + secdebug(PROXYXPCSCOPE, "RequestEnsurePeerRegistration reply sent"); + } + else if (operation && !strcmp(operation, kOperationFlush)) + { + [[UbiqitousKVSProxy sharedKVSProxy] doAfterFlush:^{ + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (replyMessage) // Caller wanted an ACK, so give one + { + xpc_dictionary_set_string(replyMessage, kMessageKeyValue, "ACK"); + xpc_connection_send_message(peer, replyMessage); + } + secdebug(PROXYXPCSCOPE, "flush reply sent"); + }]; + } + 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; +xit: + if (!result) + describeXPCObject("handle_operation fail: ", event); +} + +void finalize_connection(void *not_used) +{ + secdebug(PROXYXPCSCOPE, "finalize_connection"); + [[UbiqitousKVSProxy sharedKVSProxy] synchronizeStore]; + xpc_transaction_end(); +} + +static bool operation_put_dictionary(xpc_object_t event) +{ + // PUT a set of objects into the KVS store. Return false if error + describeXPCObject("operation_put_dictionary event: ", event); + xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); + if (!xvalue) { + return false; + } + + NSObject* object = (__bridge_transfer NSObject*) _CFXPCCreateCFObjectFromXPCObject(xvalue); + if (![object isKindOfClass:[NSDictionary class]]) { + describeXPCObject("operation_put_dictionary unable to convert to CF: ", xvalue); + return false; + } + + [[UbiqitousKVSProxy sharedKVSProxy] setObjectsFromDictionary: (NSDictionary *)object]; + + return true; +} + +static bool operation_get_v2(xpc_connection_t peer, xpc_object_t event) +{ + // GET a set of objects from the KVS store. Return false if error + describeXPCObject("operation_get_v2 event: ", event); + + xpc_object_t replyMessage = xpc_dictionary_create_reply(event); + if (!replyMessage) + { + secdebug(PROXYXPCSCOPE, "can't create replyMessage"); + assert(true); //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"); + assert(true); // must have a spot for the returned values + return false; + } + + xpc_object_t xvalue = xpc_dictionary_get_value(event, kMessageKeyValue); + if (!xvalue) + { + secdebug(PROXYXPCSCOPE, "missing \"value\" key"); + return false; + } + + xpc_object_t xkeystoget = xpc_dictionary_get_value(xvalue, kMessageKeyKeysToGet); + if (xkeystoget) + { + secdebug(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"); + CFReleaseSafe(keystoget); + return false; + } + + [(__bridge NSArray *)keystoget enumerateObjectsUsingBlock: ^ (id obj, NSUInteger idx, BOOL *stop) + { + NSString *key = (NSString *)obj; + id object = [[UbiqitousKVSProxy sharedKVSProxy] objectForKey:key]; + secdebug(PROXYXPCSCOPE, "[UbiqitousKVSProxy sharedKVSProxy] 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); + describeXPCObject("operation_get_v2: value from kvs: ", xobject); + }]; + } + else // get all values from kvs + { + secdebug(PROXYXPCSCOPE, "get all values from kvs"); + NSDictionary *all = [[UbiqitousKVSProxy sharedKVSProxy] copyAsDictionary]; + [all enumerateKeysAndObjectsUsingBlock: ^ (id key, id obj, BOOL *stop) + { + xpc_object_t xobject = obj ? _CFXPCCreateXPCObjectFromCFObject((__bridge CFTypeRef)obj) : xpc_null_create(); + xpc_dictionary_set_value(returnedValues, [(NSString *)key UTF8String], xobject); + }]; + } + + xpc_dictionary_set_uint64(replyMessage, kMessageKeyVersion, kCKDXPCVersion); + xpc_dictionary_set_value(replyMessage, kMessageKeyValue, returnedValues); + xpc_connection_send_message(peer, replyMessage); + + return true; +} + +static void cloudkeychainproxy_peer_event_handler(xpc_connection_t peer, xpc_object_t event) +{ + describeXPCObject("peer: ", peer); + xpc_type_t type = xpc_get_type(event); + if (type == XPC_TYPE_ERROR) { + if (event == XPC_ERROR_CONNECTION_INVALID) { + // The client process on the other end of the connection has either + // crashed or cancelled the connection. After receiving this error, + // the connection is in an invalid state, and you do not need to + // call xpc_connection_cancel(). Just tear down any associated state + // here. + } else if (event == XPC_ERROR_TERMINATION_IMMINENT) { + // Handle per-connection termination cleanup. + } + } else { + assert(type == XPC_TYPE_DICTIONARY); + // Handle the message. + // describeXPCObject("dictionary:", event); + dispatch_async(dispatch_get_main_queue(), ^{ + cloudkeychainproxy_peer_dictionary_handler(peer, event); + }); + } +} + +static void cloudkeychainproxy_event_handler(xpc_connection_t peer) +{ + // By defaults, new connections will target the default dispatch + // concurrent queue. + + if (xpc_get_type(peer) != XPC_TYPE_CONNECTION) + { + secdebug(PROXYXPCSCOPE, "expected XPC_TYPE_CONNECTION"); + return; + } + + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) + { + cloudkeychainproxy_peer_event_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); +} + +static void diagnostics(int argc, const char *argv[]) +{ + @autoreleasepool + { + NSDictionary *all = [[UbiqitousKVSProxy sharedKVSProxy] copyAsDictionary]; + NSLog(@"All: %@",all); + } +} + +int ckdproxymain(int argc, const char *argv[]) +{ + secdebug(PROXYXPCSCOPE, "Starting CloudKeychainProxy"); + char *wait4debugger = getenv("WAIT4DEBUGGER"); + + if (wait4debugger && !strcasecmp("YES", wait4debugger)) + { + syslog(LOG_ERR, "Waiting for debugger"); + kill(getpid(), SIGTSTP); + } + + if (argc > 1) { + diagnostics(argc, argv); + return 0; + } + + id proxyID = [UbiqitousKVSProxy sharedKVSProxy]; + + if (proxyID) { // nothing bad happened when initializing + + + xpc_connection_t listener = xpc_connection_create_mach_service(xpcServiceName, 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]; + } + } + + secdebug(PROXYXPCSCOPE, "Exiting CloudKeychainProxy"); + + return EXIT_FAILURE; +} + +int main(int argc, const char *argv[]) +{ + return ckdproxymain(argc, argv); +} diff --git a/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist b/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist similarity index 100% rename from CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist rename to KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.ios.plist diff --git a/OSX/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist b/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist similarity index 98% rename from OSX/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist rename to KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist index c9056a14..b841f7f2 100644 --- a/OSX/CloudKeychainProxy/com.apple.security.cloudkeychainproxy.plist +++ b/KVSKeychainSyncingProxy/com.apple.security.cloudkeychainproxy3.osx.plist @@ -28,7 +28,7 @@ EnvironmentVariables DEBUGSCOPE - none + all WAIT4DEBUGGER NO diff --git a/Keychain/KCATableViewController.m b/Keychain/KCATableViewController.m index 78b3bfbd..ded63880 100644 --- a/Keychain/KCATableViewController.m +++ b/Keychain/KCATableViewController.m @@ -279,7 +279,6 @@ nd[(NSString *)kCFUserNotificationAlertMessageKey] = @"To view details"; nd[(NSString *)kCFUserNotificationDefaultButtonTitleKey] = @"OK"; nd[(NSString *)kCFUserNotificationAlternateButtonTitleKey] = @"Cancel"; - nd[(__bridge __strong id)(SBUserNotificationGroupsTextFields)] = (__bridge id)(kCFBooleanTrue); nd[(NSString *)kCFUserNotificationTextFieldTitlesKey] = @[@"Passcode"]; nd[(__bridge NSString *)SBUserNotificationTextAutocapitalizationType] = @[ @(NO_AUTOCAPITALIZATION) ]; nd[(__bridge NSString *)SBUserNotificationTextAutocapitalizationType] = @[ @(NO_AUTOCORRECTION) ]; diff --git a/Keychain/Keychain-Info.plist b/Keychain/Keychain-Info.plist index 98556e5b..b27b1b31 100644 --- a/Keychain/Keychain-Info.plist +++ b/Keychain/Keychain-Info.plist @@ -22,7 +22,7 @@ CFBundleIdentifier - com.apple.security.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -37,14 +37,12 @@ ${CURRENT_PROJECT_VERSION} LSRequiresIPhoneOS + UIRequiresFullScreen + UIMainStoryboardFile MainStoryboard_iPhone UIMainStoryboardFile~ipad MainStoryboard_iPhone - UIRequiredDeviceCapabilities - - armv7 - UIStatusBarTintParameters UINavigationBar diff --git a/Keychain_114x114.png b/Keychain/Keychain_114x114.png similarity index 100% rename from Keychain_114x114.png rename to Keychain/Keychain_114x114.png diff --git a/Keychain_144x144.png b/Keychain/Keychain_144x144.png similarity index 100% rename from Keychain_144x144.png rename to Keychain/Keychain_144x144.png diff --git a/Keychain_57x57.png b/Keychain/Keychain_57x57.png similarity index 100% rename from Keychain_57x57.png rename to Keychain/Keychain_57x57.png diff --git a/Keychain_72x72.png b/Keychain/Keychain_72x72.png similarity index 100% rename from Keychain_72x72.png rename to Keychain/Keychain_72x72.png diff --git a/KeychainCircle/Info.plist b/KeychainCircle/Info.plist new file mode 100644 index 00000000..d3de8eef --- /dev/null +++ b/KeychainCircle/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/KeychainCircle/KCAESGCMDuplexSession.h b/KeychainCircle/KCAESGCMDuplexSession.h new file mode 100644 index 00000000..0304f1d1 --- /dev/null +++ b/KeychainCircle/KCAESGCMDuplexSession.h @@ -0,0 +1,38 @@ +// +// KCAESGCMDuplexSession.h +// Security +// +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KCAESGCMDuplexSession : NSObject + +- (nullable NSData*) encrypt: (NSData*) data error: (NSError**) error; +- (nullable NSData*) decryptAndVerify: (NSData*) data error: (NSError**) error; + ++ (nullable instancetype) sessionAsSender: (NSData*) sharedSecret + context: (uint64_t) context; ++ (nullable instancetype) sessionAsReceiver: (NSData*) sharedSecret + context: (uint64_t) context; + +- (nullable instancetype) initAsSender: (NSData*) sharedSecret + context: (uint64_t) context; +- (nullable instancetype) initAsReceiver: (NSData*) sharedSecret + context: (uint64_t) context; +- (nullable instancetype) initWithSecret: (NSData*) sharedSecret + context: (uint64_t) context + as: (bool) inverted NS_DESIGNATED_INITIALIZER; + +- (instancetype) init NS_UNAVAILABLE; + + +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder; ++ (BOOL)supportsSecureCoding; + +@end + +NS_ASSUME_NONNULL_END diff --git a/KeychainCircle/KCAESGCMDuplexSession.m b/KeychainCircle/KCAESGCMDuplexSession.m new file mode 100644 index 00000000..7f80ee0a --- /dev/null +++ b/KeychainCircle/KCAESGCMDuplexSession.m @@ -0,0 +1,314 @@ +// +// KCAESGCMDuplexSession.m +// Security +// +// + +#import +#import +#import +#import +#import + +#include +#include +#include +#include + +#include + +#include + + +#define kdfInfoForwardString "send->recv" +#define kdfInfoBackwardString "recv->send" +static NSData* kdfInfoSendToReceive = nil; +static NSData* kdfInfoReceiveToSend = nil; + +static const int kKCAESGCMTagSize = CCAES_KEY_SIZE_128; +static const int kKCAESGCMKeySize = CCAES_KEY_SIZE_128; + +static bool derive_and_init(const struct ccmode_gcm *mode, ccgcm_ctx* ctx, NSData* sharedSecret, NSData* info) { + const struct ccdigest_info *di = ccsha256_di(); + + NSMutableData* space = [NSMutableData dataWithLength:di->output_size]; + + int cc_status = 0; + + cc_status = cchkdf(di, + sharedSecret.length, sharedSecret.bytes, + 0, NULL, + info.length, info.bytes, + space.length, space.mutableBytes); + + if (cc_status != 0) { + return false; + } + // We only use the first 16 bytes (128 bits) for the key. + cc_status = ccgcm_init(mode, ctx, kKCAESGCMKeySize, space.bytes); + cc_clear(space.length, space.mutableBytes); + + return cc_status == 0; +} + +@interface NSMutableData(KAESGCM) +- (void) replaceTrailingWith7LSB: (uint64_t) value; +@end + +@implementation NSMutableData(KAESGCM) +- (void) replaceTrailingWith7LSB: (uint64_t) value { + uint8_t bytes[sizeof(value)]; + OSWriteBigInt64(bytes, 0, value); + + [self replaceBytesInRange: NSMakeRange(self.length - 7, 7) withBytes: (bytes + 1)]; +} +@end + + + +@interface KCAESGCMDuplexSession () +@property (readwrite) bool asSender; +@property (readwrite) uint64_t context; +@property (readwrite) NSData* secret; + +@property (readwrite) ccgcm_ctx * send; +@property (readwrite) ccgcm_ctx * receive; + +@end + +@implementation KCAESGCMDuplexSession + ++ (nullable instancetype) sessionAsSender: (NSData*) sharedSecret + context: (uint64_t) context { + return [[KCAESGCMDuplexSession alloc] initAsSender:sharedSecret + context:context]; +} + ++ (nullable instancetype) sessionAsReceiver: (NSData*) sharedSecret + context: (uint64_t) context { + return [[KCAESGCMDuplexSession alloc] initAsReceiver:sharedSecret + context:context]; + +} + +static NSString* KCDSSender = @"asSender"; +static NSString* KCDSSecret = @"secret"; +static NSString* KCDSContext = @"context"; + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeBool: self.asSender forKey:KCDSSender]; + [aCoder encodeObject: self.secret forKey:KCDSSecret]; + [aCoder encodeInt64: self.context forKey:KCDSContext]; +} + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + + bool asSender = [aDecoder decodeBoolForKey:KCDSSender]; + NSData* secret = [aDecoder decodeObjectOfClass:[NSData class] forKey:KCDSSecret]; + uint64_t context = [aDecoder decodeInt64ForKey:KCDSContext]; + + return [self initWithSecret:secret context:context as:asSender]; +} + ++ (BOOL)supportsSecureCoding { + return true; +} + + + +- (nullable instancetype) initAsSender: (NSData*) sharedSecret context: (uint64_t) context { + return [self initWithSecret:sharedSecret context:context as:true]; +} + +- (nullable instancetype) initAsReceiver: (NSData*) sharedSecret context: (uint64_t) context { + return [self initWithSecret:sharedSecret context:context as:false]; +} + +- (nullable instancetype) initWithSecret: (NSData*) sharedSecret + context: (uint64_t) context + as: (bool) sender { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + kdfInfoSendToReceive = [NSData dataWithBytesNoCopy: kdfInfoForwardString + length: strlen(kdfInfoForwardString) + freeWhenDone: false]; + + kdfInfoReceiveToSend = [NSData dataWithBytesNoCopy: kdfInfoBackwardString + length: strlen(kdfInfoBackwardString) + 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; + + 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); + + return self; +} + +- (size_t) encryptCapsuleSize: (NSData*) plaintext IV: (NSData*) iv { + size_t iv_size = kcder_sizeof_data(iv, nil); + if (iv_size == 0) { + return 0; + } + size_t text_size = kcder_sizeof_data(plaintext, nil); + if (text_size == 0) { + return 0; + } + size_t tag_size = kcder_sizeof_data([NSMutableData dataWithLength: kKCAESGCMTagSize], nil); + if (tag_size == 0) { + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, iv_size + text_size + tag_size); +} + +- (bool) GCM:(const struct ccmode_gcm*) mode + context:(ccgcm_ctx*) ctx + iv:(NSData*) iv + size:(size_t) data_size + data:(const uint8_t*) data + processed:(uint8_t*) result + tag:(uint8_t*) tagBuffer + error:(NSError**) error { + int cc_status; + + cc_status = ccgcm_reset(mode, ctx); + if (!CoreCryptoError(cc_status, error, @"ccgcm_reset failed: %d", cc_status)) + return NO; + + cc_status = ccgcm_set_iv(mode, ctx, iv.length, iv.bytes); + if (!CoreCryptoError(cc_status, error, @"ccgcm_set_iv failed: %d", cc_status)) + return NO; + + cc_status = ccgcm_update(mode, ctx, data_size, data, result); + if (!CoreCryptoError(cc_status, error, @"ccgcm_update failed: %d", cc_status)) + return NO; + + cc_status = ccgcm_finalize(mode, ctx, kKCAESGCMTagSize, tagBuffer); + return CoreCryptoError(cc_status, error, @"ccgcm_finalize failed: %d", cc_status); +} + + +- (nullable NSData*) encrypt: (NSData*) data error: (NSError**) error { + static const int kIVSizeInBytes = 16; + + NSMutableData* iv = [NSMutableData dataWithRandomBytes: kIVSizeInBytes]; + + NSMutableData* result = [NSMutableData dataWithLength: [self encryptCapsuleSize: data IV: iv]]; + + // Encode with all the space set up for the result: + + uint8_t* der_end = result.mutableBytes + result.length; + const uint8_t* der = result.bytes; + + uint8_t* tag = NULL; + uint8_t* encrypted = NULL; + + der_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + kcder_encode_data(iv, error, der, + kcder_encode_raw_octet_space(data.length, &encrypted, der, + kcder_encode_raw_octet_space(kKCAESGCMTagSize, &tag, der, der_end)))); + + if (der_end != der) { + KCJoiningErrorCreate(kAllocationFailure, error, @"Failed to allocate space for der"); + return nil; + } + + const struct ccmode_gcm * mode = ccaes_gcm_encrypt_mode(); + + return [self GCM:mode + context:self.send + iv:iv + size:data.length + data:data.bytes + processed:encrypted + tag:tag + error:error] ? result : nil; +} + +- (nullable NSData*) decryptAndVerify: (NSData*) data error: (NSError**) error { + + const uint8_t *der = data.bytes; + const uint8_t *der_end = der + data.length; + + const uint8_t *sequence_end = 0; + der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end); + + if (der == NULL || sequence_end != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed"); + return nil; + } + + const uint8_t *encrypted = 0; + size_t encrypted_len = 0; + const uint8_t *received_tag = 0; + + NSData* iv; + + der = kcder_decode_data(&iv, error, der, der_end); + if (der == NULL) return nil; + + encrypted = ccder_decode_constructed_tl(CCDER_OCTET_STRING, &der, der, der_end); + encrypted_len = der - encrypted; + + received_tag = ccder_decode_constructed_tl(CCDER_OCTET_STRING, &der, der, der_end); + + if (der == NULL) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Decode failure"); + return nil; + } + + if (der != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra space"); + return nil; + } + + if (der - received_tag != kKCAESGCMTagSize) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unexpected tag size: %d", der - received_tag); + return nil; + } + + NSMutableData* decrypted = [NSMutableData dataWithLength: encrypted_len]; + + uint8_t tag[kKCAESGCMTagSize]; + memcpy(tag, received_tag, sizeof(tag)); + + const struct ccmode_gcm * mode = ccaes_gcm_decrypt_mode(); + + return [self GCM:mode + context:self.receive + iv:iv + size:encrypted_len + data:encrypted + processed:decrypted.mutableBytes + tag:tag + error:error] ? decrypted : nil; +} + +- (void) finalize { + if (self.send) { + ccgcm_ctx_clear(sizeof(*self.send), self.send); + free(self.send); + } + if (self.receive) { + ccgcm_ctx_clear(sizeof(*self.receive), self.receive); + free(self.receive); + } + [super finalize]; +} + +@end diff --git a/KeychainCircle/KCAccountKCCircleDelegate.h b/KeychainCircle/KCAccountKCCircleDelegate.h new file mode 100644 index 00000000..dec0a273 --- /dev/null +++ b/KeychainCircle/KCAccountKCCircleDelegate.h @@ -0,0 +1,45 @@ +// +// KCAccountKCCircleDelegate.h +// Security +// + +#import + +@interface KCJoiningRequestAccountCircleDelegate : NSObject < KCJoiningRequestCircleDelegate> +/*! + Get this devices peer info (As Application) + + @result + SOSPeerInfoRef object or NULL if we had an error. + */ +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error; + +/*! + Handle recipt of confirmed circleJoinData over the channel + + @parameter circleJoinData + Data the acceptor made to allow us to join the circle. + + */ +- (bool) processCircleJoinData: (NSData*) circleJoinData error: (NSError**)error; + ++ (instancetype) delegate; + +@end + +@interface KCJoiningAcceptAccountCircleDelegate : NSObject < KCJoiningAcceptCircleDelegate> +/*! + Handle the request's peer info and get the blob they can use to get in circle + @param peer + SOSPeerInfo sent from requestor to apply to the circle + @param error + Error resulting in looking at peer and trying to produce circle join data + @result + Data containing blob the requestor can use to get in circle + */ +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error; + ++ (instancetype) delegate; + +@end diff --git a/KeychainCircle/KCAccountKCCircleDelegate.m b/KeychainCircle/KCAccountKCCircleDelegate.m new file mode 100644 index 00000000..12b64781 --- /dev/null +++ b/KeychainCircle/KCAccountKCCircleDelegate.m @@ -0,0 +1,77 @@ +// +// KCAccountKCCircleDelegate.m +// Security +// +// Created by Mitch Adler on 4/11/16. +// +// + +#import + +#include + + +@implementation KCJoiningRequestAccountCircleDelegate +/*! + Get this devices peer info (As Application) + + @result + SOSPeerInfoRef object or NULL if we had an error. + */ +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error { + CFErrorRef failure = NULL; + SOSPeerInfoRef result = SOSCCCopyApplication(error ? &failure : NULL); + if (failure != NULL && error != nil) { + *error = (__bridge_transfer NSError*) failure; + } + return result; +} + +/*! + Handle recipt of confirmed circleJoinData over the channel + + @parameter circleJoinData + Data the acceptor made to allow us to join the circle. + + */ +- (bool) processCircleJoinData: (NSData*) circleJoinData error: (NSError**)error { + CFErrorRef failure = NULL; + bool result = SOSCCJoinWithCircleJoiningBlob((__bridge CFDataRef) circleJoinData, &failure); + if (failure != NULL && error != nil) { + *error = (__bridge_transfer NSError*) failure; + } + return result; +} + ++ (instancetype) delegate { + return [[KCJoiningRequestAccountCircleDelegate alloc] init]; +} + +@end + +@implementation KCJoiningAcceptAccountCircleDelegate +/*! + Handle the request's peer info and get the blob they can use to get in circle + @param peer + SOSPeerInfo sent from requestor to apply to the circle + @param error + Error resulting in looking at peer and trying to produce circle join data + @result + Data containing blob the requestor can use to get in circle + */ +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error { + CFErrorRef failure = NULL; + CFDataRef result = SOSCCCopyCircleJoiningBlob(peer, &failure); + if (failure != NULL && error != nil) { + *error = (__bridge_transfer NSError*) failure; + } + return (__bridge_transfer NSData*) result; +} + ++ (instancetype) delegate { + return [[KCJoiningAcceptAccountCircleDelegate alloc] init]; +} + +@end + diff --git a/KeychainCircle/KCDer.h b/KeychainCircle/KCDer.h new file mode 100644 index 00000000..1ecc51dd --- /dev/null +++ b/KeychainCircle/KCDer.h @@ -0,0 +1,46 @@ +// +// KCDer.h +// KeychainCircle +// +// + +#include +#include + +NS_ASSUME_NONNULL_BEGIN + +// These should probably be shared with security, but we don't export our der'izing functions yet. +const uint8_t* _Nullable +kcder_decode_data_nocopy(NSData* _Nullable * _Nonnull data, + NSError* _Nullable * _Nullable error, + const uint8_t* _Nonnull der, const uint8_t * _Nullable der_end); +const uint8_t* _Nullable +kcder_decode_data(NSData* _Nullable* _Nonnull data, NSError* _Nullable * _Nullable error, + const uint8_t* der, const uint8_t * _Nullable der_end); +size_t +kcder_sizeof_data(NSData* data, NSError** error); +uint8_t* _Nullable +kcder_encode_data(NSData* data, NSError**error, + const uint8_t * _Nonnull der, uint8_t * _Nullable der_end); +uint8_t* _Nullable +kcder_encode_data_optional(NSData* _Nullable data, NSError* _Nullable * _Nullable error, + const uint8_t *der, uint8_t *der_end); + +const uint8_t* _Nullable +kcder_decode_string(NSString*_Nullable * _Nonnull string, + NSError* _Nullable * _Nullable error, + const uint8_t* _Nonnull der, + const uint8_t* _Nullable der_end); +size_t +kcder_sizeof_string(NSString* string, + NSError* _Nullable * _Nullable error); +uint8_t* _Nullable +kcder_encode_string(NSString* string, + NSError* _Nullable * _Nullable error, + const uint8_t * _Nonnull der, uint8_t * _Nullable der_end); + +uint8_t * +kcder_encode_raw_octet_space(size_t s_size, uint8_t * _Nullable * _Nonnull location, + const uint8_t * _Nonnull der, uint8_t * _Nullable der_end); + +NS_ASSUME_NONNULL_END diff --git a/KeychainCircle/KCDer.m b/KeychainCircle/KCDer.m new file mode 100644 index 00000000..38ac5d7f --- /dev/null +++ b/KeychainCircle/KCDer.m @@ -0,0 +1,144 @@ +// +// KCDer.m +// Security +// +// + +#import + +#include +#import + +// These should probably be shared with security, but we don't export our der'izing functions yet. + + +static const uint8_t* kcder_decode_data_internal(NSData** data, bool copy, + NSError**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 || payload + payload_size > der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unknown data encoding"); + return NULL; + } + + *data = copy ? [NSData dataWithBytes: (void*)payload length: payload_size] : + [NSData dataWithBytesNoCopy: (void*)payload length:payload_size freeWhenDone:NO]; + + if (NULL == *data) { + KCJoiningErrorCreate(kAllocationFailure, error, @"Allocation failure!"); + return NULL; + } + + return payload + payload_size; +} + + +const uint8_t* kcder_decode_data_nocopy(NSData** data, + NSError**error, + const uint8_t* der, const uint8_t *der_end) +{ + return kcder_decode_data_internal(data, NO, error, der, der_end); +} + +const uint8_t* kcder_decode_data(NSData** data, + NSError**error, + const uint8_t* der, const uint8_t *der_end) { + return kcder_decode_data_internal(data, YES, error, der, der_end); +} + + +size_t kcder_sizeof_data(NSData* data, NSError** error) { + return ccder_sizeof_raw_octet_string(data.length); +} + +uint8_t* kcder_encode_data_optional(NSData* _Nullable data, NSError**error, + const uint8_t *der, uint8_t *der_end) +{ + if (data == nil) return der_end; + + return kcder_encode_data(data, error, der, der_end); + +} + + +uint8_t* kcder_encode_data(NSData* data, NSError**error, + const uint8_t *der, uint8_t *der_end) +{ + return ccder_encode_tl(CCDER_OCTET_STRING, data.length, der, + ccder_encode_body(data.length, data.bytes, der, der_end)); + +} + + +const uint8_t* kcder_decode_string(NSString** string, NSError**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_UTF8_STRING, &payload_size, der, der_end); + + if (NULL == payload || payload + payload_size > der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Unknown string encoding"); + return NULL; + } + + *string = [[NSString alloc] initWithBytes:payload length:payload_size encoding:NSUTF8StringEncoding]; + + if (nil == *string) { + KCJoiningErrorCreate(kAllocationFailure, error, @"Allocation failure!"); + return NULL; + } + + return payload + payload_size; +} + + +size_t kcder_sizeof_string(NSString* string, NSError** error) +{ + return ccder_sizeof(CCDER_UTF8_STRING, [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]); +} + + +uint8_t* kcder_encode_string(NSString* string, NSError** error, + const uint8_t *der, uint8_t *der_end) +{ + // Obey the NULL allowed rules. + if (!der_end) + return NULL; + + NSUInteger max = (der_end - der); + void *buffer = der_end - max; + NSUInteger used = 0; + if (![string getBytes:buffer + maxLength:max + usedLength:&used + encoding:NSUTF8StringEncoding + options:0 + range:NSMakeRange(0, string.length) + remainingRange:nil]) { + KCJoiningErrorCreate(kDERStringEncodingFailed, error, @"String encoding failed"); + return NULL; + } + + return ccder_encode_tl(CCDER_UTF8_STRING, used, der, + ccder_encode_body(used, buffer, der, der_end)); + +} + +uint8_t *kcder_encode_raw_octet_space(size_t s_size, uint8_t **location, + const uint8_t *der, uint8_t *der_end) { + der_end = ccder_encode_body_nocopy(s_size, der, der_end); + if (der_end && location) + *location = der_end; + + return ccder_encode_tl(CCDER_OCTET_STRING, s_size, der, der_end); +} + diff --git a/KeychainCircle/KCError.h b/KeychainCircle/KCError.h new file mode 100644 index 00000000..80868862 --- /dev/null +++ b/KeychainCircle/KCError.h @@ -0,0 +1,34 @@ +// +// KCError.h +// Security +// +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef enum { + kAllocationFailure, + kDERUnknownEncoding, + kDERStringEncodingFailed, + kDEREncodingFailed, + kDERSpaceExhausted, + kKCTagMismatch, + kUnexpectedMessage, + kInternalError, +} KCJoiningError; + +@interface NSError(KCJoiningError) ++ (instancetype) errorWithJoiningError:(KCJoiningError) code + format:(NSString *) format + arguments:(va_list) va; ++ (instancetype) errorWithJoiningError:(KCJoiningError) code + format:(NSString *) format, ...; +- (instancetype) initWithJoiningError:(KCJoiningError) code + userInfo:(NSDictionary *)dict; +@end + +void KCJoiningErrorCreate(KCJoiningError code, NSError* _Nullable * _Nullable error, NSString* _Nonnull format, ...); + +NS_ASSUME_NONNULL_END diff --git a/KeychainCircle/KCError.m b/KeychainCircle/KCError.m new file mode 100644 index 00000000..5d8aae88 --- /dev/null +++ b/KeychainCircle/KCError.m @@ -0,0 +1,47 @@ +// +// KCError.m +// Security +// +// + +#import "KCError.h" + +static NSString* KCErrorDomain = @"com.apple.security.keychaincircle"; + + +@implementation NSError(KCJoiningError) + ++ (nonnull instancetype) errorWithJoiningError:(KCJoiningError) code + format:(NSString*) format + arguments:(va_list) va { + return [[NSError alloc] initWithJoiningError:code + userInfo:@{NSLocalizedDescriptionKey:[[NSString alloc] initWithFormat:format arguments:va]}]; + +} + ++ (nonnull instancetype) errorWithJoiningError:(KCJoiningError) code + format:(NSString*) format, ... { + + va_list va; + va_start(va, format); + NSError* result = [NSError errorWithJoiningError:code format:format arguments:va]; + va_end(va); + + return result; + +} +- (nonnull instancetype) initWithJoiningError:(KCJoiningError) code + userInfo:(nonnull NSDictionary *)dict { + return [self initWithDomain:KCErrorDomain code:code userInfo:dict]; +} +@end + +void KCJoiningErrorCreate(KCJoiningError code, NSError** error, NSString* format, ...) { + if (error && (*error == nil)) { + va_list va; + va_start(va, format); + *error = [NSError errorWithJoiningError:code format:format arguments:va]; + va_end(va); + } +} + diff --git a/KeychainCircle/KCJoiningAcceptSession.m b/KeychainCircle/KCJoiningAcceptSession.m new file mode 100644 index 00000000..60b7ada7 --- /dev/null +++ b/KeychainCircle/KCJoiningAcceptSession.m @@ -0,0 +1,244 @@ +// +// KCJoiningAcceptSession.m +// Security +// +// + +#import + +#import + +#import +#import +#import + +#import + +#include +#include +#include +#include + +#include + +typedef enum { + kExpectingA, + kExpectingM, + kExpectingPeerInfo, + kAcceptDone +} KCJoiningAcceptSessionState; + +@interface KCJoiningAcceptSession () +@property (readonly) uint64_t dsid; +@property (readonly) NSObject* secretDelegate; +@property (readonly) NSObject* circleDelegate; +@property (readonly) KCSRPServerContext* context; +@property (readonly) KCAESGCMDuplexSession* session; +@property (readonly) KCJoiningAcceptSessionState state; +@property (readwrite) NSData* startMessage; +@end + +@implementation KCJoiningAcceptSession + ++ (nullable instancetype) sessionWithInitialMessage: (NSData*) message + secretDelegate: (NSObject*) secretDelegate + circleDelegate: (NSObject*) circleDelegate + dsid: (uint64_t) dsid + error: (NSError**) error { + + int cc_error = 0; + struct ccrng_state * rng = ccrng(&cc_error); + + if (rng == nil) { + CoreCryptoError(cc_error, error, @"RNG fetch failed"); + return nil; + } + + return [[KCJoiningAcceptSession alloc] initWithSecretDelegate: secretDelegate + circleDelegate: circleDelegate + dsid: dsid + rng: rng + error: error]; +} + +- (bool) setupSession: (NSError**) error { + NSData* key = [self->_context getKey]; + + if (key == nil) { + KCJoiningErrorCreate(kInternalError, error, @"No session key available"); + return nil; + } + + self->_session = [KCAESGCMDuplexSession sessionAsReceiver:key context:self.dsid]; + + return self.session != nil; +} + +- (nullable instancetype) initWithSecretDelegate: (NSObject*) secretDelegate + circleDelegate: (NSObject*) circleDelegate + dsid: (uint64_t) dsid + rng: (struct ccrng_state *)rng + error: (NSError**) error { + self = [super init]; + + 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; + + return self; +} + +- (NSString*) stateString { + switch (self.state) { + case kExpectingA: return @"→A"; + case kExpectingM: return @"→M"; + case kExpectingPeerInfo: return @"→PeerInfo"; + case kAcceptDone: return @"done"; + default: return [NSString stringWithFormat:@"%d", self.state]; + } +} + +- (NSString *)description { + return [NSString stringWithFormat: @"", self, self.dsid, [self stateString], self.context]; +} + +- (NSData*) copyChallengeMessage: (NSError**) error { + NSData* challenge = [self.context copyChallengeFor: self.startMessage error: error]; + if (challenge == nil) return nil; + + NSData* srpMessage = [NSData dataWithEncodedSequenceData:self.context.salt data:challenge error:error]; + + if (![self setupSession:error]) return nil; + + return srpMessage; +} + +- (NSData*) processInitialMessage: (NSData*) initialMessage error: (NSError**) error { + self.startMessage = extractStartFromInitialMessage(initialMessage, error); + if (self.startMessage == nil) return nil; + + NSData* srpMessage = [self copyChallengeMessage: error]; + if (srpMessage == nil) return nil; + + self->_state = kExpectingM; + return [[KCJoiningMessage messageWithType:kChallenge + data:srpMessage + error:error] der]; +} + +- (NSData*) processResponse: (KCJoiningMessage*) message error:(NSError**) error { + if ([message type] != kResponse) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected response!"); + return nil; + } + + // We handle failure, don't capture the error. + NSData* confirmation = [self.context copyConfirmationFor:message.firstData error:NULL]; + if (!confirmation) { + // Find out what kind of error we should send. + NSData* errorData = nil; + + switch ([self.secretDelegate verificationFailed: error]) { + case kKCRetryError: + // We fill in an error if they didn't, but if they did this wont bother. + KCJoiningErrorCreate(kInternalError, error, @"Delegate returned error without filling in error: %@", self.secretDelegate); + return nil; + case kKCRetryWithSameChallenge: + errorData = [NSData data]; + break; + case kKCRetryWithNewChallenge: + if ([self.context resetWithPassword:[self.secretDelegate secret] error:error]) { + errorData = [self copyChallengeMessage: error]; + } + break; + } + if (errorData == nil) return nil; + + return [[KCJoiningMessage messageWithType:kError + data:errorData + error:error] der]; + } + + NSData* encoded = [NSData dataWithEncodedString:[self.secretDelegate accountCode] error:error]; + if (encoded == nil) + return nil; + + NSData* encrypted = [self.session encrypt:encoded error:error]; + if (encrypted == nil) return nil; + + self->_state = kExpectingPeerInfo; + + return [[KCJoiningMessage messageWithType:kVerification + data:confirmation + payload:encrypted + error:error] der]; +} + + +- (NSData*) processApplication: (KCJoiningMessage*) message error:(NSError**) error { + if ([message type] != kPeerInfo) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected peerInfo!"); + return nil; + } + + NSData* decryptedPayload = [self.session decryptAndVerify:message.firstData error:error]; + if (decryptedPayload == nil) return nil; + + CFErrorRef cfError = NULL; + SOSPeerInfoRef ref = SOSPeerInfoCreateFromData(NULL, &cfError, (__bridge CFDataRef) decryptedPayload); + if (ref == NULL) { + if (error) *error = (__bridge_transfer NSError*) cfError; + cfError = NULL; + return nil; + } + + NSData* joinData = [self.circleDelegate circleJoinDataFor:ref error:error]; + if (joinData == nil) return nil; + + NSData* encryptedOutgoing = [self.session encrypt:joinData error:error]; + if (encryptedOutgoing == nil) return nil; + + self->_state = kAcceptDone; + + return [[KCJoiningMessage messageWithType:kCircleBlob + data:encryptedOutgoing + error:error] der]; +} + + +- (nullable NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { + NSData* result = nil; + + KCJoiningMessage *message = (self.state != kExpectingA) ? [KCJoiningMessage messageWithDER:incomingMessage error:error] : nil; + + switch(self.state) { + case kExpectingA: + return [self processInitialMessage:incomingMessage error: error]; + case kExpectingM: + if (message == nil) return nil; + return [self processResponse:message error: error]; + break; + case kExpectingPeerInfo: + if (message == nil) return nil; + return [self processApplication:message error: error]; + break; + case kAcceptDone: + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Unexpected message while done"); + break; + } + return result; +} + +- (bool) isDone { + return self.state == kAcceptDone; +} + +@end diff --git a/KeychainCircle/KCJoiningMessages.h b/KeychainCircle/KCJoiningMessages.h new file mode 100644 index 00000000..18610d41 --- /dev/null +++ b/KeychainCircle/KCJoiningMessages.h @@ -0,0 +1,113 @@ +// +// KCJoiningMessages.h +// KeychainCircle +// +// + +#import + +// Initial messages are versioned and not typed for negotiation. +NS_ASSUME_NONNULL_BEGIN + +NSData* extractStartFromInitialMessage(NSData* initialMessage, NSError** error); + +size_t sizeof_initialmessage(NSData*data); +uint8_t* _Nullable encode_initialmessage(NSData* data, NSError**error, + const uint8_t *der, uint8_t *der_end); +const uint8_t* _Nullable decode_initialmessage(NSData* _Nonnull * _Nonnull data, NSError** error, + const uint8_t* der, const uint8_t *der_end); + +size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError** error); +uint8_t* _Nullable encode_seq_data_data(NSData* data, NSData*data2, NSError**error, + const uint8_t *der, uint8_t *der_end); +const uint8_t* _Nullable decode_seq_data_data(NSData* _Nonnull * _Nonnull data1, NSData* _Nonnull * _Nonnull data2, + NSError** error, + const uint8_t* der, const uint8_t *der_end); + +size_t sizeof_seq_string_data(NSString*string, NSData*data, NSError** error); +uint8_t* _Nullable encode_seq_string_data(NSString* string, NSData*data, NSError**error, + const uint8_t *der, uint8_t *der_end); +const uint8_t* _Nullable decode_seq_string_data(NSString* _Nonnull * _Nonnull string, NSData* _Nonnull * _Nonnull data, + NSError** error, + const uint8_t* der, const uint8_t *der_end); + +@interface NSData(KCJoiningMessages) + ++ (nullable instancetype) dataWithEncodedString: (NSString*) string + error: (NSError**) error; + ++ (nullable instancetype) dataWithEncodedSequenceData: (NSData*) data1 + data: (NSData*) data2 + error: (NSError**) error; + +- (bool) decodeSequenceData: (NSData* _Nullable * _Nonnull) data1 + data: (NSData* _Nullable * _Nonnull) data2 + error: (NSError** _Nullable) error; + + ++ (nullable instancetype) dataWithEncodedSequenceString: (NSString*) string + data: (NSData*) data + error: (NSError**) error; + +- (bool) decodeSequenceString: (NSString* _Nullable * _Nonnull) string + data: (NSData* _Nullable * _Nonnull) data + error: (NSError** _Nullable) error; +@end + +@interface NSString(KCJoiningMessages) ++ (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullable) error; +@end + +// Subsequent messages have a message type +typedef enum { + kChallenge = 1, + kResponse = 2, + kVerification = 3, + kPeerInfo = 4, + kCircleBlob = 5, + + kError = 0, + + kUnknown = 255, + + kLargestMessageType = kUnknown, + +} KCJoiningMessageType; + + +@interface KCJoiningMessage : NSObject + +@property (readonly) KCJoiningMessageType type; +@property (readonly) NSData* firstData; +@property (nullable, readonly) NSData* secondData; + +@property (readonly) NSData* der; + ++ (nullable instancetype) messageWithDER: (NSData*) message + error: (NSError**) error; + ++ (nullable instancetype) messageWithType: (KCJoiningMessageType) type + data: (NSData*) firstData + error: (NSError**) error; + ++ (nullable instancetype) messageWithType: (KCJoiningMessageType) type + data: (NSData*) firstData + payload: (NSData*) secondData + error: (NSError**) error; + + +- (nullable instancetype) initWithDER: (NSData*) message + error: (NSError**) error NS_DESIGNATED_INITIALIZER; + +- (nullable instancetype) initWithType: (KCJoiningMessageType) type + data: (NSData*) firstData + payload: (nullable NSData*) secondData + error: (NSError**) error NS_DESIGNATED_INITIALIZER; + + +- (instancetype) init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/KeychainCircle/KCJoiningMessages.m b/KeychainCircle/KCJoiningMessages.m new file mode 100644 index 00000000..c2922cdd --- /dev/null +++ b/KeychainCircle/KCJoiningMessages.m @@ -0,0 +1,393 @@ +// +// KCJoiningMessages.m +// Security +// +// Created by Mitch Adler on 2/17/16. +// +// + +#import + +#import +#import +#import + +#include + + +@implementation KCJoiningMessage + ++ (nullable instancetype) messageWithDER: (NSData*) message + error: (NSError**) error { + return [[KCJoiningMessage alloc] initWithDER: message error: nil]; +} + ++ (nullable instancetype) messageWithType: (KCJoiningMessageType) type + data: (NSData*) firstData + error: (NSError**) error { + return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:nil error:error]; +} + ++ (nullable instancetype) messageWithType: (KCJoiningMessageType) type + data: (NSData*) firstData + payload: (NSData*) secondData + error: (NSError**) error { + return [[KCJoiningMessage alloc] initWithType:type data:firstData payload:secondData error:error]; + +} + +- (bool) inflatePartsOfEncoding: (NSError**) error { + const uint8_t *der = self.der.bytes; + const uint8_t *der_end = der + self.der.length; + + const uint8_t *sequence_end = 0; + + der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end); + + if (der == 0) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Not sequence"); + return false; + } + + if (sequence_end != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra data at end of message"); + return false; + } + + uint64_t type; + der = ccder_decode_uint64(&type, der, der_end); + + self->_type = (type > kLargestMessageType) ? kUnknown : (KCJoiningMessageType) type; + + NSData* firstData; + NSData* secondData; + + der = kcder_decode_data_nocopy(&firstData, error, der, der_end); + + if (der != der_end) { + der = kcder_decode_data_nocopy(&secondData, error, der, der_end); + } + + self->_firstData = firstData; + self->_secondData = secondData; + + if (der != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Extra in sequence"); + return false; + } + + return true; +} + ++ (size_t) encodedSizeType: (KCJoiningMessageType) type + data: (NSData*) firstData + payload: (nullable NSData*) secondData + error: (NSError**) error { + size_t type_size = ccder_sizeof_uint64(type); + + size_t srp_data_size = kcder_sizeof_data(firstData, error); + if (srp_data_size == 0) return 0; + + size_t encrypted_payload_size = 0; + + if (secondData != nil) { + encrypted_payload_size = kcder_sizeof_data(secondData, error); + if (srp_data_size == 0) return 0; + } + + + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, type_size + srp_data_size + encrypted_payload_size); +} + ++ (nullable NSData*) encodeToDERType: (KCJoiningMessageType) type + data: (NSData*) firstData + payload: (nullable NSData*) secondData + error: (NSError**) error { + + size_t length = [KCJoiningMessage encodedSizeType:type + data:firstData + payload:secondData + error: error]; + if (length == 0) return nil; + + NSMutableData* encoded = [NSMutableData dataWithLength: length]; + + uint8_t* der = encoded.mutableBytes; + uint8_t* der_end = der + encoded.length; + + uint8_t* encode_end = ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(type, der, + kcder_encode_data(firstData, error, der, + kcder_encode_data_optional(secondData, error, der, der_end)))); + + if (encode_end == NULL) return nil; + if (encode_end != der) { + KCJoiningErrorCreate(kDEREncodingFailed, error, @"Size didn't match encoding"); + return nil; + } + + return encoded; +} + +- (nullable instancetype) initWithDER: (NSData*) message + error: (NSError**) error { + self = [super init]; + + self->_der = [NSData dataWithData: message]; + + return [self inflatePartsOfEncoding: error] ? self : nil; +} + +- (nullable instancetype) initWithType: (KCJoiningMessageType) type + 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; + + return [self inflatePartsOfEncoding: error] ? self : nil; +} + +@end + + +@implementation NSData(KCJoiningMessages) + ++ (nullable instancetype) dataWithEncodedString: (NSString*) string + error: (NSError**) error { + size_t result_size = kcder_sizeof_string(string, error); + if (result_size == 0) return nil; + + NSMutableData *result = [NSMutableData dataWithLength: result_size]; + + uint8_t *der = result.mutableBytes; + uint8_t *der_end = der + result.length; + + uint8_t *encode_done = kcder_encode_string(string, error, + der, der_end); + + if (encode_done != der) { + KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data"); + return nil; + } + + return result; +} + ++ (nullable instancetype) dataWithEncodedSequenceData: (NSData*) data1 + data: (NSData*) data2 + error: (NSError**) error { + size_t result_size = sizeof_seq_data_data(data1, data2, error); + if (result_size == 0) return nil; + + NSMutableData *result = [NSMutableData dataWithLength: result_size]; + + uint8_t *der = result.mutableBytes; + uint8_t *der_end = der + result.length; + + uint8_t *encode_done = encode_seq_data_data(data1, data2, error, + der, der_end); + + if (encode_done != der) { + KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data"); + return nil; + } + + return result; +} + +- (bool) decodeSequenceData: (NSData* _Nullable * _Nonnull) data1 + data: (NSData* _Nullable * _Nonnull) data2 + error: (NSError** _Nullable) error { + + return NULL != decode_seq_data_data(data1, data2, error, self.bytes, self.bytes + self.length); +} + ++ (nullable instancetype) dataWithEncodedSequenceString: (NSString*) string + data: (NSData*) data + error: (NSError**) error { + size_t result_size = sizeof_seq_string_data(string, data, error); + if (result_size == 0) return nil; + + NSMutableData *result = [NSMutableData dataWithLength: result_size]; + + uint8_t *der = result.mutableBytes; + uint8_t *der_end = der + result.length; + + uint8_t *encode_done = encode_seq_string_data(string, data, error, + der, der_end); + + if (encode_done != der) { + KCJoiningErrorCreate(kDEREncodingFailed, error, @"extra data"); + return nil; + } + + return result; +} + +- (bool) decodeSequenceString: (NSString* _Nullable * _Nonnull) string + data: (NSData* _Nullable * _Nonnull) data + error: (NSError** _Nullable) error { + return NULL != decode_seq_string_data(string, data, error, self.bytes, self.bytes + self.length); +} + +@end + +@implementation NSString(KCJoiningMessages) ++ (nullable instancetype) decodeFromDER: (NSData*)der error: (NSError** _Nullable) error { + NSString* result = nil; + const uint8_t* decode_result = kcder_decode_string(&result, error, der.bytes, der.bytes+der.length); + if (decode_result == nil) return nil; + if (decode_result != der.bytes + der.length) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"extra data in string"); + return nil; + } + + return result; +} +@end + + +NSData* extractStartFromInitialMessage(NSData* initialMessage, NSError** error) { + NSData* result = nil; + const uint8_t *der = [initialMessage bytes]; + const uint8_t *der_end = der + [initialMessage length]; + const uint8_t *parse_end = decode_initialmessage(&result, error, der, der_end); + + // Allow extra stuff in here for future start messages. + if (parse_end == NULL) { + return nil; + } + return result; + +} + +const uint8_t* decode_initialmessage(NSData** data, NSError** error, + const uint8_t* der, const uint8_t *der_end) +{ + if (NULL == der) + return NULL; + + const uint8_t *sequence_end = 0; + der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end); + + if (der == NULL || sequence_end != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed"); + return nil; + } + + uint64_t version = 0; + der = ccder_decode_uint64(&version, der, der_end); + + if (der == NULL) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Version mising"); + return nil; + } + + if (version != 0) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"Bad version: %d", version); + return nil; + } + + return kcder_decode_data(data, error, der, der_end); +} + +size_t sizeof_initialmessage(NSData*data) { + size_t version_size = ccder_sizeof_uint64(0); + if (version_size == 0) { + return 0; + } + size_t message_size = kcder_sizeof_data(data, nil); + if (message_size == 0) { + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, version_size + message_size); +} + +uint8_t* encode_initialmessage(NSData* data, NSError**error, + const uint8_t *der, uint8_t *der_end) +{ + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + ccder_encode_uint64(0, der, + kcder_encode_data(data, error, der, der_end))); + +} + + +size_t sizeof_seq_data_data(NSData*data1, NSData*data2, NSError**error) { + size_t data1_size = kcder_sizeof_data(data1, error); + if (data1_size == 0) { + return 0; + } + size_t data2_size = kcder_sizeof_data(data2, error); + if (data2_size == 0) { + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, data1_size + data2_size); +} + +uint8_t* encode_seq_data_data(NSData* data1, NSData*data2, NSError**error, + const uint8_t *der, uint8_t *der_end) { + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + kcder_encode_data(data1, error, der, + kcder_encode_data(data2, error, der, der_end))); +} + +const uint8_t* decode_seq_data_data(NSData** data1, NSData** data2, NSError** error, + const uint8_t* der, const uint8_t *der_end) { + if (NULL == der) + return NULL; + + const uint8_t *sequence_end = 0; + der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end); + + if (der == NULL || sequence_end != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed"); + return nil; + } + + der = kcder_decode_data(data1, error, der, der_end); + return kcder_decode_data(data2, error, der, der_end); +} + +size_t sizeof_seq_string_data(NSString*string, NSData*data, NSError** error) { + size_t string_size = kcder_sizeof_string(string, error); + if (string_size == 0) { + return 0; + } + size_t data_size = kcder_sizeof_data(data, error); + if (data_size == 0) { + return 0; + } + return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, string_size + data_size); +} + +uint8_t* _Nullable encode_seq_string_data(NSString* string, NSData*data, NSError**error, + const uint8_t *der, uint8_t *der_end) { + return ccder_encode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, der_end, der, + kcder_encode_string(string, error, der, + kcder_encode_data(data, error, der, der_end))); +} + +const uint8_t* _Nullable decode_seq_string_data(NSString* _Nonnull * _Nonnull string, NSData* _Nonnull * _Nonnull data, + NSError** error, + const uint8_t* der, const uint8_t *der_end) { + if (NULL == der) + return NULL; + + const uint8_t *sequence_end = 0; + der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &sequence_end, der, der_end); + + if (der == NULL || sequence_end != der_end) { + KCJoiningErrorCreate(kDERUnknownEncoding, error, @"decode failed"); + return nil; + } + + der = kcder_decode_string(string, error, der, der_end); + return kcder_decode_data(data, error, der, der_end); +} diff --git a/KeychainCircle/KCJoiningRequestSession.m b/KeychainCircle/KCJoiningRequestSession.m new file mode 100644 index 00000000..e41c53bb --- /dev/null +++ b/KeychainCircle/KCJoiningRequestSession.m @@ -0,0 +1,370 @@ +// +// KCJoiningSession.m +// Security +// +// + +#import + +#import + +#import +#import +#import + +#import + +#include +#include +#include +#include +#include + +#include + +#import + +typedef enum { + kExpectingB, + kExpectingHAMK, + kRequestSecretDone +} KCJoiningRequestSecretSessionState; + +typedef enum { + kExpectingCircleBlob, + kRequestCircleDone +} KCJoiningRequestCircleSessionState; + +@interface KCJoiningRequestSecretSession () +@property (readonly) NSObject* secretDelegate; +@property (readonly) KCSRPClientContext* context; +@property (readonly) uint64_t dsid; +@property (readonly) KCJoiningRequestSecretSessionState state; + +@property (readwrite) NSData* challenge; +@property (readwrite) NSData* salt; +@end + +@implementation KCJoiningRequestSecretSession : NSObject + +- (nullable NSData*) initialMessage: (NSError**) error { + NSData* start = [self->_context copyStart: error]; + if (start == nil) return nil; + + NSMutableData* initialMessage = [NSMutableData dataWithLength: sizeof_initialmessage(start)]; + + if (NULL == encode_initialmessage(start, error, initialMessage.mutableBytes, initialMessage.mutableBytes + initialMessage.length)) + return nil; + + return initialMessage; +} + +- (bool) isDone { + return self->_state == kRequestSecretDone; +} + +- (bool) setupSession: (NSError**) error { + NSData* key = [self->_context getKey]; + + if (key == nil) { + KCJoiningErrorCreate(kInternalError, error, @"No session key available"); + return nil; + } + + self->_session = [KCAESGCMDuplexSession sessionAsSender:key context:self.dsid]; + + return self.session != nil; +} + +- (nullable NSData*) copyResponseForChallenge:(NSData*) challenge + salt:(NSData*) salt + secret: (NSString*) password + error: (NSError**) error { + NSData* response = [self->_context copyResposeToChallenge:challenge + password:password + salt:salt + error:error]; + + if (!response) { + // @@@ return error to other side??? + return nil; + } else { + if (![self setupSession: error]) return nil; + + self.challenge = challenge; + self.salt = salt; + + self->_state = kExpectingHAMK; + return [[KCJoiningMessage messageWithType:kResponse + data:response + error:error] der]; + } +} + + +- (nullable NSData*) copyResponseForSecret: (NSString*) password + error: (NSError**) error { + return [self copyResponseForChallenge:self.challenge salt:self.salt secret:password error:error]; +} + +- (nullable NSData*) handleChallengeData: (NSData*) challengeData + secret: (NSString*) password + error: (NSError**) error { + NSData* challenge = nil; + NSData* salt = nil; + + if (![challengeData decodeSequenceData:&salt data:&challenge error:error]) return nil; + + return [self copyResponseForChallenge:challenge salt:salt secret:password error:error]; + +} + +- (nullable NSData*) handleChallenge: (KCJoiningMessage*) message + secret: (NSString*) password + error: (NSError**)error { + // Parse the challenge message + // Salt and Challenge packet + if ([message type] != kChallenge) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected challenge!"); + return nil; + } + + return [self handleChallengeData:[message firstData] secret:password error:error]; +} + +- (NSData*) handleChallenge: (KCJoiningMessage*) message error: (NSError**)error { + return [self handleChallenge:message + secret:[self.secretDelegate secret] + error:error]; + +} + +- (NSData*) handleVerification: (KCJoiningMessage*) message error: (NSError**) error { + if ([message type] == kError) { + bool newCode = [[message firstData] length] == 0; + NSString* nextSecret = [self.secretDelegate verificationFailed: newCode]; + + if (nextSecret) { + if (newCode) { + return [self copyResponseForSecret:nextSecret error:error]; + } else { + return [self handleChallengeData:[message firstData] secret:nextSecret error:error]; + } + } else { + return nil; + } + } + + if ([message type] != kVerification) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected verification!"); + return nil; + } + + if (![self.context verifyConfirmation:[message firstData] error:error]) { + // Sender thought we had it right, but he can't prove he has it right! + KCJoiningErrorCreate(kInternalError, error, @"Got verification but acceptor doesn't have matching secret: %@", self); + secnotice("request-session", "Verification failed: %@", self); + return nil; + } + + { + NSData* payload = [self.session decryptAndVerify:[message secondData] error:error]; + if (payload == nil) return nil; + + NSString* accountCode = [NSString decodeFromDER:payload error:error]; + if (accountCode == nil) return nil; + + if (![self.secretDelegate processAccountCode:accountCode error:error]) return nil; + } + + self->_state = kRequestSecretDone; + + return [NSData data]; +} + + + + +// [self.delegate processCircleJoinData:circleData error:error]; + +- (NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { + NSData* result = nil; + KCJoiningMessage* message = [KCJoiningMessage messageWithDER: incomingMessage error: error]; + if (message == nil) return nil; + + switch(self->_state) { + case kExpectingB: + return [self handleChallenge:message error: error]; + break; + case kExpectingHAMK: + return [self handleVerification:message error:error]; + break; + case kRequestSecretDone: + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Done, no messages expected."); + break; + } + + return result; +} + ++ (nullable instancetype)sessionWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + error: (NSError**) error { + return [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:secretDelegate + dsid:dsid + error:error]; +} + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + error: (NSError**)error { + int cc_error = 0; + struct ccrng_state * rng = ccrng(&cc_error); + + if (rng == nil) { + CoreCryptoError(cc_error, error, @"RNG fetch failed"); + return nil; + } + + return [self initWithSecretDelegate: secretDelegate + dsid: dsid + rng: rng + error: error]; +} + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + rng: (struct ccrng_state *)rng + error: (NSError**)error { + + self = [super init]; + + self->_secretDelegate = secretDelegate; + self->_state = kExpectingB; + self->_dsid = dsid; + + NSString* name = [NSString stringWithFormat: @"%llu", dsid]; + + self->_context = [[KCSRPClientContext alloc] initWithUser: name + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: rng]; + + return self; +} + +- (NSString*) stateString { + switch (self.state) { + case kExpectingB: return @"→B"; + case kExpectingHAMK: return @"→HAMK"; + case kRequestSecretDone: return @"SecretDone"; + default: return [NSString stringWithFormat:@"%d", self.state]; + } +} + +- (NSString *)description { + return [NSString stringWithFormat: @"", self, self.dsid, [self stateString], self.context]; +} + +@end + +@interface KCJoiningRequestCircleSession () +@property (readonly) NSObject* circleDelegate; +@property (readonly) KCAESGCMDuplexSession* session; +@property (readwrite) KCJoiningRequestCircleSessionState state; +@end + +@implementation KCJoiningRequestCircleSession +- (nullable NSData*) encryptedPeerInfo: (NSError**) error { + // Get our peer info and send it along: + if (self->_session == nil) { + KCJoiningErrorCreate(kInternalError, error, @"Attempt to encrypt with no session"); + return nil; + } + + SOSPeerInfoRef us = [self.circleDelegate copyPeerInfoError:error]; + if (us == NULL) return nil; + CFErrorRef cfError = NULL; + NSData* piEncoded = (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(us, NULL, &cfError); + + if (piEncoded == nil) { + if (error != nil) { + *error = (__bridge_transfer NSError*) cfError; + } + return nil; + } + + return [self->_session encrypt:piEncoded error:error]; +} + +- (nullable NSData*) initialMessage: (NSError**) error { + NSData* encryptedPi = [self encryptedPeerInfo:error]; + if (encryptedPi == nil) return nil; + + self->_state = kExpectingCircleBlob; + + return [[KCJoiningMessage messageWithType:kPeerInfo + data:encryptedPi + error:error] der]; + +} + +- (NSData*) handleCircleBlob: (KCJoiningMessage*) message error: (NSError**) error { + if ([message type] != kCircleBlob) { + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Expected CircleBlob!"); + return nil; + } + + NSData* circleBlob = [self.session decryptAndVerify:message.firstData error:error]; + if (circleBlob == nil) return nil; + + if (![self.circleDelegate processCircleJoinData: circleBlob error:error]) + return nil; + + self->_state = kRequestCircleDone; + + return [NSData data]; // Success, an empty message. +} + +- (NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error { + NSData* result = nil; + KCJoiningMessage* message = [KCJoiningMessage messageWithDER: incomingMessage error: error]; + if (message == nil) return nil; + + switch(self.state) { + case kExpectingCircleBlob: + return [self handleCircleBlob:message error:error]; + case kRequestCircleDone: + KCJoiningErrorCreate(kUnexpectedMessage, error, @"Done, no messages expected."); + break; + } + + return result; +} + +- (bool) isDone { + return self.state = kRequestCircleDone; +} + ++ (instancetype) sessionWithCircleDelegate: (NSObject*) circleDelegate + session: (KCAESGCMDuplexSession*) session + error: (NSError**) error { + return [[KCJoiningRequestCircleSession alloc] initWithCircleDelegate:circleDelegate + session:session + error:error]; +} + +- (instancetype) initWithCircleDelegate: (NSObject*) circleDelegate + session: (KCAESGCMDuplexSession*) session + error: (NSError**) error { + self = [super init]; + + self->_circleDelegate = circleDelegate; + self->_session = session; + self.state = kExpectingCircleBlob; + + return self; +} + +@end + diff --git a/KeychainCircle/KCJoiningSession.h b/KeychainCircle/KCJoiningSession.h new file mode 100644 index 00000000..6e66ea0b --- /dev/null +++ b/KeychainCircle/KCJoiningSession.h @@ -0,0 +1,197 @@ +// +// KCJoiningSession.h +// KeychainCircle +// +// + +#import +#import +#include + +NS_ASSUME_NONNULL_BEGIN + +@protocol KCJoiningRequestCircleDelegate +/*! + Get this devices peer info (As Application) + + @result + SOSPeerInfoRef object or NULL if we had an error. + */ +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error; + +/*! + Handle recipt of confirmed circleJoinData over the channel + + @parameter circleJoinData + Data the acceptor made to allow us to join the circle. + + */ +- (bool) processCircleJoinData: (NSData*) circleJoinData error: (NSError**)error; + +@end + +@protocol KCJoiningRequestSecretDelegate +/*! + Get the shared secret for this session. + Not called during creation or initialMessage: to allow the initial message to be sent before + we know the secret. + Called during message processing. + + @result + String containing shared secret for session + */ +- (NSString*) secret; + +/*! + Handle verification failure + @result + NULL if we should give up. Secret to use on retry, if not. + */ +- (NSString*) verificationFailed: (bool) codeChanged; + +/*! + Handle recipt of confirmed accountCode over the channel + + @parameter accountCode + Data the acceptor made to allow us to join the circle. + */ +- (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error; + +@end + +@interface KCJoiningRequestSecretSession : NSObject +@property (nullable, readonly) KCAESGCMDuplexSession* session; + +- (bool) isDone; + +- (nullable NSData*) initialMessage: (NSError**) error; +- (nullable NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error; + ++ (nullable instancetype)sessionWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + error: (NSError**) error; + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + error: (NSError**)error; + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) secretDelegate + dsid: (uint64_t)dsid + rng: (struct ccrng_state *)rng + error: (NSError**)error NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +@end + + +@interface KCJoiningRequestCircleSession : NSObject + +- (bool) isDone; + +- (nullable NSData*) initialMessage: (NSError**) error; +- (nullable NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error; + ++ (instancetype) sessionWithCircleDelegate: (NSObject*) circleDelegate + session: (KCAESGCMDuplexSession*) session + error: (NSError**) error; + +- (instancetype) initWithCircleDelegate: (NSObject*) circleDelegate + session: (KCAESGCMDuplexSession*) session + error: (NSError**) error NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; +@end + + +@protocol KCJoiningAcceptCircleDelegate +/*! + Handle the request's peer info and get the blob they can use to get in circle + @param peer + SOSPeerInfo sent from requestor to apply to the circle + @param error + Error resulting in looking at peer and trying to produce circle join data + @result + Data containing blob the requestor can use to get in circle + */ +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error; +@end + +typedef enum { + kKCRetryError = 0, + kKCRetryWithSameChallenge, + kKCRetryWithNewChallenge +} KCRetryOrNot; + +@protocol KCJoiningAcceptSecretDelegate +/*! + Get the shared secret for this session + @result + String containing shared secret for session +*/ +- (NSString*) secret; +/*! + Get the code the other device can use to access the account + @result + String containing code to access the account +*/ +- (NSString*) accountCode; + +/*! + Handle verification failure + @result + NULL if we should permit retry with the same secret. New secret if we've changed it. + */ +- (KCRetryOrNot) verificationFailed: (NSError**) error; + +@end + + +@interface KCJoiningAcceptSession : NSObject +/*! + create an appropriate joining session given the initial message. + + @parameter message + initial message received from the requestor + @parameter delegate + delegate which will provide data and processing (see KCJoiningAcceptSecretDelegate protocol + @parameter error + failures to find a session for the initial message + @result + KCJoiningAcceptSession that can handle the data from the peer + + */ ++ (nullable instancetype) sessionWithInitialMessage: (NSData*) message + secretDelegate: (NSObject*) delegate + circleDelegate: (NSObject*) delegate + dsid: (uint64_t) dsid + error: (NSError**) error; + + +- (nullable instancetype)initWithSecretDelegate: (NSObject*) delegate + circleDelegate: (NSObject*) delegate + dsid: (uint64_t) dsid + rng: (struct ccrng_state *)rng + error: (NSError**) error NS_DESIGNATED_INITIALIZER; + +/*! + create an appropriate joining session given the initial message. + + @parameter incomingMessage + message received from the requestor + @parameter error + failures parse the message + @result + Data to send to the requestor, or NULL if we had an error. + Calling this function when we are done results in an error return. + */ +- (nullable NSData*) processMessage: (NSData*) incomingMessage error: (NSError**) error; + +- (bool) isDone; + +- (id)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/KeychainCircle/KCSRPContext.h b/KeychainCircle/KCSRPContext.h new file mode 100644 index 00000000..c0d8149e --- /dev/null +++ b/KeychainCircle/KCSRPContext.h @@ -0,0 +1,76 @@ +// +// SRPSession.h +// KeychainCircle +// +// + +#import + +#include +#include +#include + +NS_ASSUME_NONNULL_BEGIN + +@interface KCSRPContext : NSObject + +- (instancetype) init NS_UNAVAILABLE; + +- (instancetype) initWithUser: (NSString*) user + digestInfo: (const struct ccdigest_info *) di + group: (ccsrp_const_gp_t) gp + randomSource: (struct ccrng_state *) rng NS_DESIGNATED_INITIALIZER; + +- (bool) isAuthenticated; + +// Returns an NSData that refers to the key in the context. +// It becomes invalid when this context is released. +- (NSData*) getKey; + +@end + +@interface KCSRPClientContext : KCSRPContext + +- (nullable NSData*) copyStart: (NSError**) error; +- (nullable NSData*) copyResposeToChallenge: (NSData*) B_data + password: (NSString*) password + salt: (NSData*) salt + error: (NSError**) error; +- (bool) verifyConfirmation: (NSData*) HAMK_data + error: (NSError**) error; + +@end + +@interface KCSRPServerContext : KCSRPContext +@property (readonly) NSData* salt; + +- (instancetype) initWithUser: (NSString*) user + salt: (NSData*) salt + verifier: (NSData*) verifier + digestInfo: (const struct ccdigest_info *) di + group: (ccsrp_const_gp_t) gp + randomSource: (struct ccrng_state *) rng NS_DESIGNATED_INITIALIZER; + +- (instancetype) initWithUser: (NSString*)user + password: (NSString*)password + digestInfo: (const struct ccdigest_info *) di + group: (ccsrp_const_gp_t) gp + randomSource: (struct ccrng_state *) rng NS_DESIGNATED_INITIALIZER; + +- (instancetype) initWithUser: (NSString*) user + digestInfo: (const struct ccdigest_info *) di + group: (ccsrp_const_gp_t) gp + randomSource: (struct ccrng_state *) rng NS_UNAVAILABLE; + + +- (bool) resetWithPassword: (NSString*) password + error: (NSError**) error; + +- (nullable NSData*) copyChallengeFor: (NSData*) A_data + error: (NSError**) error; +- (nullable NSData*) copyConfirmationFor: (NSData*) M_data + error: (NSError**) error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/KeychainCircle/KCSRPContext.m b/KeychainCircle/KCSRPContext.m new file mode 100644 index 00000000..dab973fe --- /dev/null +++ b/KeychainCircle/KCSRPContext.m @@ -0,0 +1,245 @@ +// +// SRPSession.m +// Security +// +// + + +#import +#import "KCSRPContext.h" + +#include + +#include +#include +#include +#include + +#import "NSError+KCCreationHelpers.h" + +static const NSStringEncoding srpStringEncoding = NSUTF8StringEncoding; + +@interface KCSRPContext () +@property (readwrite) ccsrp_ctx* context; +@property (readwrite) struct ccrng_state *rng; +@property (readwrite) NSString* user; +@end + +@implementation KCSRPContext + ++ (KCSRPContext*) createWithUser: (NSString*) user + digestInfo: (const struct ccdigest_info *) di + group: (ccsrp_const_gp_t) gp + randomSource: (struct ccrng_state *) rng { + return [[self alloc] initWithUser:user + digestInfo:di + group:gp + randomSource:rng]; +} + +- (NSData*) dataForPassword: (NSString*) password { + return [password dataUsingEncoding:srpStringEncoding]; +} + +- (nullable const char *) userNameString { + return [self.user cStringUsingEncoding:srpStringEncoding]; +} + +- (instancetype) initWithUser: (NSString*) user + digestInfo: (const struct ccdigest_info *) di + 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; + + return self; +} + +- (void) finalize { + ccsrp_ctx_clear(ccsrp_ctx_di(self.context), + ccsrp_ctx_gp(self.context), + self.context); + + free(self.context); +} + +- (NSData*) getKey { + size_t key_length = 0; + const void * key = ccsrp_get_session_key(self.context, &key_length); + + return key ? [NSData dataWithBytesNoCopy:(void *)key length:key_length freeWhenDone:false] : nil; +} + +- (bool) isAuthenticated { + return ccsrp_is_authenticated(self.context); +} + +@end + + +@implementation KCSRPClientContext + +- (NSData*) copyStart: (NSError**) error { + NSMutableData* A_data = [NSMutableData dataWithLength: ccsrp_exchange_size(self.context)]; + + int result = ccsrp_client_start_authentication(self.context, self.rng, A_data.mutableBytes); + if (!CoreCryptoError(result, error, @"Start packet copy failed: %d", result)) { + A_data = NULL; + } + + return A_data; +} + +static bool ExactDataSizeRequirement(NSData* data, NSUInteger expectedLength, NSError**error, NSString* name) { + return RequirementError(data.length == expectedLength, error, @"%@ incorrect size, Expected %ld, got %ld", name, (unsigned long)expectedLength, (unsigned long)data.length); +} + +- (nullable NSData*) copyResposeToChallenge: (NSData*) B_data + password: (NSString*) password + salt: (NSData*) salt + error: (NSError**) error { + + if (!ExactDataSizeRequirement(B_data, ccsrp_exchange_size(self.context), error, @"challenge data")) + return nil; + + NSMutableData* M_data = [NSMutableData dataWithLength: ccsrp_session_size(self.context)]; + NSData* passwordData = [self dataForPassword: password]; + + int result = ccsrp_client_process_challenge(self.context, + [self userNameString], + passwordData.length, + passwordData.bytes, + salt.length, + salt.bytes, + B_data.bytes, + M_data.mutableBytes); + + if (!CoreCryptoError(result, error, @"Challenge processing failed: %d", result)) { + M_data = NULL; + } + + return M_data; +} + +- (bool) verifyConfirmation: (NSData*) HAMK_data + error: (NSError**) error { + if (!ExactDataSizeRequirement(HAMK_data, ccsrp_session_size(self.context), error, @"confirmation data")) + return nil; + + return ccsrp_client_verify_session(self.context, HAMK_data.bytes); +} + +@end + +@interface KCSRPServerContext () +@property (readwrite) NSData* verifier; +@end + +@implementation KCSRPServerContext + +- (bool) resetWithPassword: (NSString*) password + error: (NSError**) error { + const int salt_length = 16; + + NSMutableData* salt = [NSMutableData dataWithLength: salt_length]; + NSMutableData* verifier = [NSMutableData dataWithLength: ccsrp_ctx_sizeof_n(self.context)]; + + NSData* passwordData = [self dataForPassword: password]; + + int generateResult = ccsrp_generate_salt_and_verification(self.context, + self.rng, + [self userNameString], + passwordData.length, + passwordData.bytes, + salt.length, + salt.mutableBytes, + verifier.mutableBytes); + + if (!CoreCryptoError(generateResult, error, @"Error generating SRP salt/verifier")) { + return false; + } + + self.verifier = verifier; + self->_salt = salt; + + return true; +} + +- (instancetype) initWithUser: (NSString*)user + password: (NSString*)password + 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; + } + + return self; +} + +- (instancetype) initWithUser: (NSString*) user + salt: (NSData*) salt + verifier: (NSData*) verifier + 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; + + return self; +} + + +- (NSData*) copyChallengeFor: (NSData*) A_data + error: (NSError**) error { + if (!ExactDataSizeRequirement(A_data, ccsrp_exchange_size(self.context), error, @"start data")) + return nil; + + NSMutableData* B_data = [NSMutableData dataWithLength: ccsrp_exchange_size(self.context)]; + + int result = ccsrp_server_start_authentication(self.context, self.rng, + [self userNameString], + self.salt.length, self.salt.bytes, + self.verifier.bytes, A_data.bytes, + B_data.mutableBytes); + + if (!CoreCryptoError(result, error, @"Server start authentication failed: %d", result)) { + B_data = NULL; + } + + return B_data; +} + +- (NSData*) copyConfirmationFor: (NSData*) M_data + error: (NSError**) error { + if (!ExactDataSizeRequirement(M_data, ccsrp_session_size(self.context), error, @"response data")) + return nil; + + NSMutableData* HAMK_data = [NSMutableData dataWithLength: ccsrp_session_size(self.context)]; + + bool verify = ccsrp_server_verify_session(self.context, M_data.bytes, HAMK_data.mutableBytes); + + if (!CoreCryptoError(!verify, error, @"SRP verification failed")) { + HAMK_data = NULL; + } + + return HAMK_data; +} + +@end diff --git a/KeychainCircle/KeychainCircle.h b/KeychainCircle/KeychainCircle.h new file mode 100644 index 00000000..8122f4e6 --- /dev/null +++ b/KeychainCircle/KeychainCircle.h @@ -0,0 +1,9 @@ +// +// KeychainCircle.h +// KeychainCircle +// + +#import +#import +#import +#import diff --git a/KeychainCircle/NSData+SecRandom.h b/KeychainCircle/NSData+SecRandom.h new file mode 100644 index 00000000..04f7f3fb --- /dev/null +++ b/KeychainCircle/NSData+SecRandom.h @@ -0,0 +1,11 @@ +// +// NSData+SecRandom.h +// Security +// +// + +@interface NSData (SecRandom) + ++ (instancetype) dataWithRandomBytes: (int) length; + +@end diff --git a/KeychainCircle/NSData+SecRandom.m b/KeychainCircle/NSData+SecRandom.m new file mode 100644 index 00000000..5de75615 --- /dev/null +++ b/KeychainCircle/NSData+SecRandom.m @@ -0,0 +1,26 @@ +// +// NSData+SecRandom.m +// Security +// +// Created by Mitch Adler on 4/15/16. +// +// + +#import +#import + +#include + +@implementation NSMutableData (SecRandom) + ++ (instancetype) dataWithRandomBytes: (int) length { + + NSMutableData* result = [NSMutableData dataWithLength: length]; + + if (0 != SecRandomCopyBytes(kSecRandomDefault, result.length, result.mutableBytes)) + return nil; + + return result; +} + +@end diff --git a/KeychainCircle/NSError+KCCreationHelpers.h b/KeychainCircle/NSError+KCCreationHelpers.h new file mode 100644 index 00000000..4a04a356 --- /dev/null +++ b/KeychainCircle/NSError+KCCreationHelpers.h @@ -0,0 +1,53 @@ +// +// NSError+KCCreationHelpers.h +// KeychainCircle +// +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +// Returns false and fills in error with formatted description if cc_result is an error +bool CoreCryptoError(int cc_result, NSError * _Nullable * _Nullable error, NSString * _Nonnull description, ...) NS_FORMAT_FUNCTION(3, 4); +// Returns false and fills in a requirement error if requirement is false +// We should have something better than -50 here. +bool RequirementError(bool requirement, NSError * _Nullable * _Nullable error, NSString * _Nonnull description, ...) NS_FORMAT_FUNCTION(3, 4); + +bool OSStatusError(OSStatus status, NSError * _Nullable * _Nullable error, NSString* _Nonnull description, ...) NS_FORMAT_FUNCTION(3, 4); + + +// MARK: Error Extensions +@interface NSError(KCCreationHelpers) + ++ (instancetype) errorWithOSStatus:(OSStatus) status + userInfo:(NSDictionary *)dict; + +- (instancetype) initWithOSStatus:(OSStatus) status + userInfo:(NSDictionary *)dict; + ++ (instancetype) errorWithOSStatus:(OSStatus) status + description:(NSString*)description + args:(va_list)va; + +- (instancetype) initWithOSStatus:(OSStatus) status + description:(NSString*)description + args:(va_list)va; + ++ (instancetype) errorWithCoreCryptoStatus:(int) status + userInfo:(NSDictionary *)dict; + +- (instancetype) initWithCoreCryptoStatus:(int) status + userInfo:(NSDictionary *)dict; + ++ (instancetype) errorWithCoreCryptoStatus:(int) status + description:(NSString*)description + args:(va_list)va; + +- (instancetype) initWithCoreCryptoStatus:(int) status + description:(NSString*)description + args:(va_list)va; + +@end + +NS_ASSUME_NONNULL_END diff --git a/KeychainCircle/NSError+KCCreationHelpers.m b/KeychainCircle/NSError+KCCreationHelpers.m new file mode 100644 index 00000000..0d0e6fc8 --- /dev/null +++ b/KeychainCircle/NSError+KCCreationHelpers.m @@ -0,0 +1,116 @@ +// +// NSError+KCCreationHelpers.m +// KechainCircle +// +// + +#import + +#import + +static NSString* coreCryptoDomain = @"kSecCoreCryptoDomain"; +static NSString* srpDomain = @"com.apple.security.srp"; + +static NSDictionary* UserInfoFromVA(NSString*description, va_list va) { + return @{NSLocalizedDescriptionKey:[[NSString alloc] initWithFormat:description + arguments:va]}; +} + +// We should get this from SecCFError.h and Security.framework.. +bool CoreCryptoError(int cc_result, NSError** error, NSString* description, ...) +{ + bool failed = cc_result != 0; + + if (failed && error && !*error) { + va_list va; + va_start(va, description); + *error = [NSError errorWithCoreCryptoStatus:cc_result + description:description + args:va]; + va_end(va); + } + + return !failed; +} + +bool OSStatusError(OSStatus status, NSError** error, NSString*description, ...) { + bool failed = status != 0; + + if (failed && error && !*error) { + va_list va; + va_start(va, description); + *error = [NSError errorWithOSStatus:status + description:description + args:va]; + va_end(va); + } + + return !failed; +} + +bool RequirementError(bool requirement, NSError** error, NSString*description, ...) { + bool failed = !requirement; + + if (failed && error && !*error) { + va_list va; + va_start(va, description); + *error = [NSError errorWithOSStatus:-50 + description:description + args:va]; + va_end(va); + } + + return !failed; +} + + +@implementation NSError(KCCreationHelpers) + ++ (instancetype) errorWithOSStatus:(OSStatus) status + userInfo:(NSDictionary *)dict { + return [[NSError alloc] initWithOSStatus:status userInfo:dict]; +} + +- (instancetype) initWithOSStatus:(OSStatus) status + userInfo:(NSDictionary *)dict { + return [self initWithDomain:NSOSStatusErrorDomain code:status userInfo:dict]; +} + ++ (instancetype) errorWithOSStatus:(OSStatus) status + description:(NSString*)description + args:(va_list)va { + return [[NSError alloc] initWithOSStatus:status description:description args:va]; +} + +- (instancetype) initWithOSStatus:(OSStatus) status + description:(NSString*)description + args:(va_list)va { + return [self initWithOSStatus:status + userInfo:UserInfoFromVA(description, va)]; +} + ++ (instancetype) errorWithCoreCryptoStatus:(int) status + userInfo:(NSDictionary *)dict { + return [[NSError alloc] initWithCoreCryptoStatus:status userInfo:dict]; +} + + +- (instancetype) initWithCoreCryptoStatus:(int) status + userInfo:(NSDictionary *)dict { + return [self initWithDomain:coreCryptoDomain code:status userInfo:dict]; +} + ++ (instancetype) errorWithCoreCryptoStatus:(int) status + description:(NSString*)description + args:(va_list)va { + return [[NSError alloc] initWithCoreCryptoStatus:status description:description args:va]; +} + +- (instancetype) initWithCoreCryptoStatus:(int) status + description:(NSString*)description + args:(va_list)va { + return [self initWithCoreCryptoStatus:status + userInfo:UserInfoFromVA(description, va)]; +} + +@end diff --git a/KeychainCircle/Tests/Info.plist b/KeychainCircle/Tests/Info.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/KeychainCircle/Tests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/KeychainCircle/Tests/KCAESGCMTest.m b/KeychainCircle/Tests/KCAESGCMTest.m new file mode 100644 index 00000000..25e02df7 --- /dev/null +++ b/KeychainCircle/Tests/KCAESGCMTest.m @@ -0,0 +1,138 @@ +// +// KCAESGCMTest.m +// Keychain Circle +// +// + +#import + +#import +#import + +@interface KCAESGCMTest : XCTestCase + +@end + +@implementation KCAESGCMTest + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void) sendMessage: (NSData*) message + from: (KCAESGCMDuplexSession*) sender + to: (KCAESGCMDuplexSession*) receiver { + NSError* error = nil; + NSData* sendToRecv = [sender encrypt:message error:&error]; + + XCTAssertNil(error, @"Got error"); + XCTAssertNotNil(sendToRecv, @"Failed to get data"); + + error = nil; + NSData* decryptedSendToRecv = [receiver decryptAndVerify:sendToRecv error:&error]; + + XCTAssertNil(error, @"Error decrypting"); + XCTAssertNotNil(decryptedSendToRecv, @"Got decryption"); + + XCTAssertEqualObjects(message, decryptedSendToRecv, @"Send to recv failed."); +} + +- (void)testAESGCMDuplex { + uint64_t context = 0x81FC134000123041; + uint8_t secretBytes[] = { 0x11, 0x22, 0x33, 0x13, 0x44, 0xF1, 0x13, 0x92, 0x11, 0x22, 0x33, 0x13, 0x44, 0xF1, 0x13, 0x92 }; + NSData* secret = [NSData dataWithBytes:secretBytes length:sizeof(secretBytes)]; + + KCAESGCMDuplexSession* sender = [KCAESGCMDuplexSession sessionAsSender:secret + context:context]; + + KCAESGCMDuplexSession* receiver = [KCAESGCMDuplexSession sessionAsReceiver:secret + context:context]; + + uint8_t sendToRecvBuffer[] = { 0x1, 0x2, 0x3, 0x88, 0xFF, 0xE1 }; + NSData* sendToRecvData = [NSData dataWithBytes:sendToRecvBuffer length:sizeof(sendToRecvBuffer)]; + + [self sendMessage:sendToRecvData from:sender to:receiver]; + + uint8_t recvToSendBuffer[] = { 0x81, 0x52, 0x63, 0x88, 0xFF, 0xE1 }; + NSData* recvToSendData = [NSData dataWithBytes:recvToSendBuffer length:sizeof(recvToSendBuffer)]; + + [self sendMessage:recvToSendData from:receiver to:sender]; +} + +- (KCAESGCMDuplexSession*) archiveDearchive: (KCAESGCMDuplexSession*) original { + NSMutableData *data = [NSMutableData data]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [archiver encodeObject:original forKey:@"Top"]; + [archiver finishEncoding]; + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + + // Customize the unarchiver. + KCAESGCMDuplexSession *result = [unarchiver decodeObjectForKey:@"Top"]; + [unarchiver finishDecoding]; + + return result; +} + +- (void)doAESGCMDuplexCodingFlattenSender: (bool) flattenSender + Receiver: (bool) flattenReceiver { + uint64_t context = 0x81FC134000123041; + uint8_t secretBytes[] = { 0x73, 0xb7, 0x7f, 0xff, 0x7f, 0xe3, 0x44, 0x6b, 0xa4, 0xec, 0x9d, 0x5d, 0x68, 0x12, 0x13, 0x71 }; + NSData* secret = [NSData dataWithBytes:secretBytes length:sizeof(secretBytes)]; + + KCAESGCMDuplexSession* sender = [KCAESGCMDuplexSession sessionAsSender:secret + context:context]; + + KCAESGCMDuplexSession* receiver = [KCAESGCMDuplexSession sessionAsReceiver:secret + context:context]; + + { + uint8_t sendToRecvBuffer[] = { 0x0e, 0x9b, 0x9d, 0x2c, 0x90, 0x96, 0x8a }; + NSData* sendToRecvData = [NSData dataWithBytes:sendToRecvBuffer length:sizeof(sendToRecvBuffer)]; + + [self sendMessage:sendToRecvData from:sender to:receiver]; + + + uint8_t recvToSendBuffer[] = { 0x9b, 0x63, 0xaf, 0xb5, 0x4d, 0xa0, 0xfa, 0x9d, 0x90 }; + NSData* recvToSendData = [NSData dataWithBytes:recvToSendBuffer length:sizeof(recvToSendBuffer)]; + + [self sendMessage:recvToSendData from:receiver to:sender]; + } + + // Re-encode... + if (flattenSender) { + sender = [self archiveDearchive:sender]; + } + + if (flattenReceiver) { + receiver = [self archiveDearchive:receiver]; + } + + { + uint8_t sendToRecvBuffer[] = { 0xae, 0xee, 0x5f, 0x62, 0xb2, 0x72, 0x6f, 0x0a, 0xb6, 0x56 }; + NSData* sendToRecvData = [NSData dataWithBytes:sendToRecvBuffer length:sizeof(sendToRecvBuffer)]; + + [self sendMessage:sendToRecvData from:sender to:receiver]; + + + uint8_t recvToSendBuffer[] = { 0x49, 0x0b, 0xbb, 0x2d, 0x20, 0xb1, 0x8a, 0xfc, 0xba, 0xd1, 0xFF }; + NSData* recvToSendData = [NSData dataWithBytes:recvToSendBuffer length:sizeof(recvToSendBuffer)]; + + [self sendMessage:recvToSendData from:receiver to:sender]; + } +} + +- (void)testAESGCMDuplexCoding { + [self doAESGCMDuplexCodingFlattenSender:NO Receiver:YES]; + [self doAESGCMDuplexCodingFlattenSender:YES Receiver:NO]; + [self doAESGCMDuplexCodingFlattenSender:YES Receiver:YES]; +} + + +@end diff --git a/KeychainCircle/Tests/KCDerTest.m b/KeychainCircle/Tests/KCDerTest.m new file mode 100644 index 00000000..c4dcc319 --- /dev/null +++ b/KeychainCircle/Tests/KCDerTest.m @@ -0,0 +1,114 @@ +// +// KCDerTest.m +// Security +// +// + +#import + +#import +#import + +@interface KCDerTest : XCTestCase + +@end + +@implementation KCDerTest + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void) roundTripData: (NSData*) data { + NSError* error = nil; + size_t size = kcder_sizeof_data(data, &error); + + XCTAssert(size != 0, @"Bad size: %@", data); + + if (size == 0) + return; + + uint8_t buffer[size]; + error = nil; + uint8_t* beginning = kcder_encode_data(data, &error, buffer, buffer + sizeof(buffer)); + + XCTAssert(beginning != NULL, "Error encoding: %@", error); + + if (beginning == NULL) + return; + + XCTAssertEqual(beginning, &buffer[0], @"Size != buffer use"); + + NSData* recovered = nil; + + error = nil; + const uint8_t* end = kcder_decode_data(&recovered, &error, buffer, buffer + sizeof(buffer)); + + XCTAssert(end != NULL, "Error decoding: %@", error); + + if (end == NULL) + return; + + XCTAssertEqual(end, buffer + sizeof(buffer), @"readback didn't use all the buffer"); + + XCTAssertEqualObjects(data, recovered, @"Didn't get equal object"); + +} + +- (void)testData { + [self roundTripData: [NSData data]]; + + uint8_t bytes[] = { 1, 2, 3, 0xFF, 4, 0x0, 0xA }; + [self roundTripData: [NSData dataWithBytes:bytes length:sizeof(bytes)]]; +} + +- (void) roundTripString: (NSString*) string { + NSError* error = nil; + + size_t size = kcder_sizeof_string(string, &error); + + XCTAssert(size != 0, @"Bad size: %@", string); + + if (size == 0) + return; + + uint8_t buffer[size]; + error = nil; + uint8_t* beginning = kcder_encode_string(string, &error, buffer, buffer + sizeof(buffer)); + + XCTAssert(beginning != NULL, "Error encoding: %@", error); + + if (beginning == NULL) + return; + + XCTAssertEqual(beginning, &buffer[0], @"Size != buffer use"); + + NSString* recovered = nil; + + error = nil; + const uint8_t* end = kcder_decode_string(&recovered, &error, buffer, buffer + sizeof(buffer)); + + XCTAssert(end != NULL, "Error decoding: %@", error); + + if (end == NULL) + return; + + XCTAssertEqual(end, buffer + sizeof(buffer), @"readback didn't use all the buffer"); + + XCTAssertEqualObjects(string, recovered, @"Didn't get equal object"); + +} + +- (void)testString { + [self roundTripString: [NSString stringWithCString:"Test" encoding:NSUTF8StringEncoding]]; + [self roundTripString: [NSString stringWithCString:"ü😍🐸✝️₧➜" encoding:NSUTF8StringEncoding]]; +} + + +@end diff --git a/KeychainCircle/Tests/KCJoiningSessionTest.m b/KeychainCircle/Tests/KCJoiningSessionTest.m new file mode 100644 index 00000000..d44a297f --- /dev/null +++ b/KeychainCircle/Tests/KCJoiningSessionTest.m @@ -0,0 +1,579 @@ +// +// KCJoiningSessionTest.m +// Security +// +// + +#import + +#import + +#import +#import +#import +#import + +#include +#include +#include + +#include + + +__unused static SOSFullPeerInfoRef SOSNSFullPeerInfoCreate(NSDictionary* gestalt, + NSData* backupKey, SecKeyRef signingKey, + NSError**error) +{ + CFErrorRef errorRef = NULL; + + SOSFullPeerInfoRef result = SOSFullPeerInfoCreate(NULL, (__bridge CFDictionaryRef) gestalt, (__bridge CFDataRef) backupKey, signingKey, &errorRef); + + if (errorRef && error) { + *error = (__bridge_transfer NSError*) errorRef; + errorRef = NULL; + } + + return result; +} + +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); +} + + +__unused static SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(NSString* name, SecKeyRef* outSigningKey, NSError** error) +{ + if (outSigningKey == NULL) + return NULL; + + *outSigningKey = GenerateFullECKey(256, error); + if (*outSigningKey == NULL) + return NULL; + + return SOSNSFullPeerInfoCreate(@{(__bridge NSString*)kPIUserDefinedDeviceNameKey:name}, nil, *outSigningKey, error); +} + + +@interface KCJoiningRequestTestDelegate : NSObject +@property (readwrite) NSString* sharedSecret; + +@property (readonly) NSString* accountCode; +@property (readonly) NSData* circleJoinData; +@property (readwrite) SOSPeerInfoRef peerInfo; + +@property (readwrite) NSString* incorrectSecret; +@property (readwrite) int incorrectTries; + + ++ (id) requestDelegateWithSecret:(NSString*) secret; +- (id) init NS_UNAVAILABLE; +- (id) initWithSecret: (NSString*) secret + incorrectSecret: (NSString*) wrongSecret + incorrectTries: (int) retries NS_DESIGNATED_INITIALIZER; +- (NSString*) secret; +- (NSString*) verificationFailed: (bool) codeChanged; +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error; +- (bool) processCircleJoinData: (NSData*) circleJoinData error: (NSError**)error ; +- (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error; + +@end + +@implementation KCJoiningRequestTestDelegate + ++ (id) requestDelegateWithSecret:(NSString*) secret { + return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret + incorrectSecret:@"" + incorrectTries:0]; +} + ++ (id) requestDelegateWithSecret:(NSString*) secret + incorrectSecret:(NSString*) wrongSecret + incorrectTries:(int) retries { + return [[KCJoiningRequestTestDelegate alloc] initWithSecret:secret + incorrectSecret:wrongSecret + incorrectTries:retries]; +} + + +- (id) initWithSecret: (NSString*) secret + incorrectSecret: (NSString*) incorrectSecret + incorrectTries: (int) retries { + self = [super init]; + + SecKeyRef signingKey = GenerateFullECKey(256, NULL); + + self.peerInfo = SOSPeerInfoCreate(NULL, (__bridge CFDictionaryRef) @{(__bridge NSString*)kPIUserDefinedDeviceNameKey:@"Fakey"}, NULL, signingKey, NULL); + + if (self.peerInfo == NULL) + return nil; + + self.sharedSecret = secret; + self.incorrectSecret = incorrectSecret; + self.incorrectTries = retries; + + return self; +} + +- (NSString*) nextSecret { + if (self.incorrectTries > 0) { + self.incorrectTries -= 1; + return self.incorrectSecret; + } + return self.sharedSecret; +} + +- (NSString*) secret { + return [self nextSecret]; +} + +- (NSString*) verificationFailed: (bool) codeChanged { + return [self nextSecret]; +} + +- (SOSPeerInfoRef) copyPeerInfoError: (NSError**) error { + return self.peerInfo; +} + +- (bool) processCircleJoinData: (NSData*) circleJoinData error: (NSError**)error { + self->_circleJoinData = circleJoinData; + return true; +} + +- (bool) processAccountCode: (NSString*) accountCode error: (NSError**)error { + self->_accountCode = accountCode; + return true; +} + +@end + +@interface KCJoiningAcceptTestDelegate : NSObject +@property (readonly) NSArray* secrets; +@property (readwrite) NSUInteger currentSecret; +@property (readwrite) int retriesLeft; +@property (readwrite) int retriesPerSecret; + +@property (readonly) NSString* codeToUse; +@property (readonly) NSData* circleJoinData; +@property (readonly) SOSPeerInfoRef peerInfo; + ++ (id) acceptDelegateWithSecret: (NSString*) secret code: (NSString*) code; ++ (id) acceptDelegateWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code; +- (id) initWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code NS_DESIGNATED_INITIALIZER; + + +- (NSString*) secret; +- (NSString*) accountCode; + +- (KCRetryOrNot) verificationFailed: (NSError**) error; +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error; + +- (id) init NS_UNAVAILABLE; + +@end + +@implementation KCJoiningAcceptTestDelegate + ++ (id) acceptDelegateWithSecrets: (NSArray*) secrets retries: (int) retries code: (NSString*) code { + return [[KCJoiningAcceptTestDelegate alloc] initWithSecrets:secrets retries:retries code:code]; + +} + ++ (id) acceptDelegateWithSecret: (NSString*) secret code: (NSString*) code { + return [[KCJoiningAcceptTestDelegate alloc] initWithSecret:secret code:code]; +} + +- (id) initWithSecret: (NSString*) secret code: (NSString*) code { + return [self initWithSecrets:@[secret] retries:3 code:code]; +} + +- (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; + + 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; +} + +- (KCRetryOrNot) advanceSecret { + if (self.retriesLeft == 0) { + self.currentSecret += 1; + if (self.currentSecret >= [self.secrets count]) { + self.currentSecret = [self.secrets count] - 1; + } + self.retriesLeft = self.retriesPerSecret; + return kKCRetryWithNewChallenge; + } else { + self.retriesLeft -= 1; + return kKCRetryWithSameChallenge; + } +} + +- (NSString*) secret { + return self.secrets[self.currentSecret]; +} +- (NSString*) accountCode { + return self.codeToUse; +} + +- (KCRetryOrNot) verificationFailed: (NSError**) error { + return [self advanceSecret]; +} + +- (NSData*) circleJoinDataFor: (SOSPeerInfoRef) peer + error: (NSError**) error { + uint8_t joinDataBuffer[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + + self->_peerInfo = peer; + return [NSData dataWithBytes: joinDataBuffer length: sizeof(joinDataBuffer) ]; +} + + +@end + + +@interface KCJoiningSessionTest : XCTestCase + +@end + +@implementation KCJoiningSessionTest + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testJoiningSession { + NSError* error = nil; + + NSString* secret = @"123456"; + NSString* code = @"987654"; + + uint64_t dsid = 0x1234567887654321; + + KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; + KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + NSData* initialMessage = [requestSession initialMessage: &error]; + + XCTAssertNotNil(initialMessage, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + KCJoiningAcceptTestDelegate* acceptDelegate = [KCJoiningAcceptTestDelegate acceptDelegateWithSecret:secret code:code]; + KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate + circleDelegate:acceptDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + error = nil; + NSData* challenge = [acceptSession processMessage: initialMessage error: &error]; + + XCTAssertNotNil(challenge, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* response = [requestSession processMessage: challenge error: &error]; + + XCTAssertNotNil(response, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* verification = [acceptSession processMessage: response error: &error]; + + XCTAssertNotNil(verification, @"No verification message"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* doneMessage = [requestSession processMessage: verification error: &error]; + + XCTAssertNotNil(doneMessage, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSession isDone], @"SecretSession done"); + XCTAssertFalse([acceptSession isDone], @"Unexpected accept session done"); + + KCAESGCMDuplexSession* aesSession = [requestSession session]; + requestSession = nil; + + KCJoiningRequestCircleSession* requestSecretSession = [KCJoiningRequestCircleSession sessionWithCircleDelegate:requestDelegate session:aesSession error:&error]; + + XCTAssertNotNil(requestSecretSession, @"No request secret session"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* peerInfoMessage = [requestSecretSession initialMessage: &error]; + + XCTAssertNotNil(peerInfoMessage, @"No peerInfo message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertEqualObjects(requestDelegate.accountCode, acceptDelegate.codeToUse, @"Code made it"); + + error = nil; + NSData* blobMessage = [acceptSession processMessage:peerInfoMessage error: &error]; + + XCTAssertNotNil(blobMessage, @"No blob message"); + XCTAssertNil(error, @"Got error %@", error); + + // We have different peer_info types due to wierd linking of our tests. + // Compare the der representations: + NSData* rp_der = requestDelegate.peerInfo != nil ? (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(requestDelegate.peerInfo, NULL, NULL) : nil; + NSData* ap_der = acceptDelegate.peerInfo != nil ? (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(acceptDelegate.peerInfo, NULL, NULL) : nil; + + XCTAssertEqualObjects(rp_der, ap_der, @"Peer infos match"); + + error = nil; + NSData* nothing = [requestSecretSession processMessage:blobMessage error: &error]; + + XCTAssertEqualObjects(requestDelegate.circleJoinData, acceptDelegate.circleJoinData); + + XCTAssertNotNil(nothing, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSecretSession isDone], @"requesor done"); + XCTAssertTrue([acceptSession isDone], @"acceptor done"); + +} + +- (void)testJoiningSessionRetry { + NSError* error = nil; + + NSString* secret = @"123456"; + NSString* code = @"987654"; + + uint64_t dsid = 0x1234567887654321; + + KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret incorrectSecret:@"777888" incorrectTries:3]; + KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + NSData* initialMessage = [requestSession initialMessage: &error]; + + XCTAssertNotNil(initialMessage, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + KCJoiningAcceptTestDelegate* acceptDelegate = [KCJoiningAcceptTestDelegate acceptDelegateWithSecret:secret code:code]; + KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate + circleDelegate:acceptDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + error = nil; + NSData* challenge = [acceptSession processMessage: initialMessage error: &error]; + + XCTAssertNotNil(challenge, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + NSData* response = nil; + NSData* verification = nil; + + NSData* nextChallenge = challenge; + for (int tries = 0; tries < 4; ++tries) { + error = nil; + response = [requestSession processMessage: nextChallenge error: &error]; + + XCTAssertNotNil(response, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertNotEqualObjects(requestDelegate.accountCode, acceptDelegate.codeToUse, @"Code should not make it"); + + error = nil; + verification = [acceptSession processMessage: response error: &error]; + + XCTAssertNotNil(verification, @"No verification message"); + XCTAssertNil(error, @"Got error %@", error); + + nextChallenge = verification; + } + + error = nil; + NSData* doneMessage = [requestSession processMessage: verification error: &error]; + + XCTAssertNotNil(doneMessage, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSession isDone], @"SecretSession done"); + XCTAssertFalse([acceptSession isDone], @"Unexpected accept session done"); + + KCAESGCMDuplexSession* aesSession = [requestSession session]; + requestSession = nil; + + error = nil; + KCJoiningRequestCircleSession* requestSecretSession = [KCJoiningRequestCircleSession sessionWithCircleDelegate:requestDelegate session:aesSession error:&error]; + + XCTAssertNotNil(requestSecretSession, @"No request secret session"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* peerInfoMessage = [requestSecretSession initialMessage: &error]; + + XCTAssertNotNil(peerInfoMessage, @"No peerInfo message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertEqualObjects(requestDelegate.accountCode, acceptDelegate.codeToUse, @"Code made it"); + + error = nil; + NSData* blobMessage = [acceptSession processMessage:peerInfoMessage error: &error]; + + XCTAssertNotNil(blobMessage, @"No blob message"); + XCTAssertNil(error, @"Got error %@", error); + + // We have different peer_info types due to wierd linking of our tests. + // Compare the der representations: + NSData* rp_der = requestDelegate.peerInfo != nil ? (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(requestDelegate.peerInfo, NULL, NULL) : nil; + NSData* ap_der = acceptDelegate.peerInfo != nil ? (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(acceptDelegate.peerInfo, NULL, NULL) : nil; + + XCTAssertEqualObjects(rp_der, ap_der, @"Peer infos match"); + + error = nil; + NSData* nothing = [requestSecretSession processMessage:blobMessage error: &error]; + + XCTAssertEqualObjects(requestDelegate.circleJoinData, acceptDelegate.circleJoinData); + + XCTAssertNotNil(nothing, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSecretSession isDone], @"requesor done"); + XCTAssertTrue([acceptSession isDone], @"acceptor done"); + +} + +- (void)testJoiningSessionCodeChange { + NSError* error = nil; + + NSString* secret = @"123456"; + NSString* code = @"987654"; + + uint64_t dsid = 0x1234567887654321; + + KCJoiningRequestTestDelegate* requestDelegate = [KCJoiningRequestTestDelegate requestDelegateWithSecret: secret]; + KCJoiningRequestSecretSession *requestSession = [[KCJoiningRequestSecretSession alloc] initWithSecretDelegate:requestDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + NSData* initialMessage = [requestSession initialMessage: &error]; + + XCTAssertNotNil(initialMessage, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + KCJoiningAcceptTestDelegate* acceptDelegate = [KCJoiningAcceptTestDelegate acceptDelegateWithSecrets:@[@"222222", @"3333333", secret] retries:1 code:code]; + KCJoiningAcceptSession* acceptSession = [[KCJoiningAcceptSession alloc] initWithSecretDelegate:acceptDelegate + circleDelegate:acceptDelegate + dsid:dsid + rng:ccDRBGGetRngState() + error:&error]; + + error = nil; + NSData* challenge = [acceptSession processMessage: initialMessage error: &error]; + + XCTAssertNotNil(challenge, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + NSData* response = nil; + NSData* verification = nil; + + NSData* nextChallenge = challenge; + for (int tries = 0; tries < 5; ++tries) { + error = nil; + response = [requestSession processMessage: nextChallenge error: &error]; + + XCTAssertNotNil(response, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertNotEqualObjects(requestDelegate.accountCode, acceptDelegate.codeToUse, @"Code should not make it"); + + error = nil; + verification = [acceptSession processMessage: response error: &error]; + + XCTAssertNotNil(verification, @"No verification message"); + XCTAssertNil(error, @"Got error %@", error); + + nextChallenge = verification; + } + + error = nil; + NSData* doneMessage = [requestSession processMessage: verification error: &error]; + + XCTAssertNotNil(doneMessage, @"No response message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSession isDone], @"SecretSession done"); + XCTAssertFalse([acceptSession isDone], @"Unexpected accept session done"); + + KCAESGCMDuplexSession* aesSession = [requestSession session]; + requestSession = nil; + + error = nil; + KCJoiningRequestCircleSession* requestSecretSession = [KCJoiningRequestCircleSession sessionWithCircleDelegate:requestDelegate session:aesSession error:&error]; + + XCTAssertNotNil(requestSecretSession, @"No request secret session"); + XCTAssertNil(error, @"Got error %@", error); + + error = nil; + NSData* peerInfoMessage = [requestSecretSession initialMessage: &error]; + + XCTAssertNotNil(peerInfoMessage, @"No peerInfo message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertEqualObjects(requestDelegate.accountCode, acceptDelegate.codeToUse, @"Code made it"); + + error = nil; + NSData* blobMessage = [acceptSession processMessage:peerInfoMessage error: &error]; + + XCTAssertNotNil(blobMessage, @"No blob message"); + XCTAssertNil(error, @"Got error %@", error); + + // We have different peer_info types due to wierd linking of our tests. + // Compare the der representations: + NSData* rp_der = requestDelegate.peerInfo != nil ? (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(requestDelegate.peerInfo, NULL, NULL) : nil; + NSData* ap_der = acceptDelegate.peerInfo != nil ? (__bridge_transfer NSData*) SOSPeerInfoCopyEncodedData(acceptDelegate.peerInfo, NULL, NULL) : nil; + + XCTAssertEqualObjects(rp_der, ap_der, @"Peer infos match"); + + error = nil; + NSData* nothing = [requestSecretSession processMessage:blobMessage error: &error]; + + XCTAssertEqualObjects(requestDelegate.circleJoinData, acceptDelegate.circleJoinData); + + XCTAssertNotNil(nothing, @"No initial message"); + XCTAssertNil(error, @"Got error %@", error); + + XCTAssertTrue([requestSecretSession isDone], @"requesor done"); + XCTAssertTrue([acceptSession isDone], @"acceptor done"); + +} + +@end diff --git a/KeychainCircle/Tests/KCSRPTests.m b/KeychainCircle/Tests/KCSRPTests.m new file mode 100644 index 00000000..e518a261 --- /dev/null +++ b/KeychainCircle/Tests/KCSRPTests.m @@ -0,0 +1,108 @@ +// +// KeychainCircleTests.m +// KeychainCircleTests +// +// + +#import + +#import "KCSRPContext.h" +#include +#include +#include +#include + +@interface KCSRPTests : XCTestCase + +@end + +@implementation KCSRPTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void) negotiateWithUser: (NSString*) user + digestInfo: (const struct ccdigest_info*) di + group: (ccsrp_const_gp_t) group + randomSource: (struct ccrng_state *) rng { + + NSString* password = @"TryMeAs a ü password, sucka"; + + KCSRPClientContext * client = [[KCSRPClientContext alloc] initWithUser: user + digestInfo: di + group: group + randomSource: rng]; + XCTAssert([client getKey] == NULL, @"No key yet"); + XCTAssert(![client isAuthenticated], @"Not yet authenticated"); + + XCTAssert(client, @"No KCSRPClientContext created"); + + KCSRPServerContext * server = [[KCSRPServerContext alloc] initWithUser:user + password:password + digestInfo:di + group:group + randomSource:rng]; + + + XCTAssert(server, @"No KCSRPServerContext created"); + + XCTAssert([server getKey] == NULL, @"No key yet"); + + NSError* error = nil; + + NSData* A_data = [client copyStart:&error]; + XCTAssert(A_data, @"copied start failed (%@)", error); + error = nil; + + XCTAssert([client getKey] == NULL, @"Shouldn't have key"); + XCTAssert(![client isAuthenticated], @"Not yet authenticated"); + + NSData* B_data = [server copyChallengeFor:A_data error: &error]; + XCTAssert(B_data, @"Copied challenge for start failed (%@)", error); + error = nil; + + XCTAssert([server getKey] != NULL, @"Should have key"); + XCTAssert(![server isAuthenticated], @"Not yet authenticated"); + + NSData* M_data = [client copyResposeToChallenge:B_data + password:password + salt:server.salt + error:&error]; + XCTAssert(M_data, @"Copied responseToChallenge failed (%@)", error); + error = nil; + + XCTAssert([client getKey] != NULL, @"Don't have key"); + XCTAssert(![client isAuthenticated], @"Not yet authenticated"); + + NSData* HAMK_data = [server copyConfirmationFor:M_data error:&error]; + XCTAssert(HAMK_data, @"Copied confirmation failed (%@)", error); + error = nil; + + XCTAssert([server getKey] != NULL, @"Don't have key"); + XCTAssert([server isAuthenticated], @"Not yet authenticated"); + + bool verified = [client verifyConfirmation:HAMK_data error:&error]; + XCTAssert(verified, @"Verification failed (%@)", error); + error = nil; + + XCTAssert([client getKey] != NULL, @"Don't have key"); + XCTAssert([client isAuthenticated], @"Should be authenticated"); + + +} + +- (void)testNegotiation { + [self negotiateWithUser: @"TestUser" + digestInfo: ccsha256_di() + group: ccsrp_gp_rfc5054_3072() + randomSource: ccDRBGGetRngState()]; +} + +@end diff --git a/KeychainCircle/Tests/KeychainCircle.plist b/KeychainCircle/Tests/KeychainCircle.plist new file mode 100644 index 00000000..daf13f84 --- /dev/null +++ b/KeychainCircle/Tests/KeychainCircle.plist @@ -0,0 +1,102 @@ + + + + + BATSConfigVersion + 0.1.0 + Project + Security + TestSpecificLogs + + /var/log/module/com.apple.securityd/security.log.* + /var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/security.log.* + + Tests + + + TestName + KCDer + WorkingDirectory + /AppleInternal/Tests/Security + Arch + platform-native + AsRoot + + Command + + BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest KCDerTest KeychainCircleTests.xctest + + + + TestName + KCAESGCM + WorkingDirectory + /AppleInternal/Tests/Security + Arch + platform-native + AsRoot + + Command + + BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplex KeychainCircleTests.xctest + + + + TestName + KCAESGCMCoding + WorkingDirectory + /AppleInternal/Tests/Security + Arch + platform-native + AsRoot + + Command + + BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testAESGCMDuplexCoding KeychainCircleTests.xctest + + + + TestName + JoiningSession + WorkingDirectory + /AppleInternal/Tests/Security + Arch + platform-native + AsRoot + + Command + + BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSession KeychainCircleTests.xctest + + + + TestName + JoiningSessionRetry + WorkingDirectory + /AppleInternal/Tests/Security + Arch + platform-native + AsRoot + + Command + + BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionRetry KeychainCircleTests.xctest + + + + TestName + JoiningSessionCodeChange + WorkingDirectory + /AppleInternal/Tests/Security + Arch + platform-native + AsRoot + + Command + + BATS_XCTEST_CMD -NSTreatUnknownArgumentsAsOpen NO -ApplePersistenceIgnoreState YES -XCTest testJoiningSessionCodeChange KeychainCircleTests.xctest + + + + + diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist index 9806922e..d11ac900 100644 --- a/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.apple.security.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m index 3d522f93..c710f866 100644 --- a/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m +++ b/KeychainSyncAccountNotification/KeychainSyncAccountNotification.m @@ -2,15 +2,16 @@ // KeychainSyncAccountNotification.m // Security // -// Created by keith on 5/2/13. -// -// #import "KeychainSyncAccountNotification.h" #import #import #import +#if TARGET_OS_IPHONE #import +#else +#import +#endif #import #import #import @@ -18,12 +19,22 @@ @implementation KeychainSyncAccountNotification + +- (bool)accountIsPrimary:(ACAccount *)account +{ +#if TARGET_OS_IPHONE + return [account aa_isPrimaryAccount]; +#else + return [account icaIsPrimaryAccount]; +#endif +} + - (BOOL)account:(ACAccount *)account willChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { if ((changeType == kACAccountChangeTypeDeleted) && [oldAccount.accountType.identifier isEqualToString:ACAccountTypeIdentifierAppleAccount]) { if(oldAccount.identifier != NULL && oldAccount.username !=NULL){ - if ([oldAccount aa_isPrimaryAccount]) { + if ([self accountIsPrimary:oldAccount]) { CFErrorRef removalError = NULL; @@ -48,7 +59,8 @@ - (void)account:(ACAccount *)account didChangeWithType:(ACAccountChangeType)changeType inStore:(ACDAccountStore *)store oldAccount:(ACAccount *)oldAccount { if (changeType == kACAccountChangeTypeDeleted) { if (oldAccount.identifier != NULL && oldAccount.username != NULL){ - if ([oldAccount aa_isPrimaryAccount]) { + + if ([self accountIsPrimary:oldAccount]) { CFErrorRef removalError = NULL; ACLogDebug(@"Performing SOS circle credential removal for account %@: %@", oldAccount.identifier, oldAccount.username); if (!SOSCCLoggedOutOfAccount(&removalError)) { diff --git a/Modules/Security.iOS.modulemap b/Modules/Security.iOS.modulemap new file mode 100644 index 00000000..19cd51d0 --- /dev/null +++ b/Modules/Security.iOS.modulemap @@ -0,0 +1,20 @@ +framework module Security [extern_c] { + umbrella header "Security.h" + + export * + module * { + export * + } + + + explicit module CipherSuite { + header "CipherSuite.h" + export * + } + explicit module SecureTransport { + header "SecureTransport.h" + export * + } + +} + diff --git a/Modules/Security.macOS.modulemap b/Modules/Security.macOS.modulemap new file mode 100644 index 00000000..d7b5dd1c --- /dev/null +++ b/Modules/Security.macOS.modulemap @@ -0,0 +1,48 @@ +framework module Security [extern_c] { + umbrella header "Security.h" + header "SecurityFeatures.h" + + export * + module * { + export * + } + + + explicit module AuthorizationPlugin { + header "AuthorizationPlugin.h" + export * + } + explicit module AuthSession { + header "AuthSession.h" + export * + } + explicit module CodeSigning { + header "CodeSigning.h" + export * + } + explicit module eisl { + header "eisl.h" + export * + } + explicit module SecAsn1Coder { + header "SecAsn1Coder.h" + export * + } + explicit module SecAsn1Templates { + header "SecAsn1Templates.h" + export * + } + explicit module SecureDownload { + header "SecureDownload.h" + export * + } + explicit module SecRandom { + header "SecRandom.h" + export * + } + explicit module SecureTransport { + header "SecureTransport.h" + export * + } +} + diff --git a/OSX/Breadcrumb/SecBreadcrumb.c b/OSX/Breadcrumb/SecBreadcrumb.c index b0c3b56d..44b1ac55 100644 --- a/OSX/Breadcrumb/SecBreadcrumb.c +++ b/OSX/Breadcrumb/SecBreadcrumb.c @@ -17,7 +17,9 @@ static const int kKeySize = CCAES_KEY_SIZE_128; static const int kSaltSize = 20; static const int kIterations = 5000; static const CFIndex tagLen = 16; -static const uint8_t BCversion = 1; +static const CFIndex ivLen = 16; +static const uint8_t BCversion1 = 1; +static const uint8_t BCversion2 = 2; static const size_t paddingSize = 256; static const size_t maxSize = 1024; @@ -30,6 +32,7 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, const struct ccmode_ecb *ecb = ccaes_ecb_encrypt_mode(); const struct ccmode_gcm *gcm = ccaes_gcm_encrypt_mode(); const struct ccdigest_info *di = ccsha256_di(); + uint8_t iv[ivLen]; CFMutableDataRef key, npw; CFDataRef pw; @@ -43,7 +46,15 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, return false; CFDataSetLength(key, kKeySize + kSaltSize + 4); - CCRandomCopyBytes(kCCRandomDefault, CFDataGetMutableBytePtr(key), CFDataGetLength(key) - 4); + if (SecRandomCopyBytes(kSecRandomDefault, CFDataGetLength(key) - 4, CFDataGetMutableBytePtr(key)) != 0) { + CFReleaseNull(key); + return false; + } + if (SecRandomCopyBytes(kSecRandomDefault, ivLen, iv) != 0) { + CFReleaseNull(key); + return false; + } + uint32_t size = htonl(kIterations); memcpy(CFDataGetMutableBytePtr(key) + kKeySize + kSaltSize, &size, sizeof(size)); @@ -66,7 +77,7 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, } CFIndex paddedSize = passwordLength + paddingSize - (passwordLength % paddingSize); - const CFIndex outLength = 1 + 4 + paddedSize + tagLen; + const CFIndex outLength = 1 + ivLen + 4 + paddedSize + tagLen; npw = CFDataCreateMutable(NULL, outLength); if (npw == NULL) { @@ -77,10 +88,11 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, CFDataSetLength(npw, outLength); memset(CFDataGetMutableBytePtr(npw), 0, outLength); - CFDataGetMutableBytePtr(npw)[0] = BCversion; + CFDataGetMutableBytePtr(npw)[0] = BCversion2; + memcpy(CFDataGetMutableBytePtr(npw) + 1, iv, ivLen); size = htonl(passwordLength); - memcpy(CFDataGetMutableBytePtr(npw) + 1, &size, sizeof(size)); - memcpy(CFDataGetMutableBytePtr(npw) + 5, CFDataGetBytePtr(pw), passwordLength); + memcpy(CFDataGetMutableBytePtr(npw) + 1 + ivLen, &size, sizeof(size)); + memcpy(CFDataGetMutableBytePtr(npw) + 1 + ivLen + 4, CFDataGetBytePtr(pw), passwordLength); /* * Now create a GCM encrypted password using the random key @@ -88,8 +100,9 @@ SecBreadcrumbCreateFromPassword(CFStringRef inPassword, ccgcm_ctx_decl(gcm->size, ctx); ccgcm_init(gcm, ctx, kKeySize, CFDataGetMutableBytePtr(key)); + ccgcm_set_iv(gcm, ctx, ivLen, iv); ccgcm_gmac(gcm, ctx, 1, CFDataGetMutableBytePtr(npw)); - ccgcm_update(gcm, ctx, outLength - tagLen - 1, CFDataGetMutableBytePtr(npw) + 1, CFDataGetMutableBytePtr(npw) + 1); + ccgcm_update(gcm, ctx, outLength - tagLen - ivLen - 1, CFDataGetMutableBytePtr(npw) + 1 + ivLen, CFDataGetMutableBytePtr(npw) + 1 + ivLen); ccgcm_finalize(gcm, ctx, tagLen, CFDataGetMutableBytePtr(npw) + outLength - tagLen); ccgcm_ctx_clear(gcm->size, ctx); @@ -138,9 +151,9 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, CFErrorRef *outError) { const struct ccmode_ecb *ecb = ccaes_ecb_decrypt_mode(); - const struct ccmode_gcm *gcm = ccaes_gcm_decrypt_mode(); const struct ccdigest_info *di = ccsha256_di(); CFMutableDataRef gcmkey, oldpw; + CFIndex outLength; CFDataRef pw; uint32_t size; @@ -152,11 +165,16 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, return false; } - if (CFDataGetLength(inBreadcrumb) < 1 + 4 + paddingSize + tagLen) { - return false; - } - - if (CFDataGetBytePtr(inBreadcrumb)[0] != BCversion) { + if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { + if (CFDataGetLength(inBreadcrumb) < 1 + 4 + paddingSize + tagLen) + return false; + + outLength = CFDataGetLength(inBreadcrumb) - 1 - tagLen; + } else if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion2) { + if (CFDataGetLength(inBreadcrumb) < 1 + ivLen + 4 + paddingSize + tagLen) + return false; + outLength = CFDataGetLength(inBreadcrumb) - 1 - ivLen - tagLen; + } else { return false; } @@ -165,7 +183,6 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, return false; } - const CFIndex outLength = CFDataGetLength(inBreadcrumb) - 1 - tagLen; if ((outLength % 16) != 0 && outLength < 4) { CFReleaseNull(gcmkey); return false; @@ -177,7 +194,6 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, return false; } CFDataSetLength(oldpw, outLength); - /* * Create data for password @@ -220,23 +236,38 @@ SecBreadcrumbCopyPassword(CFStringRef inPassword, /* * GCM unwrap */ - + uint8_t tag[tagLen]; - ccgcm_ctx_decl(gcm->size, ctx); - - ccgcm_init(gcm, ctx, kKeySize, CFDataGetMutableBytePtr(gcmkey)); - ccgcm_gmac(gcm, ctx, 1, CFDataGetBytePtr(inBreadcrumb)); - ccgcm_update(gcm, ctx, outLength, CFDataGetBytePtr(inBreadcrumb) + 1, CFDataGetMutableBytePtr(oldpw)); - ccgcm_finalize(gcm, ctx, tagLen, tag); - ccgcm_ctx_clear(gcm->size, ctx); - - CFReleaseNull(gcmkey); - - if (memcmp(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, tagLen) != 0) { - CFReleaseNull(oldpw); - return false; + + if (CFDataGetBytePtr(inBreadcrumb)[0] == BCversion1) { + memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, tagLen); + + ccgcm_one_shot_legacy(ccaes_gcm_decrypt_mode(), kKeySize, CFDataGetMutableBytePtr(gcmkey), 0, NULL, 1, CFDataGetBytePtr(inBreadcrumb), + outLength, CFDataGetBytePtr(inBreadcrumb) + 1, CFDataGetMutableBytePtr(oldpw), tagLen, tag); + if (memcmp(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + outLength, tagLen) != 0) { + CFReleaseNull(oldpw); + return false; + } + + } else { + const uint8_t *iv = CFDataGetBytePtr(inBreadcrumb) + 1; + int res; + memcpy(tag, CFDataGetBytePtr(inBreadcrumb) + 1 + ivLen + outLength, tagLen); + + res = ccgcm_one_shot(ccaes_gcm_decrypt_mode(), kKeySize, CFDataGetMutableBytePtr(gcmkey), + ivLen, iv, + 1, CFDataGetBytePtr(inBreadcrumb), + outLength, CFDataGetBytePtr(inBreadcrumb) + 1 + ivLen, CFDataGetMutableBytePtr(oldpw), + tagLen, tag); + if (res) { + CFReleaseNull(oldpw); + return false; + } } + + CFReleaseNull(gcmkey); + memcpy(&size, CFDataGetMutableBytePtr(oldpw), sizeof(size)); size = ntohl(size); if (size > outLength - 4) { diff --git a/OSX/Breadcrumb/bc-10-knife-on-bread.c b/OSX/Breadcrumb/bc-10-knife-on-bread.m similarity index 53% rename from OSX/Breadcrumb/bc-10-knife-on-bread.c rename to OSX/Breadcrumb/bc-10-knife-on-bread.m index e3d4409b..638eb729 100644 --- a/OSX/Breadcrumb/bc-10-knife-on-bread.c +++ b/OSX/Breadcrumb/bc-10-knife-on-bread.m @@ -22,27 +22,19 @@ */ +#include #include #include #include "breadcrumb_regressions.h" -static void -print_hex(const char *label, CFDataRef data) -{ - CFIndex count, n; - printf("%s = ", label); - const uint8_t *ptr = CFDataGetBytePtr(data); - count = CFDataGetLength(data); - for (n = 0; n < count; n++) { - printf("%02x", ptr[n]); - } - printf("\n"); -} +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 6 +#define kTestCount 10 int bc_10_password(int argc, char *const *argv) { CFDataRef breadcrumb = NULL, encryptedKey = NULL; @@ -59,12 +51,9 @@ int bc_10_password(int argc, char *const *argv) ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); CFRelease(oldPassword); - - print_hex("encrypted key before", encryptedKey); - + CFDataRef newEncryptedKey; - printf("changing password from \"password\" to \"newpassword\"\n"); newEncryptedKey = SecBreadcrumbCreateNewEncryptedKey(password, @@ -73,9 +62,6 @@ int bc_10_password(int argc, char *const *argv) &error); ok(newEncryptedKey, "no new encrypted key"); - print_hex("encrypted key after", newEncryptedKey); - - ok(SecBreadcrumbCopyPassword(newpassword, breadcrumb, newEncryptedKey, &oldPassword, NULL), "unwrap failed"); ok(oldPassword && CFStringCompare(password, oldPassword, 0) == kCFCompareEqualTo, "not same password"); @@ -84,5 +70,35 @@ int bc_10_password(int argc, char *const *argv) CFRelease(oldPassword); CFRelease(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"); + + CFRelease(breadcrumb); + CFRelease(oldPassword); + CFRelease(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"); + + CFRelease(breadcrumb); + CFRelease(oldPassword); + CFRelease(newEncryptedKey); + return 0; } diff --git a/OSX/IDSKeychainSyncingProxy/com.apple.private.alloy.keychainsync.plist b/OSX/IDSKeychainSyncingProxy/com.apple.private.alloy.keychainsync.plist deleted file mode 100644 index f08f2617b1ce77c9f0708dda9741267278cb8c15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 458 zcma)$O-{ow6ojA4Ut4}^V8H^|u|a~U3l7kzEcmS|wL+pz6&d@Ln7XkQJFT*3#Z5Q> z+=T@f;1r|~mPmP<(LBvJng^q#bJNsfa{ zfw7ZgiOKL>TBBIjVN<;CrZ(zpBY8* - - - - com.apple.wifi.manager-access - - com.apple.private.ids.remoteurlconnection - - com.apple.private.ids.force-encryption-off - - com.apple.private.alloy.keychainsync - - com.apple.private.ids.messaging.high-priority - - com.apple.private.alloy.keychainsync - - com.apple.private.ids.messaging - - com.apple.private.alloy.keychainsync - - keychain-access-groups - - IMCore - apple - InternetAccounts - - application-identifier - com.apple.security.idskeychainsyncingproxy - - diff --git a/OSX/Keychain Circle Notification/KNAppDelegate.m b/OSX/Keychain Circle Notification/KNAppDelegate.m index 044bd17b..05160674 100644 --- a/OSX/Keychain Circle Notification/KNAppDelegate.m +++ b/OSX/Keychain Circle Notification/KNAppDelegate.m @@ -36,6 +36,8 @@ #include #include #include +#import "CoreCDP/CDPFollowUpController.h" +#import "CoreCDP/CDPFollowUpContext.h" static const char * const kLaunchLaterXPCName = "com.apple.security.Keychain-Circle-Notification-TICK"; static const NSString * const kKickedOutKey = @"KickedOut"; @@ -62,9 +64,11 @@ static NSUserNotificationCenter *appropriateNotificationCenter() AEDesc aeDesc; BOOL createdAEDesc = createAEDescWithAEActionAndAccountID((__bridge NSString *) kMMServiceIDKeychainSync, eventName, account, &aeDesc); if (createdAEDesc) { - LSLaunchURLSpec lsSpec = { + NSArray *prefPaneURL = [NSArray arrayWithObject: [NSURL fileURLWithPath:@"/System/Library/PreferencePanes/iCloudPref.prefPane"]]; + + LSLaunchURLSpec lsSpec = { .appURL = NULL, - .itemURLs = (__bridge CFArrayRef)([NSArray arrayWithObject: [NSURL fileURLWithPath:@"/System/Library/PreferencePanes/iCloudPref.prefPane"]]), + .itemURLs = (__bridge CFArrayRef)prefPaneURL, .passThruParams = &aeDesc, .launchFlags = kLSLaunchDefaults | kLSLaunchAsync, .asyncRefCon = NULL, @@ -313,7 +317,7 @@ bool isAppleInternal(void) // Remove reminders NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[kValidOnlyOutOfCircleKey] && note.userInfo[@"ApplicationReminder"]) { + if (note.userInfo[(NSString*) kValidOnlyOutOfCircleKey] && note.userInfo[@"ApplicationReminder"]) { NSLog(@"{ChangeCallback} Removing notification %@", note); [appropriateNotificationCenter() removeDeliveredNotification: note]; } @@ -333,7 +337,7 @@ bool isAppleInternal(void) NSLog(@"{ChangeCallback} me.circle.isInCircle"); NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[kValidOnlyOutOfCircleKey]) { + if (note.userInfo[(NSString*) kValidOnlyOutOfCircleKey]) { NSLog(@"Removing existing notification (%@) now that we are in circle", note); [appropriateNotificationCenter() removeDeliveredNotification: note]; } @@ -455,7 +459,7 @@ bool isAppleInternal(void) { NSUserNotificationCenter *noteCenter = appropriateNotificationCenter(); for (NSUserNotification *note in noteCenter.deliveredNotifications) { - if (note.userInfo[kKickedOutKey]) { + if (note.userInfo[(NSString*) kKickedOutKey]) { if (note.isPresented) { NSLog(@"Already posted&presented (removing): %@", note); [appropriateNotificationCenter() removeDeliveredNotification: note]; @@ -540,8 +544,8 @@ bool isAppleInternal(void) note.userInfo = @{ @"ApplicationReminder" : @1, kValidOnlyOutOfCircleKey: @1, - @"Activate" : (__bridge NSString *) kMMPropertyKeychainWADetailsAEAction, - }; + @"Activate" : (__bridge NSString *) kMMPropertyKeychainWADetailsAEAction, + }; NSLog(@"About to post #-/%lu (REMINDER): %@ (I=%@)", noteCenter.deliveredNotifications.count, note, [note.userInfo compactDescription]); [appropriateNotificationCenter() deliverNotification:note]; diff --git a/OSX/Keychain Circle Notification/KNPersistentState.h b/OSX/Keychain Circle Notification/KNPersistentState.h index 8c2f2a5a..d794dff4 100644 --- a/OSX/Keychain Circle Notification/KNPersistentState.h +++ b/OSX/Keychain Circle Notification/KNPersistentState.h @@ -23,8 +23,8 @@ #import -#include "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSPeerInfo.h" +#include +#include @interface KNPersistentState : NSObject +(instancetype)loadFromStorage; diff --git a/OSX/Keychain Circle Notification/Keychain Circle Notification-Info.plist b/OSX/Keychain Circle Notification/Keychain Circle Notification-Info.plist index 9955cea7..f689ae50 100644 --- a/OSX/Keychain Circle Notification/Keychain Circle Notification-Info.plist +++ b/OSX/Keychain Circle Notification/Keychain Circle Notification-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.security.apple.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/Keychain Circle Notification/NSDictionary+compactDescription.m b/OSX/Keychain Circle Notification/NSDictionary+compactDescription.m index 64350b77..15e3318a 100644 --- a/OSX/Keychain Circle Notification/NSDictionary+compactDescription.m +++ b/OSX/Keychain Circle Notification/NSDictionary+compactDescription.m @@ -47,7 +47,7 @@ { NSMutableArray *results = [NSMutableArray new]; for (NSString *k in self) { - if ([k isEqualToString:kSecValueData]) { + if ([k isEqualToString:(__bridge NSString*) kSecValueData]) { [results addObject:[NSString stringWithFormat:@"%@=", [k compactDescription]]]; continue; } diff --git a/OSX/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist b/OSX/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist index 0167ddd5..fd668fba 100644 --- a/OSX/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist +++ b/OSX/Keychain Circle Notification/com.apple.security.keychain-circle-notification.plist @@ -5,11 +5,13 @@ Label com.apple.security.keychain-circle-notification RunAtLoad - + KeepAlive - ProcessType - Background + EnablePressuredExit + + LimitLoadToSessionType + Aqua LaunchEvents com.apple.notifyd.matching diff --git a/OSX/Keychain Circle Notification/entitlments.plist b/OSX/Keychain Circle Notification/entitlments.plist index f1eb0a17..356b6481 100644 --- a/OSX/Keychain Circle Notification/entitlments.plist +++ b/OSX/Keychain Circle Notification/entitlments.plist @@ -2,6 +2,8 @@ + com.apple.accounts.appleaccount.fullaccess + com.apple.private.notificationcenter-system diff --git a/OSX/Keychain/KDAppDelegate.m b/OSX/Keychain/KDAppDelegate.m index 92431e81..b3fca93c 100644 --- a/OSX/Keychain/KDAppDelegate.m +++ b/OSX/Keychain/KDAppDelegate.m @@ -43,7 +43,9 @@ self.itemDataSource = [[KDSecItems alloc] init]; self.itemTable.dataSource = self.itemDataSource; - + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" int notificationToken; uint32_t rc = notify_register_dispatch(kSecServerKeychainChangedNotification, ¬ificationToken, dispatch_get_main_queue(), ^(int token __unused) { NSLog(@"Received %s", kSecServerKeychainChangedNotification); @@ -51,26 +53,32 @@ [self.itemTable reloadData]; }); NSAssert(rc == 0, @"Can't register for %s", kSecServerKeychainChangedNotification); +#pragma clang diagnostic pop self.circle = [KDSecCircle new]; + + __weak typeof(self) weakSelf = self; [self.circle addChangeCallback:^{ - self.circleStatusCell.stringValue = self.circle.status; - - [self setCheckbox]; - - self.peerCountCell.objectValue = @(self.circle.peers.count); - NSString *peerNames = [[self.circle.peers mapWithBlock:^id(id obj) { - return ((KDCirclePeer*)obj).name; - }] componentsJoinedByString:@"\n"]; - [self.peerTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [self.peerTextList.textStorage length]) withString:peerNames]; - - self.applicantCountCell.objectValue = @(self.circle.applicants.count); - NSString *applicantNames = [[self.circle.applicants mapWithBlock:^id(id obj) { - return ((KDCirclePeer*)obj).name; - }] componentsJoinedByString:@"\n"]; - [self.applicantTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [self.applicantTextList.textStorage length]) withString:applicantNames]; - - [self.syncSpinner stopAnimation:nil]; + __strong typeof(self) strongSelf = weakSelf; + if(strongSelf) { + strongSelf.circleStatusCell.stringValue = strongSelf.circle.status; + + [strongSelf setCheckbox]; + + strongSelf.peerCountCell.objectValue = @(strongSelf.circle.peers.count); + NSString *peerNames = [[strongSelf.circle.peers mapWithBlock:^id(id obj) { + return ((KDCirclePeer*)obj).name; + }] componentsJoinedByString:@"\n"]; + [strongSelf.peerTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [strongSelf.peerTextList.textStorage length]) withString:peerNames]; + + strongSelf.applicantCountCell.objectValue = @(strongSelf.circle.applicants.count); + NSString *applicantNames = [[strongSelf.circle.applicants mapWithBlock:^id(id obj) { + return ((KDCirclePeer*)obj).name; + }] componentsJoinedByString:@"\n"]; + [strongSelf.applicantTextList.textStorage replaceCharactersInRange:NSMakeRange(0, [strongSelf.applicantTextList.textStorage length]) withString:applicantNames]; + + [strongSelf.syncSpinner stopAnimation:nil]; + } }]; } diff --git a/OSX/Keychain/KDCirclePeer.m b/OSX/Keychain/KDCirclePeer.m index a813b41c..91f8864e 100644 --- a/OSX/Keychain/KDCirclePeer.m +++ b/OSX/Keychain/KDCirclePeer.m @@ -23,8 +23,8 @@ #import "KDCirclePeer.h" -#include "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSPeerInfo.h" +#include +#include @interface KDCirclePeer () diff --git a/OSX/Keychain/KDSecCircle.h b/OSX/Keychain/KDSecCircle.h index 214c77ab..42f70275 100644 --- a/OSX/Keychain/KDSecCircle.h +++ b/OSX/Keychain/KDSecCircle.h @@ -22,7 +22,7 @@ */ -#import "SecureObjectSync/SOSCloudCircle.h" +#import #import @interface KDSecCircle : NSObject diff --git a/OSX/Keychain/KDSecCircle.m b/OSX/Keychain/KDSecCircle.m index 31cbc174..14ddc7d2 100644 --- a/OSX/Keychain/KDSecCircle.m +++ b/OSX/Keychain/KDSecCircle.m @@ -26,10 +26,13 @@ #import "KDCirclePeer.h" #include #include -#import "SecureObjectSync/SOSCloudCircle.h" -#include "SecureObjectSync/SOSPeerInfo.h" + +#import +#import + #import -#include "../utilities/utilities/debugging.h" + +#include @interface KDSecCircle () @property (retain) NSMutableArray *callbacks; @@ -129,6 +132,10 @@ typedef void (^applicantBlock)(id applicant); }); } +// Tell clang that these bools are okay, even if NSAssert doesn't use them +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" + -(void)acceptApplicantId:(NSString*)applicantId { [self forApplicantId:applicantId run:^void(id applicant) { @@ -147,6 +154,8 @@ typedef void (^applicantBlock)(id applicant); }]; } +#pragma clang diagnostic pop + -(id)init { self = [super init]; diff --git a/OSX/Keychain/Keychain-Info.plist b/OSX/Keychain/Keychain-Info.plist index 36213f65..70ad5526 100644 --- a/OSX/Keychain/Keychain-Info.plist +++ b/OSX/Keychain/Keychain-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile Icon.icns CFBundleIdentifier - com.apple.security.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/Modules b/OSX/Modules new file mode 120000 index 00000000..287aeb42 --- /dev/null +++ b/OSX/Modules @@ -0,0 +1 @@ +./Modules \ No newline at end of file diff --git a/OSX/OSX.xcodeproj/project.pbxproj b/OSX/OSX.xcodeproj/project.pbxproj index 2bb44ff5..482c5946 100644 --- a/OSX/OSX.xcodeproj/project.pbxproj +++ b/OSX/OSX.xcodeproj/project.pbxproj @@ -7,29 +7,6 @@ objects = { /* Begin PBXAggregateTarget section */ - 0C6C642915D5ADB500BC68CD /* Security_kexts */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 0C6C642A15D5ADB500BC68CD /* Build configuration list for PBXAggregateTarget "Security_kexts" */; - buildPhases = ( - ); - dependencies = ( - ); - name = Security_kexts; - productName = Security_kexts; - }; - 182BB598146FE295000BF1F3 /* World */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */; - buildPhases = ( - 18F2360315CB30EC00060520 /* ShellScript */, - ); - dependencies = ( - 186F779914E5A06500434E1F /* PBXTargetDependency */, - 186F779B14E5A06800434E1F /* PBXTargetDependency */, - ); - name = World; - productName = SecurityFramework; - }; 186F778814E59FB200434E1F /* Security_frameworks */ = { isa = PBXAggregateTarget; buildConfigurationList = 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */; @@ -54,18 +31,17 @@ 3705CADE1A8971DF00402F75 /* PBXTargetDependency */, 37AB39401A44A95500B56E04 /* PBXTargetDependency */, 37A7CEDA197DBA8700926CE8 /* PBXTargetDependency */, - 722CF218175D602F00BCE0A5 /* PBXTargetDependency */, - 521470291697842500DF0DB3 /* PBXTargetDependency */, - CDEB2BD21A8151CD00B0E23A /* PBXTargetDependency */, 18F235FF15CA100300060520 /* PBXTargetDependency */, - 186F779114E5A00F00434E1F /* PBXTargetDependency */, BE48AE291ADF204E000836C1 /* PBXTargetDependency */, + 186F779114E5A00F00434E1F /* PBXTargetDependency */, 0CCEBDBA16C303D8001BD7F6 /* PBXTargetDependency */, 0CFC55E315DDB86500BEC89E /* PBXTargetDependency */, C2432A2515C726B50096DB5B /* PBXTargetDependency */, 4CB23B90169F59D8003A0131 /* PBXTargetDependency */, EBB9FFE01682E71F00FF9774 /* PBXTargetDependency */, F94E7A971ACC8CC200F23132 /* PBXTargetDependency */, + EBB6970E1BE2095F00715F16 /* PBXTargetDependency */, + D466FA771CA0C2A500433142 /* PBXTargetDependency */, ); name = Security_executables; productName = Other; @@ -97,14 +73,13 @@ /* Begin PBXBuildFile section */ 0C03D62B17D93EED0087643B /* SecDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C03D60317D93E810087643B /* SecDH.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0C0C887D1CCED19E00617D1B /* si-82-sectrust-ct-data in Resources */ = {isa = PBXBuildFile; fileRef = 0C0C887C1CCED19E00617D1B /* si-82-sectrust-ct-data */; }; 0C10987616CAAE8200803B8F /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; - 0C4EAE4C1766864F00773425 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; - 0C4EAE761766875E00773425 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C4EAE721766865000773425 /* libsecdRegressions.a */; }; 0C4F055E15C9E51A00F9DFD5 /* sslTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */; }; 0C6C633015D19FF500BC68CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - 0C6D0065177B54CB0095D167 /* com.apple.securityd in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0C6D0064177B54C60095D167 /* com.apple.securityd */; }; + 0C869B6A1C865E62006A2873 /* CoreCDP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C869B691C865E62006A2873 /* CoreCDP.framework */; }; 0CAA7AB516C9A72A00A32C6D /* libsecurity_keychain_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */; }; 0CC2CB101B6A04D80074B0F2 /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC2CB0F1B6A04D80074B0F2 /* libDiagnosticMessagesClient.dylib */; }; 0CC3351C16C1ED8000399E53 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; @@ -172,8 +147,6 @@ 182BB5B8146FF0A2000BF1F3 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B7146FF0A1000BF1F3 /* libobjc.dylib */; }; 182BB5BA146FF0BF000BF1F3 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; 182BB5BB146FF62F000BF1F3 /* libsecurity_comcryption.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1879B676146DE75E007E536C /* libsecurity_comcryption.a */; }; - 1831329B14EB2C6D00F0BCAC /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; - 1831329C14EB2C6D00F0BCAC /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; 1844605F146DE93E00B12992 /* csp_capabilities.mdsinfo in Resources */ = {isa = PBXBuildFile; fileRef = 1844605B146DE93E00B12992 /* csp_capabilities.mdsinfo */; }; 18446060146DE93E00B12992 /* csp_capabilities_common.mds in Resources */ = {isa = PBXBuildFile; fileRef = 1844605C146DE93E00B12992 /* csp_capabilities_common.mds */; }; @@ -375,6 +348,8 @@ 18FE688B1471A46700A2CBE3 /* SecureTransportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB372146F13BB000BF1F3 /* SecureTransportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; 18FE688C1471A46700A2CBE3 /* TrustSettingsSchema.h in Headers */ = {isa = PBXBuildFile; fileRef = 182BB1C8146EAD5D000BF1F3 /* TrustSettingsSchema.h */; settings = {ATTRIBUTES = (Private, ); }; }; 18FE688D1471A46700A2CBE3 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 1844609E146DFCB700B12992 /* X509Templates.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1FDA9ABC1C4489280083929D /* SecTranslocate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FDA9ABB1C4489280083929D /* SecTranslocate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1FDA9ABD1C448DFC0083929D /* libsecurity_translocate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F6FC6001C3D9D90001C758F /* libsecurity_translocate.a */; }; 3705CAD91A896E0600402F75 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 3705CACD1A896DA800402F75 /* main.c */; }; 3705CADA1A896E0F00402F75 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; 371AB2F21A04052E00A08CF2 /* teamid.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = 371AB2CA1A04050700A08CF2 /* teamid.sh */; }; @@ -389,7 +364,6 @@ 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; 431B737F1B27762C00EB0360 /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 431B73571B27762300EB0360 /* CloudServices.framework */; }; 431B73C11B2777A200EB0360 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 432800831B4CE730002E8525 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; 432800841B4CE731002E8525 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; 4328FE9B1B4CDBA5002E8525 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; 4328FED11B4CDC11002E8525 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; @@ -398,11 +372,8 @@ 4381B9A91B28C6B2002BBC79 /* CloudServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 431B73571B27762300EB0360 /* CloudServices.framework */; }; 4381B9AA1B28E09F002BBC79 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; 43A599161B0CFCAB00D14A7B /* CloudKeychain.strings in CopyFiles */ = {isa = PBXBuildFile; fileRef = 43A598591B0CF2AB00D14A7B /* CloudKeychain.strings */; }; - 43C3B0D41AFD569600786702 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; 43C3B0D51AFD56B700786702 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; 43C3B2681AFD5B4800786702 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - 43C3B2C61AFD5BBB00786702 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; - 43C3B3311AFD5E1100786702 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; 43C3B35A1AFD5E1800786702 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; 4469FC291AA0A5AF0021AA26 /* libctkclient_test.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FC001AA0A56F0021AA26 /* libctkclient_test.a */; }; 44A655A71AA4B4F30059D185 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FC011AA0A56F0021AA26 /* libctkclient.a */; }; @@ -415,6 +386,7 @@ 44D78BBA1A0A616200B63C6C /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 44D78B8F1A0A611C00B63C6C /* libaks_acl.a */; }; 44D78BBB1A0A617700B63C6C /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; 44F7912019FFED88008B8147 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; + 486326331CAA0C6500A466D9 /* com.apple.securityd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 486326321CAA0C6500A466D9 /* com.apple.securityd.plist */; }; 48FDA8771AF98A3600A9366F /* SOSCloudCircleInternal.h in Copy SecureObjectSync Headers */ = {isa = PBXBuildFile; fileRef = 48FDA84D1AF989F600A9366F /* SOSCloudCircleInternal.h */; }; 4A5C1790161A9DFB00ABF784 /* authd_private.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 18F2351A15C9FA3C00060520 /* authd_private.h */; }; 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; @@ -462,24 +434,17 @@ 4CE7EAA31AEAF5230067F5BD /* SecItemBackup.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CE7EA7D1AEAF50F0067F5BD /* SecItemBackup.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; 5208C0D716A0C96F0062DDC5 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; - 5214701216977CB800DF0DB3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5214701016977CB800DF0DB3 /* InfoPlist.strings */; }; - 5214701D16977D9500DF0DB3 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - 5214701E16977DA700DF0DB3 /* libCloudKeychainProxy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */; }; - 521470261697800500DF0DB3 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */; }; 5241C60D16DC1BA100DB5C6F /* libSecOtrOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */; }; 5244926A1AFD6CB70043695A /* der_plist.h in Headers */ = {isa = PBXBuildFile; fileRef = 524492691AFD6CB70043695A /* der_plist.h */; settings = {ATTRIBUTES = (Private, ); }; }; 52669053169D181900ED8231 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; - 529E948C169E29450000AC9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; 529E948D169E29470000AC9B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; 52AEA489153C778C005AFC59 /* tsaSupportPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */; }; 52B5A9C21519330300664F11 /* tsaSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5A9C01519330300664F11 /* tsaSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; 52B5A9C31519330300664F11 /* tsaTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B5A9C11519330300664F11 /* tsaTemplates.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 52C3D236169B56860091D9D3 /* ckdmain.m in Sources */ = {isa = PBXBuildFile; fileRef = 52C3D235169B56860091D9D3 /* ckdmain.m */; }; 52CD052316A0E24900218387 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF42BB515A3947F00ACACE1 /* Security.framework */; }; 52F8DDFA1AF2E56700A2C271 /* SOSViews.h in Copy SecureObjectSync Headers */ = {isa = PBXBuildFile; fileRef = 52F8DDF91AF2E56600A2C271 /* SOSViews.h */; }; 52F8DE211AF2E57300A2C271 /* SOSBackupSliceKeyBag.h in Copy SecureObjectSync Headers */ = {isa = PBXBuildFile; fileRef = 52F8DE201AF2E57300A2C271 /* SOSBackupSliceKeyBag.h */; }; - 52F8DE251AF2E58B00A2C271 /* SOSForerunnerSession.h in Copy SecureObjectSync Headers */ = {isa = PBXBuildFile; fileRef = 52F8DE231AF2E58B00A2C271 /* SOSForerunnerSession.h */; }; 52F8DE4C1AF2EB6600A2C271 /* SOSTypes.h in Copy SecureObjectSync Headers */ = {isa = PBXBuildFile; fileRef = 52F8DE4B1AF2EB6600A2C271 /* SOSTypes.h */; }; 532847791785076B009118DC /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5328475117850741009118DC /* Localizable.strings */; }; 5E605AFC1AB859B70049FA14 /* libcoreauthd_test_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E605AFB1AB859B70049FA14 /* libcoreauthd_test_client.a */; }; @@ -497,20 +462,20 @@ 5EF7C2501B00EA7A00E5E99C /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E7AF4721ACD64AC00005140 /* libACM.a */; }; 5EF7C2511B00EAF100E5E99C /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; 5EF7C2521B00EB0A00E5E99C /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; - 5EFB69BD1B0CBE030095A36E /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F1214CF43C000B05E7F /* libDER.a */; }; 5EFB69C31B0CC16F0095A36E /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; - 72756C31175D48C100F52070 /* cloud_keychain_diagnose.c in Sources */ = {isa = PBXBuildFile; fileRef = 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */; }; + 6C721DB11D3D18D700888AE1 /* login.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C721DB01D3D18D700888AE1 /* login.framework */; }; + 6C721DD61D3D18EC00888AE1 /* login.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C721DB01D3D18D700888AE1 /* login.framework */; }; 7A21DAE619B7F27C0007D37F /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; + 8E64DB4A1C17C26F0076C9DF /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; + 8E64DB4B1C17C2830076C9DF /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */; }; AC5688BC18B4396D00F0526C /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = AC5688BA18B4396D00F0526C /* SecCMS.h */; settings = {ATTRIBUTES = (Private, ); }; }; ACB6171918B5231800EBEDD7 /* libsecurity_smime_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ACB6171818B5231800EBEDD7 /* libsecurity_smime_regressions.a */; }; - BE2C05151AD893DF00D6A139 /* libsecurity_codesigning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F2360015CAF41100060520 /* libsecurity_codesigning.a */; }; BE48AE031ADF1DF4000836C1 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 18270EF314CF333400B05E7F /* server.c */; }; BE48AE051ADF1DF4000836C1 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E7AF4721ACD64AC00005140 /* libACM.a */; }; BE48AE061ADF1DF4000836C1 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; BE48AE071ADF1DF4000836C1 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; BE48AE081ADF1DF4000836C1 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; - BE48AE091ADF1DF4000836C1 /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; BE48AE0A1ADF1DF4000836C1 /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18F235F715CA0D9D00060520 /* libsecurity_utilities.a */; }; BE48AE0B1ADF1DF4000836C1 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; BE48AE0C1ADF1DF4000836C1 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 44D78B8F1A0A611C00B63C6C /* libaks_acl.a */; }; @@ -520,74 +485,128 @@ BE48AE101ADF1DF4000836C1 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; BE48AE111ADF1DF4000836C1 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; BE48AE121ADF1DF4000836C1 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; - BE48AE131ADF1DF4000836C1 /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; - BE48AE141ADF1DF4000836C1 /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; BE48AE151ADF1DF4000836C1 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FC011AA0A56F0021AA26 /* libctkclient.a */; }; - BE48AE161ADF1DF4000836C1 /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; BE48AE171ADF1DF4000836C1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; BE48AE181ADF1DF4000836C1 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFB14CF427800B05E7F /* CFNetwork.framework */; }; BE48AE251ADF1FD3000836C1 /* com.apple.trustd.agent.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = BE48AE241ADF1FD3000836C1 /* com.apple.trustd.agent.plist */; }; BE48AE271ADF2016000836C1 /* com.apple.trustd.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = BE48AE261ADF2011000836C1 /* com.apple.trustd.plist */; }; - BE60737A1ADC9E89007FECC1 /* libACM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E7AF4721ACD64AC00005140 /* libACM.a */; }; - BE6073A51ADC9F1C007FECC1 /* libctkclient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4469FC011AA0A56F0021AA26 /* libctkclient.a */; }; - BE6073A61ADC9F7A007FECC1 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 395E7CED16C64EA500CD82A4 /* SystemConfiguration.framework */; }; - BE6073A71ADC9F88007FECC1 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFB14CF427800B05E7F /* CFNetwork.framework */; }; - BE607DC61AD8673C001B7778 /* libcoreauthd_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */; }; - BE607DC71AD86746001B7778 /* libaks_acl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 44D78B8F1A0A611C00B63C6C /* libaks_acl.a */; }; - BE607DC81AD86859001B7778 /* libASN1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329914EB2C6D00F0BCAC /* libASN1.a */; }; - BE607DC91AD8685B001B7778 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; BE8C5F0A16F7CE450074CF86 /* framework.sb in Resources */ = {isa = PBXBuildFile; fileRef = BE8C5F0916F7CE450074CF86 /* framework.sb */; }; BE8D22C01ABB74C3009A4E18 /* libSecTrustOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8D22BC1ABB747B009A4E18 /* libSecTrustOSX.a */; }; - BE94B7941AD83AF700A7216D /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5AD146FEF43000BF1F3 /* libsqlite3.dylib */; }; - BE94B7951AD83AF700A7216D /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB5B9146FF0BE000BF1F3 /* libbsm.dylib */; }; - BE94B7971AD83AF700A7216D /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */; }; - BE94B7981AD83AF700A7216D /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - BE94B7CD1AD83B9900A7216D /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 18270EF314CF333400B05E7F /* server.c */; }; - BE94B7D01AD83D0D00A7216D /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; - BE94B7D21AD83D0D00A7216D /* libSecTrustOSX.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BE8D22BC1ABB747B009A4E18 /* libSecTrustOSX.a */; }; - BE94B7D41AD83D0D00A7216D /* libsecurity.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18D4053B14CE2C1600A2BE4E /* libsecurity.a */; }; - BE94B7D51AD83D2B00A7216D /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - BE94B7D81AD83D6A00A7216D /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; - BE94B7DC1AD8425E00A7216D /* com.apple.trustd.asl in Copy asl module */ = {isa = PBXBuildFile; fileRef = BE94B7DA1AD8424700A7216D /* com.apple.trustd.asl */; }; - BE94B7DD1AD8426500A7216D /* com.apple.trustd.sb in Copy sandbox profile */ = {isa = PBXBuildFile; fileRef = BE94B7DB1AD8424700A7216D /* com.apple.trustd.sb */; }; - BE94B7F01AD8457200A7216D /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; - BE9703F71AD865540041D253 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; BEC3A76816F79497003E5634 /* SecTaskPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = BEC3A76716F79497003E5634 /* SecTaskPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BEFB63691B6834AB0052149A /* AppWorkaround.plist in Resources */ = {isa = PBXBuildFile; fileRef = BEFB63681B6834AB0052149A /* AppWorkaround.plist */; }; C2407A1B1B30BBF30067E6AE /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; C288A0891505796F00E773B7 /* libOpenScriptingUtil.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */; settings = {ATTRIBUTES = (Weak, ); }; }; - CD0637581A840B5B00C81E74 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; - CD0CB49E1A818A0D00C058A4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18FE67EA1471A3AA00A2CBE3 /* Security.framework */; }; - CD19A65D1A8065DC00F9C276 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; - CD19A65F1A8065E900F9C276 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; - CD19A6611A8069D100F9C276 /* libIDSKeychainSyncingProxy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CD63AD0C1A8061FA001B5671 /* libIDSKeychainSyncingProxy.a */; }; - CD276BE41A83F204003226BC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CD276BE21A83F204003226BC /* InfoPlist.strings */; }; - CD2E85F61A81793B00F8B00A /* IDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD7446D8195A1CFE00FB01C0 /* IDS.framework */; }; - CD63AD161A8064C2001B5671 /* idksmain.m in Sources */ = {isa = PBXBuildFile; fileRef = CD63AD151A8064C2001B5671 /* idksmain.m */; }; - CD7446D9195A1CFE00FB01C0 /* IDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD7446D8195A1CFE00FB01C0 /* IDS.framework */; }; CD8B5A9D1B618ED9004D4AEF /* SOSPeerInfoPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = CD8B5A9C1B618ED9004D4AEF /* SOSPeerInfoPriv.h */; }; - CDAE4B9A1A86F6F20000AA84 /* idskeychainsyncingproxy.entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = CD63AD191A8064DE001B5671 /* idskeychainsyncingproxy.entitlements.plist */; }; - CDAE4BC21A86F6FF0000AA84 /* cloudkeychain.entitlements.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */; }; - CDB22CE31A9D2EA70043E348 /* IDSKeychainSyncingProxy-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = CD63AD181A8064DE001B5671 /* IDSKeychainSyncingProxy-Info.plist */; }; CDDE9D1E1729E2E60013B0E8 /* SecPasswordGenerate.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */; settings = {ATTRIBUTES = (Private, ); }; }; - CDE08DD41A85E92200B5C261 /* com.apple.security.idskeychainsyncingproxy.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = CD50D6D21A841C0E00C35E74 /* com.apple.security.idskeychainsyncingproxy.plist */; }; - CDF91EC91AAE022600E88CF7 /* com.apple.private.alloy.keychainsync.plist in Resources */ = {isa = PBXBuildFile; fileRef = CDF91EC81AAE022600E88CF7 /* com.apple.private.alloy.keychainsync.plist */; }; - CDF91EF51AAE028F00E88CF7 /* com.apple.private.alloy.keychainsync.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = CDF91EC81AAE022600E88CF7 /* com.apple.private.alloy.keychainsync.plist */; }; D41685841B3A288F001FB54E /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = D41685831B3A288F001FB54E /* oids.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D42817D01C6000E1007F95D8 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; + D42CFD771BFD3379008C8737 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1831329A14EB2C6D00F0BCAC /* libDER.a */; }; + D42FA82B1C9B8D3D003E46A7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D42FA82A1C9B8D3D003E46A7 /* main.m */; }; + D42FA8451C9B8FDE003E46A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42FA8441C9B8FDE003E46A7 /* Foundation.framework */; }; + D42FA8461C9B9000003E46A7 /* libsecurity_cms_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */; }; + D42FA8471C9B9000003E46A7 /* libsecurity_keychain_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */; }; + D42FA8481C9B9000003E46A7 /* libsecurity_smime_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ACB6171818B5231800EBEDD7 /* libsecurity_smime_regressions.a */; }; + D42FA8491C9B9000003E46A7 /* libsecurity_ssl_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0C6D77CF15C8B66000BB4405 /* libsecurity_ssl_regressions.a */; }; + D42FA84A1C9B900A003E46A7 /* libSharedRegressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D40772181C9B52210016AA66 /* libSharedRegressions.a */; }; + D42FA84B1C9B9013003E46A7 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + D42FA84D1C9B901E003E46A7 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42FA84C1C9B901E003E46A7 /* IOKit.framework */; }; + D42FA84E1C9B903F003E46A7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; + D42FA8501C9B9047003E46A7 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42FA84F1C9B9047003E46A7 /* CoreFoundation.framework */; }; + D42FA87D1C9B9186003E46A7 /* si-82-sectrust-ct-logs.plist in Resources */ = {isa = PBXBuildFile; fileRef = D42FA87C1C9B9186003E46A7 /* si-82-sectrust-ct-logs.plist */; }; + D42FA8E91C9B95EC003E46A7 /* libregressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC3356016C1EF5D00399E53 /* libregressions.a */; }; + D42FA8EA1C9BAA44003E46A7 /* bc-10-knife-on-bread.m in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.m */; }; + D42FA8EB1C9BAAD5003E46A7 /* libaks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18752C1D16F2837A004E2799 /* libaks.a */; }; + D447C0C21D2C9BAB0082FC1D /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D447C0C11D2C9BAB0082FC1D /* libDiagnosticMessagesClient.dylib */; }; + D447C0E71D2C9C390082FC1D /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D447C0C11D2C9BAB0082FC1D /* libDiagnosticMessagesClient.dylib */; }; + D45FC3E11C9E068700509CDA /* libsecurityd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270C7D14CE573D00B05E7F /* libsecurityd.a */; }; + D45FC3E41C9E06B500509CDA /* libSecureObjectSync.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */; }; + D467D0EA1C9DF27100C9DE3E /* libsecipc_client.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F6014CF655B00B05E7F /* libsecipc_client.a */; }; + D47F51221C3B80DF00A7CEFE /* SecCFAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = D47F51211C3B80DE00A7CEFE /* SecCFAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4CBC1451BE981F600C5795E /* libsecurity_cms_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */; }; + D4D886C41CEBDBEB00DC7583 /* ssl-policy-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D886C31CEBDBEB00DC7583 /* ssl-policy-certs */; }; + D4D886F31CED01F800DC7583 /* nist-certs in Resources */ = {isa = PBXBuildFile; fileRef = D4D886F21CED01F800DC7583 /* nist-certs */; }; + D4D886FE1CED07B400DC7583 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = D4D886FA1CED07B400DC7583 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */; }; + D4D886FF1CED07B400DC7583 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = D4D886FB1CED07B400DC7583 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */; }; + D4D887001CED07B400DC7583 /* Invalid-webmail.jaring.my.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = D4D886FC1CED07B400DC7583 /* Invalid-webmail.jaring.my.crt */; }; + D4D887011CED07B400DC7583 /* Invalid-www.cybersecurity.my.crt in Copy DigicertMalaysia Resources */ = {isa = PBXBuildFile; fileRef = D4D886FD1CED07B400DC7583 /* Invalid-www.cybersecurity.my.crt */; }; + D4D8871B1CED081700DC7583 /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887041CED081500DC7583 /* diginotar-public-ca-2025-Cert.crt */; }; + D4D8871C1CED081700DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887051CED081500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + D4D8871D1CED081700DC7583 /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887061CED081500DC7583 /* diginotar-services-diginotar-root-Cert.crt */; }; + D4D8871E1CED081700DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887071CED081500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + D4D8871F1CED081700DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887081CED081500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + D4D887201CED081700DC7583 /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887091CED081500DC7583 /* diginotar.root.ca-entrust-secure-server-Cert.crt */; }; + D4D887231CED081700DC7583 /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D8870C1CED081600DC7583 /* Invalid-asterisk.google.com.crt */; }; + D4D887241CED081700DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D8870D1CED081600DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + D4D887251CED081700DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D8870E1CED081600DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; + D4D887261CED081700DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D8870F1CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; + D4D887271CED081700DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887101CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; + D4D887281CED081700DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887111CED081600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + D4D887291CED081700DC7583 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887121CED081600DC7583 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + D4D8872A1CED081700DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887131CED081600DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + D4D8872B1CED081700DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887141CED081600DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + D4D8872C1CED081700DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887151CED081600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + D4D8872D1CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887161CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; + D4D8872F1CED081700DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887181CED081700DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; + D4D887301CED081700DC7583 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */ = {isa = PBXBuildFile; fileRef = D4D887191CED081700DC7583 /* staatdernederlandenoverheidca-Cert.crt */; }; + D4D887321CED093200DC7583 /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D8870C1CED081600DC7583 /* Invalid-asterisk.google.com.crt */; }; + D4D887331CED093A00DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887111CED081600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + D4D887341CED094200DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887131CED081600DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + D4D887351CED094C00DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887141CED081600DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + D4D887361CED095600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887151CED081600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + D4D887371CED098500DC7583 /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887041CED081500DC7583 /* diginotar-public-ca-2025-Cert.crt */; }; + D4D887381CED098500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887051CED081500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + D4D887391CED098500DC7583 /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887061CED081500DC7583 /* diginotar-services-diginotar-root-Cert.crt */; }; + D4D8873A1CED098500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887071CED081500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + D4D8873B1CED098500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887081CED081500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + D4D8873C1CED099F00DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D8870D1CED081600DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + D4D8873D1CED099F00DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D8870E1CED081600DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */; }; + D4D8873E1CED099F00DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D8870F1CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt */; }; + D4D8873F1CED099F00DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887101CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */; }; + D4D887401CED09B300DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887181CED081700DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt */; }; + D4D887411CED09B300DC7583 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887191CED081700DC7583 /* staatdernederlandenoverheidca-Cert.crt */; }; + D4D887421CED09BD00DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887161CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */; }; + D4D887431CED09C500DC7583 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */ = {isa = PBXBuildFile; fileRef = D4D887121CED081600DC7583 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + D4D887441CED09DA00DC7583 /* Expectations.plist in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D8870B1CED081500DC7583 /* Expectations.plist */; }; + D4D887451CED09F600DC7583 /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887031CED081500DC7583 /* DigiNotar_Root_CA_G2-RootCertificate.crt */; }; + D4D887461CED09F600DC7583 /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887041CED081500DC7583 /* diginotar-public-ca-2025-Cert.crt */; }; + D4D887471CED09F600DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887051CED081500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt */; }; + D4D887481CED09F600DC7583 /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887061CED081500DC7583 /* diginotar-services-diginotar-root-Cert.crt */; }; + D4D887491CED09F600DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887071CED081500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt */; }; + D4D8874A1CED09F600DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887081CED081500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */; }; + D4D8874B1CED09F600DC7583 /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D8870A1CED081500DC7583 /* DigiNotarCA2007RootCertificate.crt */; }; + D4D8874C1CED09FF00DC7583 /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D8870C1CED081600DC7583 /* Invalid-asterisk.google.com.crt */; }; + D4D8874D1CED0A0600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887111CED081600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */; }; + D4D8874E1CED0A0F00DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887131CED081600DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */; }; + D4D8874F1CED0A2A00DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887141CED081600DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt */; }; + D4D887501CED0A3400DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887151CED081600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */; }; + D4D887511CED0A4400DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D8870D1CED081600DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */; }; + D4D887521CED0A4B00DC7583 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */ = {isa = PBXBuildFile; fileRef = D4D887121CED081600DC7583 /* Invalid-webmail.portofamsterdam.nl.crt */; }; + D4D9B9FE1C7E5CCA008785EB /* SecServerEncryptionSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = D4D9B9FD1C7E5CCA008785EB /* SecServerEncryptionSupport.h */; settings = {ATTRIBUTES = (Private, ); }; }; D4DDD3D01BE3EC0300E8AE2D /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4DDD3A71BE3EB4200E8AE2D /* libDiagnosticMessagesClient.dylib */; }; + D4DDD9671CA2F2A700AA03AE /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4DDD9661CA2F2A700AA03AE /* libbsm.dylib */; }; + D4DDD9961CA320FE00AA03AE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; + D4DDD9971CA3216C00AA03AE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; + D4EC94D61CEA48000083E753 /* si-20-sectrust-policies-data in Resources */ = {isa = PBXBuildFile; fileRef = D4EC94D51CEA48000083E753 /* si-20-sectrust-policies-data */; }; + DC247FB51CBF1C2500527D67 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F1214CF43C000B05E7F /* libDER.a */; }; + DC247FD81CBF1C3F00527D67 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270F1214CF43C000B05E7F /* libDER.a */; }; + DC311CC81CCEC82E00E14E8D /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C12894015FFECF3008CE3E3 /* libutilities.a */; }; + DC7EFBAB1CBC46A7005F9624 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC7EFBAA1CBC46A7005F9624 /* SecurityFoundation.framework */; }; + DC7EFC0E1CBC7567005F9624 /* SecurityFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC7EFBAA1CBC46A7005F9624 /* SecurityFoundation.framework */; }; + E74583F51BF66506001B54A4 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18270EFD14CF429600B05E7F /* IOKit.framework */; }; E76079D61951FDAF00F69731 /* liblogging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E76079D51951FDA800F69731 /* liblogging.a */; }; E778BFBC17176DDE00302C14 /* security.exp-in in Sources */ = {isa = PBXBuildFile; fileRef = 182BB562146F4C73000BF1F3 /* security.exp-in */; }; EB22F3F918A26BCA0016A8EC /* SecBreadcrumb.c in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */; }; EB22F3FA18A26BCE0016A8EC /* SecBreadcrumb.h in Headers */ = {isa = PBXBuildFile; fileRef = EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */; settings = {ATTRIBUTES = (Private, ); }; }; - EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.c in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */; }; + EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.m in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.m */; }; EB5D733B1B0CB0FF009CAA47 /* SOSPeerInfo.h in Old SOS header location */ = {isa = PBXBuildFile; fileRef = 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */; }; EB5D733C1B0CB109009CAA47 /* SOSTypes.h in Old SOS header location */ = {isa = PBXBuildFile; fileRef = 52F8DE4B1AF2EB6600A2C271 /* SOSTypes.h */; }; - EBC1B8E31BE9708300E6ACA6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBC1B8E21BE9708300E6ACA6 /* Foundation.framework */; }; - EBF2D7141C1E0AF7006AB6FF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBF2D7131C1E0AF7006AB6FF /* Foundation.framework */; }; - EBF2D7631C1E2B58006AB6FF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBF2D7131C1E0AF7006AB6FF /* Foundation.framework */; }; - EBF2D7641C1E3AB2006AB6FF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBF2D7131C1E0AF7006AB6FF /* Foundation.framework */; }; - EBF2E29D1BEC8D9200626DE4 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBF2E29C1BEC8D9200626DE4 /* IOKit.framework */; }; + EB73EFE81C210947008191E3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; + EB73EFE91C210947008191E3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; + EB73EFEA1C210947008191E3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; + EB73EFEB1C210947008191E3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; + EB73F0451C210E6F008191E3 /* SecurityFeatures.h in Headers */ = {isa = PBXBuildFile; fileRef = EB73F0441C210DF8008191E3 /* SecurityFeatures.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EBB6970B1BE2091300715F16 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD19A65E1A8065E900F9C276 /* Foundation.framework */; }; + EBB6970F1BE209D400715F16 /* secbackupntest.m in Sources */ = {isa = PBXBuildFile; fileRef = EBB696FF1BE208CB00715F16 /* secbackupntest.m */; }; + EBB697101BE20A1200715F16 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1807384B146D0D4E00F05C24 /* Security.framework */; }; F93C493E1AB8FF670047E01A /* ckcdiagnose.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = F93C493D1AB8FF670047E01A /* ckcdiagnose.sh */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; /* End PBXBuildFile section */ @@ -648,20 +667,6 @@ remoteGlobalIDString = 0CCA42D715C8A395002AEC4C; remoteInfo = dtlsEchoServer; }; - 0C6D77EA15C8C06600BB4405 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 0CE08A73148FF2C6000473EB; - remoteInfo = tlsnketest; - }; - 0C6D77EC15C8C06600BB4405 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 0CDF46A014DC794300FFE2FD; - remoteInfo = tlssocket; - }; 0CBD50B216C325F000713B6C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; @@ -1089,20 +1094,6 @@ remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; remoteInfo = copyHeaders; }; - 186F779814E5A06500434E1F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 186F778814E59FB200434E1F; - remoteInfo = Framework; - }; - 186F779A14E5A06800434E1F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 186F778C14E59FDA00434E1F; - remoteInfo = Helpers; - }; 1879B537146DDBE5007E536C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; @@ -1404,13 +1395,6 @@ remoteGlobalIDString = 795CA7FF0D38013D00BAE6A2; remoteInfo = libASN1; }; - 1885B45014D9AB3D00519375 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 795CA7FE0D38013D00BAE6A2; - remoteInfo = libASN1; - }; 18AD56A514CDED59008233F2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; @@ -1446,6 +1430,20 @@ remoteGlobalIDString = 18FE67E91471A3AA00A2CBE3; remoteInfo = copyHeaders; }; + 1F6FC5FF1C3D9D90001C758F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F6FC5DF1C3D9D90001C758F /* libsecurity_translocate.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 1FAA71431C10D8E000EAAE3E; + remoteInfo = libsecurity_translocate; + }; + 1FDA9A5E1C4471EC0083929D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1F6FC5DF1C3D9D90001C758F /* libsecurity_translocate.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 1FAA71421C10D8E000EAAE3E; + remoteInfo = libsecurity_translocate; + }; 3705CADD1A8971DF00402F75 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 18073841146D0D4E00F05C24 /* Project object */; @@ -1488,13 +1486,6 @@ remoteGlobalIDString = 4A5CCA4E15ACEFA500702357; remoteInfo = libSecOtrOSX; }; - 4C01DE31164C3793006798CD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 528402A0164445760035F320; - remoteInfo = libCloudKeychainProxy; - }; 4C01DF12164C3E74006798CD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; @@ -1642,27 +1633,6 @@ remoteGlobalIDString = E702E73514E1F3EA00CDE635; remoteInfo = libSecureObjectSync; }; - 5214701716977D1D00DF0DB3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E742A09B14E343E70052A486; - remoteInfo = utilities; - }; - 5214701916977D2500DF0DB3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 5284029F164445760035F320; - remoteInfo = libCloudKeychainProxy; - }; - 521470281697842500DF0DB3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5214700516977CB800DF0DB3; - remoteInfo = CloudKeychainProxy; - }; 52B5A8F5151928B400664F11 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; @@ -1670,13 +1640,6 @@ remoteGlobalIDString = 52200F8F14F2B88000F7F6E7; remoteInfo = XPCTimeStampingService; }; - 5ED88B6D1B0DEF3100F3B047 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 053BA313091C00BF00A7007A; - remoteInfo = libDER; - }; 5ED88B6F1B0DEF4700F3B047 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; @@ -1733,13 +1696,6 @@ remoteGlobalIDString = 186CDD0E14CA116C00AF9171; remoteInfo = libSecItemShimOSX; }; - 722CF217175D602F00BCE0A5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 72756BFD175D485D00F52070; - remoteInfo = cloud_keychain_diagnose; - }; ACB6171718B5231800EBEDD7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; @@ -1761,13 +1717,6 @@ remoteGlobalIDString = 18270F5414CF651900B05E7F; remoteInfo = libsecipc_client; }; - BE48ADFB1ADF1DF4000836C1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = E702E73514E1F3EA00CDE635; - remoteInfo = libSecureObjectSync; - }; BE48ADFD1ADF1DF4000836C1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; @@ -1775,27 +1724,6 @@ remoteGlobalIDString = E742A09B14E343E70052A486; remoteInfo = utilities; }; - BE48ADFF1ADF1DF4000836C1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 18D4056114CE53C200A2BE4E; - remoteInfo = libsecurityd; - }; - BE48AE011ADF1DF4000836C1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; - remoteInfo = libsecurity; - }; - BE48AE221ADF1E66000836C1 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = BE8D227F1ABB7199009A4E18; - remoteInfo = libSecTrustOSX; - }; BE48AE281ADF204E000836C1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 18073841146D0D4E00F05C24 /* Project object */; @@ -1817,89 +1745,110 @@ remoteGlobalIDString = BE8D228E1ABB7199009A4E18; remoteInfo = libSecTrustOSX; }; - BE94B7E01AD8442600A7216D /* PBXContainerItemProxy */ = { + C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = C209696015BF52040093035F; + remoteInfo = gkunpack; + }; + C2432A2415C726B50096DB5B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = C209695F15BF52040093035F; + remoteInfo = gkunpack; + }; + D40772171C9B52210016AA66 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D40771B81C9B4D200016AA66; + remoteInfo = libSharedRegressions; + }; + D42FA8361C9B8F77003E46A7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18270F5414CF651900B05E7F; - remoteInfo = libsecipc_client; + remoteGlobalIDString = D4C3345B1BE2A2B100D8C1EF; + remoteInfo = libsecurity_cms_regressions; }; - BE94B7E41AD8446500A7216D /* PBXContainerItemProxy */ = { + D42FA8381C9B8F7D003E46A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 0CC3355B16C1EF5D00399E53 /* regressions.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E742A09B14E343E70052A486; - remoteInfo = utilities; + remoteGlobalIDString = E710C6FD133192E900F85568; + remoteInfo = regressions; }; - BE94B7E61AD8446C00A7216D /* PBXContainerItemProxy */ = { + D42FA83A1C9B8F94003E46A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 1879B6A0146DE79F007E536C /* libsecurity_keychain.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18D4056114CE53C200A2BE4E; - remoteInfo = libsecurityd; + remoteGlobalIDString = 0CBD500016C3242200713B6C; + remoteInfo = libsecurity_keychain_regressions; }; - BE94B7E81AD8447B00A7216D /* PBXContainerItemProxy */ = { + D42FA83C1C9B8F94003E46A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 1879B71F146DE839007E536C /* libsecurity_ssl.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 18D4043414CE0CF300A2BE4E; - remoteInfo = libsecurity; + remoteGlobalIDString = 0CCA415815C89E8B002AEC4C; + remoteInfo = libsecurity_ssl_regressions; }; - BE94B7EA1AD8449300A7216D /* PBXContainerItemProxy */ = { + D42FA83E1C9B8F94003E46A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 1879B712146DE825007E536C /* libsecurity_smime.xcodeproj */; proxyType = 1; - remoteGlobalIDString = BE8D227F1ABB7199009A4E18; - remoteInfo = libSecTrustOSX; + remoteGlobalIDString = AC62F5EF18B4356A00704BBD; + remoteInfo = libsecurity_smime_regressions; }; - BE94B7EE1AD8453300A7216D /* PBXContainerItemProxy */ = { + D42FA8401C9B8FA7003E46A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E702E73514E1F3EA00CDE635; - remoteInfo = libSecureObjectSync; + remoteGlobalIDString = D40771B71C9B4D200016AA66; + remoteInfo = libSharedRegressions; }; - C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */ = { + D42FA8421C9B8FD0003E46A7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C209696015BF52040093035F; - remoteInfo = gkunpack; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; }; - C2432A2415C726B50096DB5B /* PBXContainerItemProxy */ = { + D45FC3E21C9E069000509CDA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; + containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; proxyType = 1; - remoteGlobalIDString = C209695F15BF52040093035F; - remoteInfo = gkunpack; + remoteGlobalIDString = 18D4056114CE53C200A2BE4E; + remoteInfo = libsecurityd; }; - CD63AD0B1A8061FA001B5671 /* PBXContainerItemProxy */ = { + D45FC3E51C9E06BD00509CDA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = CD3F914B1A802EBF00E07119; - remoteInfo = libIDSKeychainSyncingProxy; + proxyType = 1; + remoteGlobalIDString = E702E73514E1F3EA00CDE635; + remoteInfo = libSecureObjectSync; }; - CD63AD111A8063AF001B5671 /* PBXContainerItemProxy */ = { + D466FA761CA0C2A500433142 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; proxyType = 1; - remoteGlobalIDString = CD3F914A1A802EBF00E07119; - remoteInfo = libIDSKeychainSyncingProxy; + remoteGlobalIDString = D42FA8231C9B8D3C003E46A7; + remoteInfo = SecurityTestsOSX; }; - CD63AD131A8063B7001B5671 /* PBXContainerItemProxy */ = { + D46B08011C8FBE6A00B5939A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; proxyType = 1; - remoteGlobalIDString = E742A09B14E343E70052A486; - remoteInfo = utilities; + remoteGlobalIDString = D46B07A51C8FB22900B5939A; + remoteInfo = libDERInstall; }; - CDEB2BD11A8151CD00B0E23A /* PBXContainerItemProxy */ = { + D46B08A71C8FD8D900B5939A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + containerPortal = 1879B5FC146DE704007E536C /* libsecurity_asn1.xcodeproj */; proxyType = 1; - remoteGlobalIDString = CD63ACDF1A8061FA001B5671; - remoteInfo = IDSKeychainSyncingProxy; + remoteGlobalIDString = D46B08791C8FCA5000B5939A; + remoteInfo = libASN1Install; }; D4A2FC7D1BC89D5200BF6E56 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -1922,12 +1871,26 @@ remoteGlobalIDString = D4C3345C1BE2A2B100D8C1EF; remoteInfo = libsecurity_cms_regressions; }; - E7421C7D1ADC8E0D005FC1C0 /* PBXContainerItemProxy */ = { + DC311CC61CCEC81D00E14E8D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 0CC9A7F0146DF66000C18F89; - remoteInfo = tlsnke; + containerPortal = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = E742A09B14E343E70052A486; + remoteInfo = utilities; + }; + DC872EE91CC983EE0076C0E7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; + DC872F141CC983F70076C0E7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18270F0814CF43C000B05E7F /* libDER.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; }; E760796E1951F99600F69731 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -1957,6 +1920,13 @@ remoteGlobalIDString = EB2E1F05166D69B800A7EF61; remoteInfo = CodeSigningHelper; }; + EBB6970D1BE2095F00715F16 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EBB697031BE208FC00715F16; + remoteInfo = secbackupntest; + }; EBB9FFDF1682E71F00FF9774 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1879B657146DE756007E536C /* libsecurity_codesigning.xcodeproj */; @@ -1964,6 +1934,13 @@ remoteGlobalIDString = EBB9FF6E1682E51300FF9774; remoteInfo = CodeSigningHelper; }; + EBE012001C21368400CB6A63 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 18073841146D0D4E00F05C24 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EBE011D31C21357200CB6A63; + remoteInfo = SecurityFeature; + }; F94E7A961ACC8CC200F23132 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 18073841146D0D4E00F05C24 /* Project object */; @@ -1977,10 +1954,10 @@ 0C6D003C177B545D0095D167 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; - dstPath = /private/etc/asl; + dstPath = /System/Library/Preferences/Logging/Subsystems; dstSubfolderSpec = 0; files = ( - 0C6D0065177B54CB0095D167 /* com.apple.securityd in CopyFiles */, + 486326331CAA0C6500A466D9 /* com.apple.securityd.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; @@ -2071,13 +2048,13 @@ }; 4C49390E16E51ED100CE110C /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 12; + buildActionMask = 8; dstPath = /System/Library/LaunchAgents; dstSubfolderSpec = 0; files = ( 4C49390F16E51FC700CE110C /* com.apple.security.keychain-circle-notification.plist in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 0; + runOnlyForDeploymentPostprocessing = 1; }; 4CB23B44169F5873003A0131 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -2101,30 +2078,10 @@ 48FDA8771AF98A3600A9366F /* SOSCloudCircleInternal.h in Copy SecureObjectSync Headers */, 4CB86AF7167A6FF300F46643 /* SOSPeerInfo.h in Copy SecureObjectSync Headers */, 52F8DDFA1AF2E56700A2C271 /* SOSViews.h in Copy SecureObjectSync Headers */, - 52F8DE251AF2E58B00A2C271 /* SOSForerunnerSession.h in Copy SecureObjectSync Headers */, ); name = "Copy SecureObjectSync Headers"; runOnlyForDeploymentPostprocessing = 1; }; - 5214702316977EA600DF0DB3 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchAgents"; - dstSubfolderSpec = 0; - files = ( - 521470261697800500DF0DB3 /* com.apple.security.cloudkeychainproxy.plist in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - 72756BFC175D485D00F52070 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; BE48AE191ADF1DF4000836C1 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -2154,47 +2111,101 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - BE94B79B1AD83AF700A7216D /* Copy sandbox profile */ = { + D4D886F61CED070600DC7583 /* Copy DigiNotar Resources */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = "$(SYSTEM_LIBRARY_DIR)/Sandbox/Profiles"; - dstSubfolderSpec = 0; + buildActionMask = 2147483647; + dstPath = DigiNotar; + dstSubfolderSpec = 7; files = ( - BE94B7DD1AD8426500A7216D /* com.apple.trustd.sb in Copy sandbox profile */, - ); - name = "Copy sandbox profile"; - runOnlyForDeploymentPostprocessing = 1; + D4D887431CED09C500DC7583 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar Resources */, + D4D887421CED09BD00DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar Resources */, + D4D887401CED09B300DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar Resources */, + D4D887411CED09B300DC7583 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar Resources */, + D4D8873C1CED099F00DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar Resources */, + D4D8873D1CED099F00DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar Resources */, + D4D8873E1CED099F00DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar Resources */, + D4D8873F1CED099F00DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar Resources */, + D4D887371CED098500DC7583 /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar Resources */, + D4D887381CED098500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar Resources */, + D4D887391CED098500DC7583 /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar Resources */, + D4D8873A1CED098500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar Resources */, + D4D8873B1CED098500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar Resources */, + D4D887361CED095600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar Resources */, + D4D887351CED094C00DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar Resources */, + D4D887341CED094200DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar Resources */, + D4D887331CED093A00DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar Resources */, + D4D887321CED093200DC7583 /* Invalid-asterisk.google.com.crt in Copy DigiNotar Resources */, + ); + name = "Copy DigiNotar Resources"; + runOnlyForDeploymentPostprocessing = 0; }; - BE94B79F1AD83AF700A7216D /* Copy asl module */ = { + D4D886F71CED070800DC7583 /* Copy DigiNotar-Entrust Resources */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /private/etc/asl; - dstSubfolderSpec = 0; + buildActionMask = 2147483647; + dstPath = "DigiNotar-Entrust"; + dstSubfolderSpec = 7; files = ( - BE94B7DC1AD8425E00A7216D /* com.apple.trustd.asl in Copy asl module */, - ); - name = "Copy asl module"; - runOnlyForDeploymentPostprocessing = 1; + D4D8871B1CED081700DC7583 /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D8871C1CED081700DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D8871D1CED081700DC7583 /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D8871E1CED081700DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D8871F1CED081700DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D887201CED081700DC7583 /* diginotar.root.ca-entrust-secure-server-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D887231CED081700DC7583 /* Invalid-asterisk.google.com.crt in Copy DigiNotar-Entrust Resources */, + D4D887241CED081700DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-Entrust Resources */, + D4D887251CED081700DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D887261CED081700DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt in Copy DigiNotar-Entrust Resources */, + D4D887271CED081700DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D887281CED081700DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-Entrust Resources */, + D4D887291CED081700DC7583 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-Entrust Resources */, + D4D8872A1CED081700DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-Entrust Resources */, + D4D8872B1CED081700DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-Entrust Resources */, + D4D8872C1CED081700DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-Entrust Resources */, + D4D8872D1CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt in Copy DigiNotar-Entrust Resources */, + D4D8872F1CED081700DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt in Copy DigiNotar-Entrust Resources */, + D4D887301CED081700DC7583 /* staatdernederlandenoverheidca-Cert.crt in Copy DigiNotar-Entrust Resources */, + ); + name = "Copy DigiNotar-Entrust Resources"; + runOnlyForDeploymentPostprocessing = 0; }; - CD63AD1D1A806552001B5671 /* CopyFiles */ = { + D4D886F81CED070A00DC7583 /* Copy DigiNotar-ok Resources */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = "$(INDIGO_INSTALL_PATH_PREFIX)/System/Library/LaunchAgents"; - dstSubfolderSpec = 0; + buildActionMask = 2147483647; + dstPath = "DigiNotar-ok"; + dstSubfolderSpec = 7; files = ( - CDE08DD41A85E92200B5C261 /* com.apple.security.idskeychainsyncingproxy.plist in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; + D4D887521CED0A4B00DC7583 /* Invalid-webmail.portofamsterdam.nl.crt in Copy DigiNotar-ok Resources */, + D4D887511CED0A4400DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt in Copy DigiNotar-ok Resources */, + D4D887501CED0A3400DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt in Copy DigiNotar-ok Resources */, + D4D8874F1CED0A2A00DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt in Copy DigiNotar-ok Resources */, + D4D8874E1CED0A0F00DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt in Copy DigiNotar-ok Resources */, + D4D8874D1CED0A0600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt in Copy DigiNotar-ok Resources */, + D4D8874C1CED09FF00DC7583 /* Invalid-asterisk.google.com.crt in Copy DigiNotar-ok Resources */, + D4D887451CED09F600DC7583 /* DigiNotar_Root_CA_G2-RootCertificate.crt in Copy DigiNotar-ok Resources */, + D4D887461CED09F600DC7583 /* diginotar-public-ca-2025-Cert.crt in Copy DigiNotar-ok Resources */, + D4D887471CED09F600DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt in Copy DigiNotar-ok Resources */, + D4D887481CED09F600DC7583 /* diginotar-services-diginotar-root-Cert.crt in Copy DigiNotar-ok Resources */, + D4D887491CED09F600DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt in Copy DigiNotar-ok Resources */, + D4D8874A1CED09F600DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt in Copy DigiNotar-ok Resources */, + D4D8874B1CED09F600DC7583 /* DigiNotarCA2007RootCertificate.crt in Copy DigiNotar-ok Resources */, + D4D887441CED09DA00DC7583 /* Expectations.plist in Copy DigiNotar-ok Resources */, + ); + name = "Copy DigiNotar-ok Resources"; + runOnlyForDeploymentPostprocessing = 0; }; - CDF91EF41AAE025C00E88CF7 /* CopyFiles */ = { + D4D886F91CED070C00DC7583 /* Copy DigicertMalaysia Resources */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = /System/Library/IdentityServices/ServiceDefinitions; - dstSubfolderSpec = 0; + buildActionMask = 2147483647; + dstPath = DigicertMalaysia; + dstSubfolderSpec = 7; files = ( - CDF91EF51AAE028F00E88CF7 /* com.apple.private.alloy.keychainsync.plist in CopyFiles */, + D4D886FE1CED07B400DC7583 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt in Copy DigicertMalaysia Resources */, + D4D886FF1CED07B400DC7583 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt in Copy DigicertMalaysia Resources */, + D4D887001CED07B400DC7583 /* Invalid-webmail.jaring.my.crt in Copy DigicertMalaysia Resources */, + D4D887011CED07B400DC7583 /* Invalid-www.cybersecurity.my.crt in Copy DigicertMalaysia Resources */, ); - runOnlyForDeploymentPostprocessing = 1; + name = "Copy DigicertMalaysia Resources"; + runOnlyForDeploymentPostprocessing = 0; }; EB5D73121B0CB0E0009CAA47 /* Old SOS header location */ = { isa = PBXCopyFilesBuildPhase; @@ -2208,6 +2219,15 @@ name = "Old SOS header location"; runOnlyForDeploymentPostprocessing = 1; }; + EBB697021BE208FC00715F16 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; F93C49351AB8FD3B0047E01A /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -2222,14 +2242,14 @@ /* Begin PBXFileReference section */ 0C03D60317D93E810087643B /* SecDH.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecDH.h; path = sec/Security/SecDH.h; sourceTree = SOURCE_ROOT; }; + 0C0C887C1CCED19E00617D1B /* si-82-sectrust-ct-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-82-sectrust-ct-data"; path = "../shared_regressions/si-82-sectrust-ct-data"; sourceTree = ""; }; 0C4F055D15C9E51A00F9DFD5 /* sslTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslTypes.h; path = libsecurity_ssl/lib/sslTypes.h; sourceTree = SOURCE_ROOT; }; 0C6C630B15D193C800BC68CD /* sectests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sectests; sourceTree = BUILT_PRODUCTS_DIR; }; 0C6C630E15D193C800BC68CD /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 0C6C632415D1964200BC68CD /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; 0C6C632F15D19DE600BC68CD /* test.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = test.xcconfig; sourceTree = ""; }; 0C6D0064177B54C60095D167 /* com.apple.securityd */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.securityd; path = asl/com.apple.securityd; sourceTree = SOURCE_ROOT; }; - 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = tlsnke.xcodeproj; path = tlsnke/tlsnke.xcodeproj; sourceTree = ""; }; - 0CC1228B19C75B9000D23178 /* shared_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = shared_regressions.h; sourceTree = ""; }; + 0C869B691C865E62006A2873 /* CoreCDP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreCDP.framework; path = System/Library/PrivateFrameworks/CoreCDP.framework; sourceTree = SDKROOT; }; 0CC2CB0F1B6A04D80074B0F2 /* libDiagnosticMessagesClient.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDiagnosticMessagesClient.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.Internal.sdk/usr/lib/libDiagnosticMessagesClient.dylib; sourceTree = DEVELOPER_DIR; }; 0CC3352D16C1ED8000399E53 /* secdtests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secdtests; sourceTree = BUILT_PRODUCTS_DIR; }; 0CC3355716C1EEE700399E53 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = secdtests/main.c; sourceTree = ""; }; @@ -2254,8 +2274,6 @@ 18270EFD14CF429600B05E7F /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 18270EFF14CF42CA00B05E7F /* libcorecrypto.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcorecrypto.a; path = /usr/local/lib/libcorecrypto.a; sourceTree = ""; }; 18270F0814CF43C000B05E7F /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = libsecurity_keychain/libDER/libDER.xcodeproj; sourceTree = ""; }; - 18270F3A14CF44C400B05E7F /* debugging.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debugging.c; sourceTree = ""; }; - 18270F3B14CF44C400B05E7F /* debugging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debugging.h; sourceTree = ""; }; 182A190F15D09AF0006AB103 /* connection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = connection.h; sourceTree = ""; }; 182A191015D09AFF006AB103 /* connection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = connection.c; sourceTree = ""; }; 182BB187146EAD4C000BF1F3 /* SecAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAccess.h; path = libsecurity_keychain/lib/SecAccess.h; sourceTree = SOURCE_ROOT; }; @@ -2341,7 +2359,7 @@ 182BB55C146F4544000BF1F3 /* FDEPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FDEPrefs.plist; sourceTree = ""; }; 182BB55D146F4544000BF1F3 /* generateErrStrings.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = generateErrStrings.pl; sourceTree = ""; }; 182BB55E146F4544000BF1F3 /* Security.order */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Security.order; sourceTree = ""; }; - 182BB562146F4C73000BF1F3 /* security.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "security.exp-in"; sourceTree = ""; }; + 182BB562146F4C73000BF1F3 /* security.exp-in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "security.exp-in"; sourceTree = ""; xcLanguageSpecificationIdentifier = ""; }; 182BB568146F4DCA000BF1F3 /* csparser.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = csparser.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 182BB569146F4DCA000BF1F3 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 182BB593146FE1ED000BF1F3 /* libantlr2c++.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libantlr2c++.a"; path = "/usr/local/lib/libantlr2c++.a"; sourceTree = ""; }; @@ -2409,8 +2427,8 @@ 18446193146E9A8F00B12992 /* SecCodeHostLib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCodeHostLib.h; path = libsecurity_codesigning/lib/SecCodeHostLib.h; sourceTree = SOURCE_ROOT; }; 18446194146E9A8F00B12992 /* SecAssessment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecAssessment.h; path = libsecurity_codesigning/lib/SecAssessment.h; sourceTree = SOURCE_ROOT; }; 184461A3146E9D3200B12992 /* libsecurityd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurityd.xcodeproj; path = libsecurityd/libsecurityd.xcodeproj; sourceTree = ""; }; - 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; - 18500FA014708F19006F9AB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; + 18500F9A14708D0E006F9AB4 /* SecDebugErrorMessages.strings */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = SecDebugErrorMessages.strings; path = derived_src/SecDebugErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; + 18500FA014708F19006F9AB4 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = derived_src/en.lproj/SecErrorMessages.strings; sourceTree = BUILT_PRODUCTS_DIR; }; 186CDD1614CA11C700AF9171 /* sec.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = sec.xcodeproj; sourceTree = ""; }; 18752C1D16F2837A004E2799 /* libaks.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks.a; path = usr/local/lib/libaks.a; sourceTree = SDKROOT; }; 1879B4A9146DCA18007E536C /* cssm.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = cssm.mdsinfo; path = libsecurity_cssm/mds/cssm.mdsinfo; sourceTree = SOURCE_ROOT; }; @@ -2469,7 +2487,7 @@ 187D6B9215D4359F00E27494 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/authorization.prompts.strings; sourceTree = ""; }; 187D6B9515D436BF00E27494 /* authorization.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = authorization.plist; sourceTree = ""; }; 188AD8D91471FE3D0081C619 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/FDELocalizable.strings; sourceTree = ""; }; - 188AD8DB1471FE3E0081C619 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 188AD8DB1471FE3E0081C619 /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 18A5493115EFD2F40059E6DC /* dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dummy.cpp; sourceTree = ""; }; 18B647E814D9EB6300F538BF /* oidsalg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsalg.h; path = ../libsecurity_asn1/lib/oidsalg.h; sourceTree = ""; }; 18B647EA14D9EE4300F538BF /* oidsattr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = oidsattr.h; path = ../libsecurity_asn1/lib/oidsattr.h; sourceTree = ""; }; @@ -2525,6 +2543,8 @@ 18F235FC15CA0EDB00060520 /* libstdc++.6.0.9.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.6.0.9.dylib"; path = "/usr/lib/libstdc++.6.0.9.dylib"; sourceTree = ""; }; 18F2360015CAF41100060520 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_codesigning.a; path = /usr/local/lib/libsecurity_codesigning.a; sourceTree = ""; }; 18FE67EA1471A3AA00A2CBE3 /* Security.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Security.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F6FC5DF1C3D9D90001C758F /* libsecurity_translocate.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_translocate.xcodeproj; path = libsecurity_translocate/libsecurity_translocate.xcodeproj; sourceTree = ""; }; + 1FDA9ABB1C4489280083929D /* SecTranslocate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecTranslocate.h; path = libsecurity_translocate/lib/SecTranslocate.h; sourceTree = SOURCE_ROOT; }; 3705CACC1A896D5A00402F75 /* SecTask-Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "SecTask-Entitlements.plist"; sourceTree = ""; }; 3705CACD1A896DA800402F75 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 3705CAD21A896DE800402F75 /* SecTaskTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SecTaskTest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2546,6 +2566,7 @@ 44B2603E18F81A6A008DF20F /* SecAccessControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecAccessControl.h; path = sec/Security/SecAccessControl.h; sourceTree = SOURCE_ROOT; }; 44B2606918F81BFE008DF20F /* SecAccessControlPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecAccessControlPriv.h; path = sec/Security/SecAccessControlPriv.h; sourceTree = SOURCE_ROOT; }; 44D78B8F1A0A611C00B63C6C /* libaks_acl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libaks_acl.a; path = usr/local/lib/libaks_acl.a; sourceTree = SDKROOT; }; + 486326321CAA0C6500A466D9 /* com.apple.securityd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = com.apple.securityd.plist; path = sec/os_log/com.apple.securityd.plist; sourceTree = ""; }; 48FDA84D1AF989F600A9366F /* SOSCloudCircleInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSCloudCircleInternal.h; path = sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h; sourceTree = SOURCE_ROOT; }; 4C0F6F861985877800178101 /* SecEntitlements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEntitlements.h; sourceTree = ""; }; 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = utilities.xcodeproj; sourceTree = ""; }; @@ -2596,23 +2617,16 @@ 4CD1980C16DD3BDF00A9E8FD /* NSArray+mapWithBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+mapWithBlock.m"; path = "Keychain Circle Notification/NSArray+mapWithBlock.m"; sourceTree = SOURCE_ROOT; }; 4CE7EA7D1AEAF50F0067F5BD /* SecItemBackup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecItemBackup.h; path = sec/Security/SecItemBackup.h; sourceTree = SOURCE_ROOT; }; 4CF42BB515A3947F00ACACE1 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CloudKeychainProxy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; 5214700716977CB800DF0DB3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; - 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CloudKeychainProxy-Info.plist"; sourceTree = ""; }; - 5214701116977CB800DF0DB3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = cloudkeychain.entitlements.plist; sourceTree = ""; }; - 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.security.cloudkeychainproxy.plist; sourceTree = ""; }; 524492691AFD6CB70043695A /* der_plist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = der_plist.h; path = ../utilities/src/der_plist.h; sourceTree = ""; }; 52AEA484153C7581005AFC59 /* tsaSupportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tsaSupportPriv.h; path = libsecurity_smime/lib/tsaSupportPriv.h; sourceTree = SOURCE_ROOT; }; 52B006BF15238F76005D4556 /* TimeStampingPrefs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TimeStampingPrefs.plist; sourceTree = ""; }; 52B5A9C01519330300664F11 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaSupport.h; path = libsecurity_smime/lib/tsaSupport.h; sourceTree = SOURCE_ROOT; }; 52B5A9C11519330300664F11 /* tsaTemplates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tsaTemplates.h; path = libsecurity_smime/lib/tsaTemplates.h; sourceTree = SOURCE_ROOT; }; - 52C3D235169B56860091D9D3 /* ckdmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = sec/SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = SOURCE_ROOT; }; 52F8DDF91AF2E56600A2C271 /* SOSViews.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSViews.h; path = ../sec/SOSCircle/SecureObjectSync/SOSViews.h; sourceTree = ""; }; 52F8DE201AF2E57300A2C271 /* SOSBackupSliceKeyBag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSBackupSliceKeyBag.h; path = ../sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.h; sourceTree = ""; }; - 52F8DE231AF2E58B00A2C271 /* SOSForerunnerSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSForerunnerSession.h; path = ../sec/SOSCircle/SecureObjectSync/SOSForerunnerSession.h; sourceTree = ""; }; 52F8DE4B1AF2EB6600A2C271 /* SOSTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSTypes.h; path = ../sec/SOSCircle/SecureObjectSync/SOSTypes.h; sourceTree = ""; }; - 5328475217850741009118DC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 5328475217850741009118DC /* en */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 5E27BBFA18F4103100B6C79A /* libcoreauthd_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_client.a; path = usr/local/lib/libcoreauthd_client.a; sourceTree = SDKROOT; }; 5E605AFB1AB859B70049FA14 /* libcoreauthd_test_client.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcoreauthd_test_client.a; path = usr/local/lib/libcoreauthd_test_client.a; sourceTree = SDKROOT; }; 5E7AF4721ACD64AC00005140 /* libACM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libACM.a; path = usr/local/lib/libACM.a; sourceTree = SDKROOT; }; @@ -2622,50 +2636,90 @@ 5EF7C23A1B00E48200E5E99C /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../secacltests/main.c; sourceTree = ""; }; 5EF7C23C1B00E48200E5E99C /* secacltests-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "secacltests-entitlements.plist"; path = "../../secacltests/secacltests-entitlements.plist"; sourceTree = ""; }; 5EF7C23D1B00E48200E5E99C /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = testlist.h; path = ../../secacltests/testlist.h; sourceTree = ""; }; + 6C721DB01D3D18D700888AE1 /* login.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = login.framework; path = System/Library/PrivateFrameworks/login.framework; sourceTree = SDKROOT; }; 721680A8179B40F600406BB4 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 721680AA179B40F600406BB4 /* iCloudStats.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = iCloudStats.1; sourceTree = ""; }; 721680BD179B4F9100406BB4 /* com.apple.iCloudStats.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.iCloudStats.plist; sourceTree = ""; }; - 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cloud_keychain_diagnose; sourceTree = BUILT_PRODUCTS_DIR; }; - 72756C04175D485D00F52070 /* cloud_keychain_diagnose-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "cloud_keychain_diagnose-Prefix.pch"; sourceTree = ""; }; - 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cloud_keychain_diagnose.c; path = utilities/src/cloud_keychain_diagnose.c; sourceTree = SOURCE_ROOT; }; AC5688BA18B4396D00F0526C /* SecCMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecCMS.h; path = libsecurity_smime/lib/SecCMS.h; sourceTree = SOURCE_ROOT; }; BE48AE211ADF1DF4000836C1 /* trustd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = trustd; sourceTree = BUILT_PRODUCTS_DIR; }; BE48AE241ADF1FD3000836C1 /* com.apple.trustd.agent.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.trustd.agent.plist; sourceTree = ""; }; BE48AE261ADF2011000836C1 /* com.apple.trustd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.apple.trustd.plist; sourceTree = ""; }; BE7048911AD84C53000402D8 /* trustd-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "trustd-Prefix.pch"; path = "trustd/trustd-Prefix.pch"; sourceTree = SOURCE_ROOT; }; + BE7169F41C0E7A2B00AFC620 /* entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; BE8C5F0916F7CE450074CF86 /* framework.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = framework.sb; sourceTree = ""; }; - BE94B7A41AD83AF700A7216D /* trustd.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = trustd.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; BE94B7A51AD83AF800A7216D /* trustd-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "trustd-Info.plist"; sourceTree = ""; }; BE94B7DA1AD8424700A7216D /* com.apple.trustd.asl */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.trustd.asl; path = ../trustd/com.apple.trustd.asl; sourceTree = ""; }; BE94B7DB1AD8424700A7216D /* com.apple.trustd.sb */ = {isa = PBXFileReference; lastKnownFileType = text; name = com.apple.trustd.sb; path = ../trustd/com.apple.trustd.sb; sourceTree = ""; }; BEC3A76716F79497003E5634 /* SecTaskPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTaskPriv.h; path = libsecurity_codesigning/lib/SecTaskPriv.h; sourceTree = SOURCE_ROOT; }; - BEFB63681B6834AB0052149A /* AppWorkaround.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AppWorkaround.plist; sourceTree = ""; }; C288A0881505795D00E773B7 /* libOpenScriptingUtil.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libOpenScriptingUtil.dylib; path = ../../../../../usr/lib/libOpenScriptingUtil.dylib; sourceTree = ""; }; CD19A65E1A8065E900F9C276 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; CD276BE31A83F204003226BC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = IDSKeychainSyncingProxy/en.lproj/InfoPlist.strings; sourceTree = ""; }; CD4F43CC1B546A1900FE3569 /* SOSPeerInfoV2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SOSPeerInfoV2.h; path = sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.h; sourceTree = SOURCE_ROOT; }; - CD50D6D21A841C0E00C35E74 /* com.apple.security.idskeychainsyncingproxy.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.security.idskeychainsyncingproxy.plist; sourceTree = ""; }; - CD63ACE01A8061FA001B5671 /* IDSKeychainSyncingProxy.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IDSKeychainSyncingProxy.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - CD63AD151A8064C2001B5671 /* idksmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = idksmain.m; path = ../../IDSKeychainSyncingProxy/idksmain.m; sourceTree = ""; }; - CD63AD181A8064DE001B5671 /* IDSKeychainSyncingProxy-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "IDSKeychainSyncingProxy-Info.plist"; sourceTree = ""; }; - CD63AD191A8064DE001B5671 /* idskeychainsyncingproxy.entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = idskeychainsyncingproxy.entitlements.plist; sourceTree = ""; }; CD7446D8195A1CFE00FB01C0 /* IDS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDS.framework; path = System/Library/PrivateFrameworks/IDS.framework; sourceTree = SDKROOT; }; CD8B5A9C1B618ED9004D4AEF /* SOSPeerInfoPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SOSPeerInfoPriv.h; path = ../sec/SOSCircle/SecureObjectSync/SOSPeerInfoPriv.h; sourceTree = ""; }; CDDE9D1C1729DF250013B0E8 /* SecPasswordGenerate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecPasswordGenerate.h; path = ../sec/Security/SecPasswordGenerate.h; sourceTree = ""; }; - CDF91EC81AAE022600E88CF7 /* com.apple.private.alloy.keychainsync.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = com.apple.private.alloy.keychainsync.plist; sourceTree = ""; }; D41685831B3A288F001FB54E /* oids.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = oids.h; path = libsecurity_keychain/libDER/libDER/oids.h; sourceTree = SOURCE_ROOT; }; + D42FA8241C9B8D3C003E46A7 /* SecurityTestsOSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SecurityTestsOSX.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D42FA82A1C9B8D3D003E46A7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + D42FA8311C9B8D3D003E46A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D42FA8351C9B8EC4003E46A7 /* testlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testlist.h; sourceTree = ""; }; + D42FA8441C9B8FDE003E46A7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + D42FA84C1C9B901E003E46A7 /* 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; }; + D42FA84F1C9B9047003E46A7 /* 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; }; + D42FA87A1C9B9099003E46A7 /* SecurityTests-Entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SecurityTests-Entitlements.plist"; sourceTree = ""; }; + D42FA87C1C9B9186003E46A7 /* si-82-sectrust-ct-logs.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "si-82-sectrust-ct-logs.plist"; path = "../shared_regressions/si-82-sectrust-ct-logs.plist"; sourceTree = ""; }; + D447C0C11D2C9BAB0082FC1D /* libDiagnosticMessagesClient.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDiagnosticMessagesClient.dylib; path = usr/lib/libDiagnosticMessagesClient.dylib; sourceTree = SDKROOT; }; D46E9CED1B1E5DEF00ED650E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; D46E9CEE1B1E5DEF00ED650E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + D47F51211C3B80DE00A7CEFE /* SecCFAllocator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecCFAllocator.h; path = ../sec/Security/SecCFAllocator.h; sourceTree = ""; }; + D4D886C31CEBDBEB00DC7583 /* ssl-policy-certs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "ssl-policy-certs"; path = "../../SecurityTests/ssl-policy-certs"; sourceTree = ""; }; + D4D886F21CED01F800DC7583 /* nist-certs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "nist-certs"; path = "../../SecurityTests/nist-certs"; sourceTree = ""; }; + D4D886FA1CED07B400DC7583 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Digisign-Server-ID-Enrich-Entrust-Cert.crt"; path = "../../SecurityTests/DigicertMalaysia/Digisign-Server-ID-Enrich-Entrust-Cert.crt"; sourceTree = ""; }; + D4D886FB1CED07B400DC7583 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Digisign-Server-ID-Enrich-GTETrust-Cert.crt"; path = "../../SecurityTests/DigicertMalaysia/Digisign-Server-ID-Enrich-GTETrust-Cert.crt"; sourceTree = ""; }; + D4D886FC1CED07B400DC7583 /* Invalid-webmail.jaring.my.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-webmail.jaring.my.crt"; path = "../../SecurityTests/DigicertMalaysia/Invalid-webmail.jaring.my.crt"; sourceTree = ""; }; + D4D886FD1CED07B400DC7583 /* Invalid-www.cybersecurity.my.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-www.cybersecurity.my.crt"; path = "../../SecurityTests/DigicertMalaysia/Invalid-www.cybersecurity.my.crt"; sourceTree = ""; }; + D4D887031CED081500DC7583 /* DigiNotar_Root_CA_G2-RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "DigiNotar_Root_CA_G2-RootCertificate.crt"; path = "../../SecurityTests/DigiNotar/DigiNotar_Root_CA_G2-RootCertificate.crt"; sourceTree = ""; }; + D4D887041CED081500DC7583 /* diginotar-public-ca-2025-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "diginotar-public-ca-2025-Cert.crt"; path = "../../SecurityTests/DigiNotar/diginotar-public-ca-2025-Cert.crt"; sourceTree = ""; }; + D4D887051CED081500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "diginotar-services-1024-entrust-secure-server-Cert.crt"; path = "../../SecurityTests/DigiNotar/diginotar-services-1024-entrust-secure-server-Cert.crt"; sourceTree = ""; }; + D4D887061CED081500DC7583 /* diginotar-services-diginotar-root-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "diginotar-services-diginotar-root-Cert.crt"; path = "../../SecurityTests/DigiNotar/diginotar-services-diginotar-root-Cert.crt"; sourceTree = ""; }; + D4D887071CED081500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "diginotar.cyberca-gte.global.root-Cert.crt"; path = "../../SecurityTests/DigiNotar/diginotar.cyberca-gte.global.root-Cert.crt"; sourceTree = ""; }; + D4D887081CED081500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "diginotar.extended.validation-diginotar.root.ca-Cert.crt"; path = "../../SecurityTests/DigiNotar/diginotar.extended.validation-diginotar.root.ca-Cert.crt"; sourceTree = ""; }; + D4D887091CED081500DC7583 /* diginotar.root.ca-entrust-secure-server-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "diginotar.root.ca-entrust-secure-server-Cert.crt"; path = "../../SecurityTests/DigiNotar/diginotar.root.ca-entrust-secure-server-Cert.crt"; sourceTree = ""; }; + D4D8870A1CED081500DC7583 /* DigiNotarCA2007RootCertificate.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = DigiNotarCA2007RootCertificate.crt; path = ../../SecurityTests/DigiNotar/DigiNotarCA2007RootCertificate.crt; sourceTree = ""; }; + D4D8870B1CED081500DC7583 /* Expectations.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Expectations.plist; path = ../../SecurityTests/DigiNotar/Expectations.plist; sourceTree = ""; }; + D4D8870C1CED081600DC7583 /* Invalid-asterisk.google.com.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-asterisk.google.com.crt"; path = "../../SecurityTests/DigiNotar/Invalid-asterisk.google.com.crt"; sourceTree = ""; }; + D4D8870D1CED081600DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-CertiID_Enterprise_Certificate_Authority.crt"; path = "../../SecurityTests/DigiNotar/Invalid-CertiID_Enterprise_Certificate_Authority.crt"; sourceTree = ""; }; + D4D8870E1CED081600DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt"; path = "../../SecurityTests/DigiNotar/Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt"; sourceTree = ""; }; + D4D8870F1CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-diginotarpkioverheidcaoverheid.crt"; path = "../../SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheid.crt"; sourceTree = ""; }; + D4D887101CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt"; path = "../../SecurityTests/DigiNotar/Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt"; sourceTree = ""; }; + D4D887111CED081600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt"; path = "../../SecurityTests/DigiNotar/Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt"; sourceTree = ""; }; + D4D887121CED081600DC7583 /* Invalid-webmail.portofamsterdam.nl.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-webmail.portofamsterdam.nl.crt"; path = "../../SecurityTests/DigiNotar/Invalid-webmail.portofamsterdam.nl.crt"; sourceTree = ""; }; + D4D887131CED081600DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-webmail.terneuzen.nl-diginotar-services.crt"; path = "../../SecurityTests/DigiNotar/Invalid-webmail.terneuzen.nl-diginotar-services.crt"; sourceTree = ""; }; + D4D887141CED081600DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-www.maestre.com-diginotal.extended.validation.crt"; path = "../../SecurityTests/DigiNotar/Invalid-www.maestre.com-diginotal.extended.validation.crt"; sourceTree = ""; }; + D4D887151CED081600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt"; path = "../../SecurityTests/DigiNotar/Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt"; sourceTree = ""; }; + D4D887161CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt; path = ../../SecurityTests/DigiNotar/Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt; sourceTree = ""; }; + D4D887171CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = Ministerie_van_Defensie_Certificatie_Autoriteit.crt; path = ../../SecurityTests/DigiNotar/Ministerie_van_Defensie_Certificatie_Autoriteit.crt; sourceTree = ""; }; + D4D887181CED081700DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "staatdernederlandenorganisatieca-g2-Cert.crt"; path = "../../SecurityTests/DigiNotar/staatdernederlandenorganisatieca-g2-Cert.crt"; sourceTree = ""; }; + D4D887191CED081700DC7583 /* staatdernederlandenoverheidca-Cert.crt */ = {isa = PBXFileReference; lastKnownFileType = file; name = "staatdernederlandenoverheidca-Cert.crt"; path = "../../SecurityTests/DigiNotar/staatdernederlandenoverheidca-Cert.crt"; sourceTree = ""; }; + D4D9B9FD1C7E5CCA008785EB /* SecServerEncryptionSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecServerEncryptionSupport.h; path = ../sec/Security/SecServerEncryptionSupport.h; sourceTree = ""; }; D4DDD3A71BE3EB4200E8AE2D /* libDiagnosticMessagesClient.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libDiagnosticMessagesClient.dylib; path = ../../../../../../usr/lib/libDiagnosticMessagesClient.dylib; sourceTree = ""; }; - EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "bc-10-knife-on-bread.c"; path = "Breadcrumb/bc-10-knife-on-bread.c"; sourceTree = ""; }; + D4DDD9661CA2F2A700AA03AE /* libbsm.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbsm.dylib; path = usr/lib/libbsm.dylib; sourceTree = SDKROOT; }; + D4EC94D51CEA48000083E753 /* si-20-sectrust-policies-data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "si-20-sectrust-policies-data"; path = "../shared_regressions/si-20-sectrust-policies-data"; sourceTree = ""; }; + DC7EFBAA1CBC46A7005F9624 /* SecurityFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SecurityFoundation.framework; path = System/Library/Frameworks/SecurityFoundation.framework; sourceTree = SDKROOT; }; + EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "bc-10-knife-on-bread.m"; path = "Breadcrumb/bc-10-knife-on-bread.m"; sourceTree = ""; }; EB22F3F618A26BA50016A8EC /* breadcrumb_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breadcrumb_regressions.h; path = Breadcrumb/breadcrumb_regressions.h; sourceTree = ""; }; EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecBreadcrumb.c; path = Breadcrumb/SecBreadcrumb.c; sourceTree = ""; }; EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBreadcrumb.h; path = Breadcrumb/SecBreadcrumb.h; sourceTree = ""; }; - EB93FF531BE088F600978606 /* secbackupntest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secbackupntest.m; path = secbackupntest/secbackupntest.m; sourceTree = ""; }; - EB93FF541BE088FC00978606 /* Security.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Security.plist; sourceTree = ""; }; - EB93FF8D1BE08DE600978606 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.Internal.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; - EBC1B8E21BE9708300E6ACA6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.Internal.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + EB73F03E1C210D49008191E3 /* SecurityFeatures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecurityFeatures.h; path = SecurityFeatures/iOS/SecurityFeatures.h; sourceTree = ""; }; + EB73F03F1C210D58008191E3 /* SecurityFeatures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecurityFeatures.h; path = SecurityFeatures/OSX/SecurityFeatures.h; sourceTree = ""; }; + EB73F0401C210D78008191E3 /* CopyHeaders.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = CopyHeaders.sh; path = SecurityFeatures/CopyHeaders.sh; sourceTree = ""; }; + EB73F0411C210D78008191E3 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = SecurityFeatures/README.txt; sourceTree = ""; }; + EB73F0441C210DF8008191E3 /* SecurityFeatures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SecurityFeatures.h; path = include/Security/SecurityFeatures.h; sourceTree = ""; }; + EBB696FD1BE208BA00715F16 /* Security.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Security.plist; sourceTree = ""; }; + EBB696FF1BE208CB00715F16 /* secbackupntest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secbackupntest.m; path = secbackupntest/secbackupntest.m; sourceTree = ""; }; + EBB697041BE208FC00715F16 /* secbackupntest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secbackupntest; sourceTree = BUILT_PRODUCTS_DIR; }; EBD8B52718A55668004A650F /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README; path = Breadcrumb/README; sourceTree = ""; }; + EBE011FF1C2135E200CB6A63 /* ExternalProject.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = ExternalProject.sh; path = SecurityFeatures/ExternalProject.sh; sourceTree = ""; }; EBF2D7131C1E0AF7006AB6FF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.Internal.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; EBF2E29C1BEC8D9200626DE4 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.Internal.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; }; F93C493D1AB8FF670047E01A /* ckcdiagnose.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ckcdiagnose.sh; sourceTree = ""; }; @@ -2676,13 +2730,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EBF2D7641C1E3AB2006AB6FF /* Foundation.framework in Frameworks */, + EB73EFE91C210947008191E3 /* Foundation.framework in Frameworks */, + 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */, D4CBC1451BE981F600C5795E /* libsecurity_cms_regressions.a in Frameworks */, 18CD682717272EBC005345FB /* libaks.a in Frameworks */, 0CCEBDB416C2D026001BD7F6 /* libregressions.a in Frameworks */, + DC247FB51CBF1C2500527D67 /* libDER.a in Frameworks */, 52669053169D181900ED8231 /* Security.framework in Frameworks */, + DC7EFBAB1CBC46A7005F9624 /* SecurityFoundation.framework in Frameworks */, 0C6C633015D19FF500BC68CD /* CoreFoundation.framework in Frameworks */, - 0C6C632A15D1989900BC68CD /* libsecurity_ssl_regressions.a in Frameworks */, 0CAA7AB516C9A72A00A32C6D /* libsecurity_keychain_regressions.a in Frameworks */, ACB6171918B5231800EBEDD7 /* libsecurity_smime_regressions.a in Frameworks */, 18CD684E17272EE2005345FB /* IOKit.framework in Frameworks */, @@ -2693,29 +2749,32 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EBF2D7141C1E0AF7006AB6FF /* Foundation.framework in Frameworks */, + D447C0E71D2C9C390082FC1D /* libDiagnosticMessagesClient.dylib in Frameworks */, 5E7AF49B1ACD64E600005140 /* libACM.a in Frameworks */, - 5E605AFC1AB859B70049FA14 /* libcoreauthd_test_client.a in Frameworks */, - 44D78BB91A0A615800B63C6C /* libaks_acl.a in Frameworks */, 187A05B1170393FF0038C158 /* libaks.a in Frameworks */, - 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */, - 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */, - 0CC3351E16C1ED8000399E53 /* libDER.a in Frameworks */, + 44D78BB91A0A615800B63C6C /* libaks_acl.a in Frameworks */, 0C10987616CAAE8200803B8F /* libASN1.a in Frameworks */, + D4DDD9671CA2F2A700AA03AE /* libbsm.dylib in Frameworks */, + 5E605AFC1AB859B70049FA14 /* libcoreauthd_test_client.a in Frameworks */, + 4469FC291AA0A5AF0021AA26 /* libctkclient_test.a in Frameworks */, + 0CC3351E16C1ED8000399E53 /* libDER.a in Frameworks */, + 0CCEBDB816C2E6CE001BD7F6 /* libsqlite3.dylib in Frameworks */, 0CC3356316C1EFBE00399E53 /* libregressions.a in Frameworks */, + 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */, + 0CC3352616C1ED8000399E53 /* libsecipc_client.a in Frameworks */, 0CC3351F16C1ED8000399E53 /* libSecItemShimOSX.a in Frameworks */, - 0CC3352016C1ED8000399E53 /* libutilities.a in Frameworks */, + 0CC3352716C1ED8000399E53 /* libSecureObjectSync.a in Frameworks */, 0CC3351C16C1ED8000399E53 /* libsecurity.a in Frameworks */, 0CCEBDB616C2E431001BD7F6 /* libsecurityd.a in Frameworks */, - 0CC3352616C1ED8000399E53 /* libsecipc_client.a in Frameworks */, - 0CC3352716C1ED8000399E53 /* libSecureObjectSync.a in Frameworks */, - 0CCEBDB816C2E6CE001BD7F6 /* libsqlite3.dylib in Frameworks */, - 0CC3352416C1ED8000399E53 /* CoreFoundation.framework in Frameworks */, - 0CCEBDB716C2E6B0001BD7F6 /* CFNetwork.framework in Frameworks */, - 4469FC291AA0A5AF0021AA26 /* libctkclient_test.a in Frameworks */, 0CC3352316C1ED8000399E53 /* libSOSRegressions.a in Frameworks */, + 0CC3352016C1ED8000399E53 /* libutilities.a in Frameworks */, 0CCEBDBB16C30924001BD7F6 /* libutilitiesRegressions.a in Frameworks */, - 0C4EAE7717668DDF00773425 /* libsecdRegressions.a in Frameworks */, + 0CCEBDB716C2E6B0001BD7F6 /* CFNetwork.framework in Frameworks */, + 0CC3352416C1ED8000399E53 /* CoreFoundation.framework in Frameworks */, + EB73EFE81C210947008191E3 /* Foundation.framework in Frameworks */, + 18363C1417026084002D5C1C /* IOKit.framework in Frameworks */, + 39BFB04516D304DE0022564B /* SystemConfiguration.framework in Frameworks */, + D4DDD9961CA320FE00AA03AE /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2723,6 +2782,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 1FDA9ABD1C448DFC0083929D /* libsecurity_translocate.a in Frameworks */, 0CC2CB101B6A04D80074B0F2 /* libDiagnosticMessagesClient.dylib in Frameworks */, 44D78BB81A0A615500B63C6C /* libaks_acl.a in Frameworks */, 44F7912019FFED88008B8147 /* libcoreauthd_client.a in Frameworks */, @@ -2780,26 +2840,29 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6C721DB11D3D18D700888AE1 /* login.framework in Frameworks */, + D447C0C21D2C9BAB0082FC1D /* libDiagnosticMessagesClient.dylib in Frameworks */, 5E7AF4731ACD64AC00005140 /* libACM.a in Frameworks */, - 44D78BBB1A0A617700B63C6C /* libcoreauthd_client.a in Frameworks */, 189757871700CF4C00672567 /* libaks.a in Frameworks */, - 395E7CEE16C64EA500CD82A4 /* SystemConfiguration.framework in Frameworks */, - 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */, - AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */, - 4C7D8765160A74C400D041E3 /* libutilities.a in Frameworks */, 44D78BBA1A0A616200B63C6C /* libaks_acl.a in Frameworks */, - 18F2360115CAF41200060520 /* libsecurity_codesigning.a in Frameworks */, - 1831329B14EB2C6D00F0BCAC /* libASN1.a in Frameworks */, - 1831329C14EB2C6D00F0BCAC /* libDER.a in Frameworks */, - 18270EFE14CF429600B05E7F /* IOKit.framework in Frameworks */, - 18270EFA14CF426200B05E7F /* libsqlite3.dylib in Frameworks */, + 8E64DB4B1C17C2830076C9DF /* libASN1.a in Frameworks */, 18270EF914CF425100B05E7F /* libbsm.dylib in Frameworks */, - 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */, - 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */, + 44D78BBB1A0A617700B63C6C /* libcoreauthd_client.a in Frameworks */, 44A655CF1AA4B4F50059D185 /* libctkclient.a in Frameworks */, + 8E64DB4A1C17C26F0076C9DF /* libDER.a in Frameworks */, + AAF3DCCB1666D03300376593 /* libsecurity_utilities.a in Frameworks */, + 18F2360115CAF41200060520 /* libsecurity_codesigning.a in Frameworks */, + 18270EFA14CF426200B05E7F /* libsqlite3.dylib in Frameworks */, 4C8D8651177A752D0019A804 /* libsecipc_client.a in Frameworks */, - 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */, + 4C01DF14164C3E7C006798CD /* libSecureObjectSync.a in Frameworks */, + 5208BF4F16A0993C0062DDC5 /* libsecurity.a in Frameworks */, + 18270EE814CF294500B05E7F /* libsecurityd.a in Frameworks */, + 4C7D8765160A74C400D041E3 /* libutilities.a in Frameworks */, 18270EFC14CF427800B05E7F /* CFNetwork.framework in Frameworks */, + 18270EF814CF424900B05E7F /* CoreFoundation.framework in Frameworks */, + 18270EFE14CF429600B05E7F /* IOKit.framework in Frameworks */, + 395E7CEE16C64EA500CD82A4 /* SystemConfiguration.framework in Frameworks */, + D4DDD9971CA3216C00AA03AE /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2808,6 +2871,7 @@ buildActionMask = 2147483647; files = ( 182BB592146FE1D7000BF1F3 /* CoreFoundation.framework in Frameworks */, + DC311CC81CCEC82E00E14E8D /* libutilities.a in Frameworks */, 182BB591146FE12F000BF1F3 /* libsecurity_utilities.a in Frameworks */, 182BB590146FE125000BF1F3 /* libsecurity_cdsa_utilities.a in Frameworks */, 182BB589146FE013000BF1F3 /* libsecurity_codesigning.a in Frameworks */, @@ -2855,11 +2919,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0C869B6A1C865E62006A2873 /* CoreCDP.framework in Frameworks */, + 4CAEACCD16D6FC7600263776 /* Security.framework in Frameworks */, 4C97761E17BEB23E0002BFE4 /* AOSAccounts.framework in Frameworks */, 4C5DD46C17A5F67300696A79 /* AppleSystemInfo.framework in Frameworks */, 4C328D301778EC4F0015EED1 /* AOSUI.framework in Frameworks */, 43651E021B016BE8008C4B88 /* CrashReporterSupport.framework in Frameworks */, - 4CAEACCD16D6FC7600263776 /* Security.framework in Frameworks */, 4C96F7C216D6DF8400D3B39D /* Cocoa.framework in Frameworks */, 431B737F1B27762C00EB0360 /* CloudServices.framework in Frameworks */, 431B73C11B2777A200EB0360 /* libutilities.a in Frameworks */, @@ -2870,7 +2935,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EBC1B8E31BE9708300E6ACA6 /* Foundation.framework in Frameworks */, + EB73EFEA1C210947008191E3 /* Foundation.framework in Frameworks */, 44D78BB71A0A613900B63C6C /* libaks_acl.a in Frameworks */, 52CD052316A0E24900218387 /* Security.framework in Frameworks */, 432800841B4CE731002E8525 /* libaks.a in Frameworks */, @@ -2895,25 +2960,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5214700316977CB800DF0DB3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - CD7446D9195A1CFE00FB01C0 /* IDS.framework in Frameworks */, - 5214701E16977DA700DF0DB3 /* libCloudKeychainProxy.a in Frameworks */, - 5214701D16977D9500DF0DB3 /* libutilities.a in Frameworks */, - 529E948C169E29450000AC9B /* Security.framework in Frameworks */, - 0C4EAE4C1766864F00773425 /* libaks.a in Frameworks */, - 0C4EAE761766875E00773425 /* IOKit.framework in Frameworks */, - 43C3B2C61AFD5BBB00786702 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 5EF7C2071B00E25400E5E99C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - EBF2D7631C1E2B58006AB6FF /* Foundation.framework in Frameworks */, + EBB6970B1BE2091300715F16 /* Foundation.framework in Frameworks */, 5EF7C2521B00EB0A00E5E99C /* libaks.a in Frameworks */, 5EF7C2511B00EAF100E5E99C /* libcoreauthd_client.a in Frameworks */, 5EF7C2501B00EA7A00E5E99C /* libACM.a in Frameworks */, @@ -2925,33 +2976,24 @@ 5EF7C24B1B00E71D00E5E99C /* libsecurity.a in Frameworks */, 5ED88B451B0DE63E00F3B047 /* libsecurityd.a in Frameworks */, 5EF7C2401B00E4C300E5E99C /* libregressions.a in Frameworks */, - 5EFB69BD1B0CBE030095A36E /* libDER.a in Frameworks */, + D42CFD771BFD3379008C8737 /* libDER.a in Frameworks */, 5EFB69C31B0CC16F0095A36E /* libsecipc_client.a in Frameworks */, 5EF7C24A1B00E6E300E5E99C /* Security.framework in Frameworks */, 438166AB1B4EC98000C54D58 /* libctkclient.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 72756BFB175D485D00F52070 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EBF2E29D1BEC8D9200626DE4 /* IOKit.framework in Frameworks */, - 43C3B0D41AFD569600786702 /* Security.framework in Frameworks */, - 43C3B3311AFD5E1100786702 /* CoreFoundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; BE48AE041ADF1DF4000836C1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 6C721DD61D3D18EC00888AE1 /* login.framework in Frameworks */, + D45FC3E41C9E06B500509CDA /* libSecureObjectSync.a in Frameworks */, D4DDD3D01BE3EC0300E8AE2D /* libDiagnosticMessagesClient.dylib in Frameworks */, BE48AE051ADF1DF4000836C1 /* libACM.a in Frameworks */, BE48AE061ADF1DF4000836C1 /* libcoreauthd_client.a in Frameworks */, BE48AE071ADF1DF4000836C1 /* libaks.a in Frameworks */, BE48AE081ADF1DF4000836C1 /* SystemConfiguration.framework in Frameworks */, - BE48AE091ADF1DF4000836C1 /* libsecurity.a in Frameworks */, BE48AE0A1ADF1DF4000836C1 /* libsecurity_utilities.a in Frameworks */, BE48AE0B1ADF1DF4000836C1 /* libutilities.a in Frameworks */, BE48AE0C1ADF1DF4000836C1 /* libaks_acl.a in Frameworks */, @@ -2961,53 +3003,43 @@ BE48AE101ADF1DF4000836C1 /* IOKit.framework in Frameworks */, BE48AE111ADF1DF4000836C1 /* libsqlite3.dylib in Frameworks */, BE48AE121ADF1DF4000836C1 /* libbsm.dylib in Frameworks */, - BE48AE131ADF1DF4000836C1 /* libsecurityd.a in Frameworks */, - BE48AE141ADF1DF4000836C1 /* libSecureObjectSync.a in Frameworks */, + D45FC3E11C9E068700509CDA /* libsecurityd.a in Frameworks */, + D467D0EA1C9DF27100C9DE3E /* libsecipc_client.a in Frameworks */, BE48AE151ADF1DF4000836C1 /* libctkclient.a in Frameworks */, - BE48AE161ADF1DF4000836C1 /* libsecipc_client.a in Frameworks */, BE48AE171ADF1DF4000836C1 /* CoreFoundation.framework in Frameworks */, BE48AE181ADF1DF4000836C1 /* CFNetwork.framework in Frameworks */, + D42817D01C6000E1007F95D8 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - BE94B7931AD83AF700A7216D /* Frameworks */ = { + D42FA8211C9B8D3C003E46A7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - BE60737A1ADC9E89007FECC1 /* libACM.a in Frameworks */, - BE607DC61AD8673C001B7778 /* libcoreauthd_client.a in Frameworks */, - BE9703F71AD865540041D253 /* libaks.a in Frameworks */, - BE6073A61ADC9F7A007FECC1 /* SystemConfiguration.framework in Frameworks */, - BE607DC71AD86746001B7778 /* libaks_acl.a in Frameworks */, - BE6073A51ADC9F1C007FECC1 /* libctkclient.a in Frameworks */, - BE94B7D41AD83D0D00A7216D /* libsecurity.a in Frameworks */, - BE94B7D51AD83D2B00A7216D /* libutilities.a in Frameworks */, - BE94B7D21AD83D0D00A7216D /* libSecTrustOSX.a in Frameworks */, - BE2C05151AD893DF00D6A139 /* libsecurity_codesigning.a in Frameworks */, - BE607DC81AD86859001B7778 /* libASN1.a in Frameworks */, - BE607DC91AD8685B001B7778 /* libDER.a in Frameworks */, - BE94B7981AD83AF700A7216D /* IOKit.framework in Frameworks */, - BE94B7941AD83AF700A7216D /* libsqlite3.dylib in Frameworks */, - BE94B7951AD83AF700A7216D /* libbsm.dylib in Frameworks */, - BE94B7D81AD83D6A00A7216D /* libsecurityd.a in Frameworks */, - BE94B7F01AD8457200A7216D /* libSecureObjectSync.a in Frameworks */, - BE94B7D01AD83D0D00A7216D /* libsecipc_client.a in Frameworks */, - BE94B7971AD83AF700A7216D /* CoreFoundation.framework in Frameworks */, - BE6073A71ADC9F88007FECC1 /* CFNetwork.framework in Frameworks */, + D42FA8501C9B9047003E46A7 /* CoreFoundation.framework in Frameworks */, + D42FA84E1C9B903F003E46A7 /* Security.framework in Frameworks */, + DC7EFC0E1CBC7567005F9624 /* SecurityFoundation.framework in Frameworks */, + D42FA8451C9B8FDE003E46A7 /* Foundation.framework in Frameworks */, + D42FA84D1C9B901E003E46A7 /* IOKit.framework in Frameworks */, + D42FA8EB1C9BAAD5003E46A7 /* libaks.a in Frameworks */, + D42FA8E91C9B95EC003E46A7 /* libregressions.a in Frameworks */, + DC247FD81CBF1C3F00527D67 /* libDER.a in Frameworks */, + D42FA84A1C9B900A003E46A7 /* libSharedRegressions.a in Frameworks */, + D42FA8461C9B9000003E46A7 /* libsecurity_cms_regressions.a in Frameworks */, + D42FA8471C9B9000003E46A7 /* libsecurity_keychain_regressions.a in Frameworks */, + D42FA8481C9B9000003E46A7 /* libsecurity_smime_regressions.a in Frameworks */, + D42FA8491C9B9000003E46A7 /* libsecurity_ssl_regressions.a in Frameworks */, + D42FA84B1C9B9013003E46A7 /* libutilities.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - CD63ACDD1A8061FA001B5671 /* Frameworks */ = { + EBB697011BE208FC00715F16 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CD0CB49E1A818A0D00C058A4 /* Security.framework in Frameworks */, - CD2E85F61A81793B00F8B00A /* IDS.framework in Frameworks */, - CD19A65F1A8065E900F9C276 /* Foundation.framework in Frameworks */, - CD19A65D1A8065DC00F9C276 /* libutilities.a in Frameworks */, - 432800831B4CE730002E8525 /* libaks.a in Frameworks */, - CD0637581A840B5B00C81E74 /* IOKit.framework in Frameworks */, - CD19A6611A8069D100F9C276 /* libIDSKeychainSyncingProxy.a in Frameworks */, + EBB697101BE20A1200715F16 /* Security.framework in Frameworks */, + E74583F51BF66506001B54A4 /* IOKit.framework in Frameworks */, + EB73EFEB1C210947008191E3 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3033,32 +3065,6 @@ path = lib; sourceTree = ""; }; - 0C6D77DF15C8C06500BB4405 /* Products */ = { - isa = PBXGroup; - children = ( - E7421C7E1ADC8E0D005FC1C0 /* tlsnke.kext */, - 0C6D77EB15C8C06600BB4405 /* tlsnketest */, - 0C6D77ED15C8C06600BB4405 /* libtlssocket.a */, - ); - name = Products; - sourceTree = ""; - }; - 0C6D77EE15C8C07C00BB4405 /* tlsnke */ = { - isa = PBXGroup; - children = ( - 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */, - ); - name = tlsnke; - sourceTree = ""; - }; - 0CC1228A19C75B8F00D23178 /* shared_regressions */ = { - isa = PBXGroup; - children = ( - 0CC1228B19C75B9000D23178 /* shared_regressions.h */, - ); - path = shared_regressions; - sourceTree = ""; - }; 0CC3355516C1EEAD00399E53 /* secdtests */ = { isa = PBXGroup; children = ( @@ -3079,6 +3085,7 @@ 1807383F146D0D4E00F05C24 = { isa = PBXGroup; children = ( + 486326321CAA0C6500A466D9 /* com.apple.securityd.plist */, F93C493C1AB8FF670047E01A /* ckcdiagnose */, CD276BE21A83F204003226BC /* InfoPlist.strings */, EB22F3CE18A26B640016A8EC /* Breadcrumb */, @@ -3089,24 +3096,21 @@ 186CDD0314CA10E700AF9171 /* sec */, 186CDE7914CA3A3800AF9171 /* secd */, 4C0F6FAF1985879300178101 /* sectask */, - 0CC1228A19C75B8F00D23178 /* shared_regressions */, - 0C6D77EE15C8C07C00BB4405 /* tlsnke */, 181EA421146D4A2A00A6D320 /* config */, 0CC3355516C1EEAD00399E53 /* secdtests */, 0C6C630D15D193C800BC68CD /* sectests */, 18F234ED15C9F9A700060520 /* authd */, BE94B7D91AD8421F00A7216D /* trustd */, - 5214700D16977CB800DF0DB3 /* CloudKeychainProxy */, 4CB23B48169F5873003A0131 /* security2 */, 4CC7A7B516CC2A85003E10C1 /* KeychainDemoApp */, 4C96F7C316D6DF8400D3B39D /* Keychain Circle Notification */, - 72756C00175D485D00F52070 /* cloud_keychain_diagnose */, 721680A7179B40F600406BB4 /* iCloudStats */, 37A7CEAC197DB8FA00926CE8 /* codesign_tests */, 37AB39101A44A88000B56E04 /* gk_reset_check */, - CD63ACE11A8061FA001B5671 /* IDSKeychainSyncingProxy */, 5EF7C20B1B00E25400E5E99C /* secacltests */, - EB93FF2A1BE0889E00978606 /* RegressionTests */, + EB73F0121C210CC7008191E3 /* SecurityFeatures */, + EBB696D51BE2089400715F16 /* RegressionTests */, + D42FA8251C9B8D3C003E46A7 /* SecurityTestsOSX */, 1807384D146D0D4E00F05C24 /* Frameworks */, 1807384C146D0D4E00F05C24 /* Products */, ); @@ -3121,19 +3125,17 @@ 18270ED614CF282600B05E7F /* secd */, 0C6C630B15D193C800BC68CD /* sectests */, 18F234EB15C9F9A600060520 /* authd.xpc */, - 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */, 4CB23B46169F5873003A0131 /* security2 */, 0CC3352D16C1ED8000399E53 /* secdtests */, 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */, 4C96F7C116D6DF8300D3B39D /* Keychain Circle Notification.app */, - 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */, 37A7CEAB197DB8FA00926CE8 /* codesign_tests */, 37AB390F1A44A88000B56E04 /* gk_reset_check */, - CD63ACE01A8061FA001B5671 /* IDSKeychainSyncingProxy.bundle */, 3705CAD21A896DE800402F75 /* SecTaskTest */, 5EF7C20A1B00E25400E5E99C /* secacltests */, - BE94B7A41AD83AF700A7216D /* trustd.xpc */, BE48AE211ADF1DF4000836C1 /* trustd */, + EBB697041BE208FC00715F16 /* secbackupntest */, + D42FA8241C9B8D3C003E46A7 /* SecurityTestsOSX.app */, ); name = Products; sourceTree = ""; @@ -3141,11 +3143,17 @@ 1807384D146D0D4E00F05C24 /* Frameworks */ = { isa = PBXGroup; children = ( + 6C721DB01D3D18D700888AE1 /* login.framework */, + D447C0C11D2C9BAB0082FC1D /* libDiagnosticMessagesClient.dylib */, + DC7EFBAA1CBC46A7005F9624 /* SecurityFoundation.framework */, + D4DDD9661CA2F2A700AA03AE /* libbsm.dylib */, + 0C869B691C865E62006A2873 /* CoreCDP.framework */, + D42FA84F1C9B9047003E46A7 /* CoreFoundation.framework */, + D42FA84C1C9B901E003E46A7 /* IOKit.framework */, + D42FA8441C9B8FDE003E46A7 /* Foundation.framework */, EBF2D7131C1E0AF7006AB6FF /* Foundation.framework */, D4DDD3A71BE3EB4200E8AE2D /* libDiagnosticMessagesClient.dylib */, EBF2E29C1BEC8D9200626DE4 /* IOKit.framework */, - EBC1B8E21BE9708300E6ACA6 /* Foundation.framework */, - EB93FF8D1BE08DE600978606 /* IOKit.framework */, 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */, 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */, 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */, @@ -3216,6 +3224,7 @@ 181EA3D0146D1ED200A6D320 /* libsecurity */ = { isa = PBXGroup; children = ( + 1F6FC5DF1C3D9D90001C758F /* libsecurity_translocate.xcodeproj */, 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */, 1879B547146DE212007E536C /* libsecurity_cdsa_utils.xcodeproj */, 1879B550146DE227007E536C /* libsecurity_cdsa_utilities.xcodeproj */, @@ -3297,8 +3306,6 @@ 18270F3114CF448600B05E7F /* security_utilities */ = { isa = PBXGroup; children = ( - 18270F3A14CF44C400B05E7F /* debugging.c */, - 18270F3B14CF44C400B05E7F /* debugging.h */, ); path = security_utilities; sourceTree = ""; @@ -3306,7 +3313,6 @@ 182BB228146F0674000BF1F3 /* Resources */ = { isa = PBXGroup; children = ( - BEFB63681B6834AB0052149A /* AppWorkaround.plist */, 187D6B8F15D4359F00E27494 /* authorization.buttons.strings */, 187D6B9115D4359F00E27494 /* authorization.prompts.strings */, 43A598591B0CF2AB00D14A7B /* CloudKeychain.strings */, @@ -3368,18 +3374,17 @@ BE8D22BC1ABB747B009A4E18 /* libSecTrustOSX.a */, 18270F6014CF655B00B05E7F /* libsecipc_client.a */, 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */, - 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */, - 4C1288EE15FFE9D7008CE3E3 /* libSecurityRegressions.a */, - 4C1288F015FFE9D7008CE3E3 /* libsecuritydRegressions.a */, 4C1288F215FFE9D7008CE3E3 /* libSecOtrOSX.a */, - 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */, - CD63AD0C1A8061FA001B5671 /* libIDSKeychainSyncingProxy.a */, 4CB23B76169F5873003A0131 /* libSecurityTool.a */, 4CB23B78169F5873003A0131 /* libSecurityCommands.a */, 4CB23B7A169F5873003A0131 /* libSOSCommands.a */, - 0C4EAE721766865000773425 /* libsecdRegressions.a */, E760796F1951F99600F69731 /* libSWCAgent.a */, E76079D51951FDA800F69731 /* liblogging.a */, + 4C1288EC15FFE9D7008CE3E3 /* libSOSRegressions.a */, + 4C1288EE15FFE9D7008CE3E3 /* libSecurityRegressions.a */, + 4C1288F015FFE9D7008CE3E3 /* libsecuritydRegressions.a */, + 0C4EAE721766865000773425 /* libsecdRegressions.a */, + D40772181C9B52210016AA66 /* libSharedRegressions.a */, ); name = Products; sourceTree = ""; @@ -3482,6 +3487,7 @@ isa = PBXGroup; children = ( 524492691AFD6CB70043695A /* der_plist.h */, + 1FDA9ABB1C4489280083929D /* SecTranslocate.h */, 184460A1146DFCB700B12992 /* asn1Templates.h */, 1844614F146E923B00B12992 /* AuthorizationPriv.h */, 1844614E146E923B00B12992 /* AuthorizationTagsPriv.h */, @@ -3504,6 +3510,7 @@ 182BB1B4146EAD5D000BF1F3 /* SecCertificateBundle.h */, 182BB1B5146EAD5D000BF1F3 /* SecCertificatePriv.h */, 182BB1B6146EAD5D000BF1F3 /* SecCertificateRequest.h */, + D47F51211C3B80DE00A7CEFE /* SecCFAllocator.h */, AC5688BA18B4396D00F0526C /* SecCMS.h */, 182BB383146F14D2000BF1F3 /* SecCmsBase.h */, 182BB384146F14D2000BF1F3 /* SecCmsContentInfo.h */, @@ -3542,6 +3549,7 @@ 182BB1CF146EAD5D000BF1F3 /* SecRandomP.h */, 182BB1CE146EAD5D000BF1F3 /* SecRecoveryPassword.h */, 1844618F146E9A8F00B12992 /* SecRequirementPriv.h */, + D4D9B9FD1C7E5CCA008785EB /* SecServerEncryptionSupport.h */, 182BB38F146F14D2000BF1F3 /* SecSMIME.h */, 1844618E146E9A8F00B12992 /* SecStaticCodePriv.h */, 182BB3B7146F1BF9000BF1F3 /* SecTransformInternal.h */, @@ -3555,7 +3563,6 @@ 48FDA84D1AF989F600A9366F /* SOSCloudCircleInternal.h */, 4CB86AE6167A6FF200F46643 /* SOSCircle.h */, 4CB86AE7167A6FF200F46643 /* SOSCloudCircle.h */, - 52F8DE231AF2E58B00A2C271 /* SOSForerunnerSession.h */, 4CB86AED167A6FF300F46643 /* SOSPeerInfo.h */, CD8B5A9C1B618ED9004D4AEF /* SOSPeerInfoPriv.h */, CD4F43CC1B546A1900FE3569 /* SOSPeerInfoV2.h */, @@ -3832,7 +3839,7 @@ isa = PBXGroup; children = ( 1879B739146DE845007E536C /* libsecurity_transform.a */, - 1879B73D146DE845007E536C /* unit-tests.octest */, + 1879B73D146DE845007E536C /* unit-tests.xctest */, 1879B73F146DE845007E536C /* 100-sha2 */, 1879B741146DE845007E536C /* input-speed-test */, ); @@ -3897,6 +3904,14 @@ name = "Supporting Files"; sourceTree = ""; }; + 1F6FC5E01C3D9D90001C758F /* Products */ = { + isa = PBXGroup; + children = ( + 1F6FC6001C3D9D90001C758F /* libsecurity_translocate.a */, + ); + name = Products; + sourceTree = ""; + }; 3705CAA31A896CEE00402F75 /* SecTask */ = { isa = PBXGroup; children = ( @@ -4038,26 +4053,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 5214700D16977CB800DF0DB3 /* CloudKeychainProxy */ = { - isa = PBXGroup; - children = ( - 52C3D235169B56860091D9D3 /* ckdmain.m */, - 5214700E16977CB800DF0DB3 /* Supporting Files */, - ); - path = CloudKeychainProxy; - sourceTree = ""; - }; - 5214700E16977CB800DF0DB3 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 5214702416977FEC00DF0DB3 /* cloudkeychain.entitlements.plist */, - 5214702516977FEC00DF0DB3 /* com.apple.security.cloudkeychainproxy.plist */, - 5214700F16977CB800DF0DB3 /* CloudKeychainProxy-Info.plist */, - 5214701016977CB800DF0DB3 /* InfoPlist.strings */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; 5EF7C20B1B00E25400E5E99C /* secacltests */ = { isa = PBXGroup; children = ( @@ -4079,23 +4074,6 @@ path = iCloudStats; sourceTree = ""; }; - 72756C00175D485D00F52070 /* cloud_keychain_diagnose */ = { - isa = PBXGroup; - children = ( - 72756C30175D48C100F52070 /* cloud_keychain_diagnose.c */, - 72756C03175D485D00F52070 /* Supporting Files */, - ); - path = cloud_keychain_diagnose; - sourceTree = ""; - }; - 72756C03175D485D00F52070 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 72756C04175D485D00F52070 /* cloud_keychain_diagnose-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; BE94B7D91AD8421F00A7216D /* trustd */ = { isa = PBXGroup; children = ( @@ -4103,37 +4081,85 @@ BE48AE241ADF1FD3000836C1 /* com.apple.trustd.agent.plist */, BE48AE261ADF2011000836C1 /* com.apple.trustd.plist */, BE94B7DB1AD8424700A7216D /* com.apple.trustd.sb */, + BE7169F41C0E7A2B00AFC620 /* entitlements.plist */, BE94B7A51AD83AF800A7216D /* trustd-Info.plist */, BE7048911AD84C53000402D8 /* trustd-Prefix.pch */, ); path = trustd; sourceTree = SOURCE_ROOT; }; - CD63ACE11A8061FA001B5671 /* IDSKeychainSyncingProxy */ = { + D42FA8251C9B8D3C003E46A7 /* SecurityTestsOSX */ = { isa = PBXGroup; children = ( - CD63AD151A8064C2001B5671 /* idksmain.m */, - CD63ACE21A8061FA001B5671 /* Supporting Files */, - ); - path = IDSKeychainSyncingProxy; + D42FA82A1C9B8D3D003E46A7 /* main.m */, + D42FA8351C9B8EC4003E46A7 /* testlist.h */, + D42FA87C1C9B9186003E46A7 /* si-82-sectrust-ct-logs.plist */, + D4EC94D51CEA48000083E753 /* si-20-sectrust-policies-data */, + D4D886F21CED01F800DC7583 /* nist-certs */, + D4D887311CED091100DC7583 /* DigiNotar */, + D4D887021CED07CA00DC7583 /* DigicertMalaysia */, + D4D886C31CEBDBEB00DC7583 /* ssl-policy-certs */, + 0C0C887C1CCED19E00617D1B /* si-82-sectrust-ct-data */, + D42FA8291C9B8D3D003E46A7 /* Supporting Files */, + ); + path = SecurityTestsOSX; sourceTree = ""; }; - CD63ACE21A8061FA001B5671 /* Supporting Files */ = { + D42FA8291C9B8D3D003E46A7 /* Supporting Files */ = { isa = PBXGroup; children = ( - CD63AD181A8064DE001B5671 /* IDSKeychainSyncingProxy-Info.plist */, - CD63AD191A8064DE001B5671 /* idskeychainsyncingproxy.entitlements.plist */, - CDF91EC81AAE022600E88CF7 /* com.apple.private.alloy.keychainsync.plist */, - CD50D6D21A841C0E00C35E74 /* com.apple.security.idskeychainsyncingproxy.plist */, + D42FA87A1C9B9099003E46A7 /* SecurityTests-Entitlements.plist */, + D42FA8311C9B8D3D003E46A7 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; + D4D887021CED07CA00DC7583 /* DigicertMalaysia */ = { + isa = PBXGroup; + children = ( + D4D886FA1CED07B400DC7583 /* Digisign-Server-ID-Enrich-Entrust-Cert.crt */, + D4D886FB1CED07B400DC7583 /* Digisign-Server-ID-Enrich-GTETrust-Cert.crt */, + D4D886FC1CED07B400DC7583 /* Invalid-webmail.jaring.my.crt */, + D4D886FD1CED07B400DC7583 /* Invalid-www.cybersecurity.my.crt */, + ); + name = DigicertMalaysia; + sourceTree = ""; + }; + D4D887311CED091100DC7583 /* DigiNotar */ = { + isa = PBXGroup; + children = ( + D4D887031CED081500DC7583 /* DigiNotar_Root_CA_G2-RootCertificate.crt */, + D4D887041CED081500DC7583 /* diginotar-public-ca-2025-Cert.crt */, + D4D887051CED081500DC7583 /* diginotar-services-1024-entrust-secure-server-Cert.crt */, + D4D887061CED081500DC7583 /* diginotar-services-diginotar-root-Cert.crt */, + D4D887071CED081500DC7583 /* diginotar.cyberca-gte.global.root-Cert.crt */, + D4D887081CED081500DC7583 /* diginotar.extended.validation-diginotar.root.ca-Cert.crt */, + D4D887091CED081500DC7583 /* diginotar.root.ca-entrust-secure-server-Cert.crt */, + D4D8870A1CED081500DC7583 /* DigiNotarCA2007RootCertificate.crt */, + D4D8870B1CED081500DC7583 /* Expectations.plist */, + D4D8870C1CED081600DC7583 /* Invalid-asterisk.google.com.crt */, + D4D8870D1CED081600DC7583 /* Invalid-CertiID_Enterprise_Certificate_Authority.crt */, + D4D8870E1CED081600DC7583 /* Invalid-DigiNotar_PKIoverheid_CA_Organisatie_-_G2-Cert.crt */, + D4D8870F1CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheid.crt */, + D4D887101CED081600DC7583 /* Invalid-diginotarpkioverheidcaoverheidenbedrijven-Cert.crt */, + D4D887111CED081600DC7583 /* Invalid-muisonline.omnyacc-denhelder.nl-diginotar.cyberca.crt */, + D4D887121CED081600DC7583 /* Invalid-webmail.portofamsterdam.nl.crt */, + D4D887131CED081600DC7583 /* Invalid-webmail.terneuzen.nl-diginotar-services.crt */, + D4D887141CED081600DC7583 /* Invalid-www.maestre.com-diginotal.extended.validation.crt */, + D4D887151CED081600DC7583 /* Invalid-www.mobilehostingservices.nl-diginotar-services-1024.crt */, + D4D887161CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit_G2.crt */, + D4D887171CED081700DC7583 /* Ministerie_van_Defensie_Certificatie_Autoriteit.crt */, + D4D887181CED081700DC7583 /* staatdernederlandenorganisatieca-g2-Cert.crt */, + D4D887191CED081700DC7583 /* staatdernederlandenoverheidca-Cert.crt */, + ); + name = DigiNotar; + sourceTree = ""; + }; EB22F3CE18A26B640016A8EC /* Breadcrumb */ = { isa = PBXGroup; children = ( EBD8B52718A55668004A650F /* README */, - EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */, + EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.m */, EB22F3F618A26BA50016A8EC /* breadcrumb_regressions.h */, EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */, EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */, @@ -4141,20 +4167,58 @@ name = Breadcrumb; sourceTree = ""; }; - EB93FF2A1BE0889E00978606 /* RegressionTests */ = { + EB73F0121C210CC7008191E3 /* SecurityFeatures */ = { + isa = PBXGroup; + children = ( + EB73F03C1C210CF2008191E3 /* BUILT_PRODUCTS_DIR */, + EB73F03B1C210CDF008191E3 /* iOS */, + EB73F03D1C210CFE008191E3 /* OSX */, + EB73F0401C210D78008191E3 /* CopyHeaders.sh */, + EBE011FF1C2135E200CB6A63 /* ExternalProject.sh */, + EB73F0411C210D78008191E3 /* README.txt */, + ); + name = SecurityFeatures; + path = ..; + sourceTree = ""; + }; + EB73F03B1C210CDF008191E3 /* iOS */ = { + isa = PBXGroup; + children = ( + EB73F03E1C210D49008191E3 /* SecurityFeatures.h */, + ); + name = iOS; + sourceTree = ""; + }; + EB73F03C1C210CF2008191E3 /* BUILT_PRODUCTS_DIR */ = { + isa = PBXGroup; + children = ( + EB73F0441C210DF8008191E3 /* SecurityFeatures.h */, + ); + name = BUILT_PRODUCTS_DIR; + sourceTree = BUILT_PRODUCTS_DIR; + }; + EB73F03D1C210CFE008191E3 /* OSX */ = { + isa = PBXGroup; + children = ( + EB73F03F1C210D58008191E3 /* SecurityFeatures.h */, + ); + name = OSX; + sourceTree = ""; + }; + EBB696D51BE2089400715F16 /* RegressionTests */ = { isa = PBXGroup; children = ( - EB93FF541BE088FC00978606 /* Security.plist */, - EB93FF521BE088E000978606 /* secbackupntest */, + EBB696FE1BE208BD00715F16 /* secbackupntest */, + EBB696FD1BE208BA00715F16 /* Security.plist */, ); name = RegressionTests; path = ../RegressionTests; sourceTree = ""; }; - EB93FF521BE088E000978606 /* secbackupntest */ = { + EBB696FE1BE208BD00715F16 /* secbackupntest */ = { isa = PBXGroup; children = ( - EB93FF531BE088F600978606 /* secbackupntest.m */, + EBB696FF1BE208CB00715F16 /* secbackupntest.m */, ); name = secbackupntest; sourceTree = ""; @@ -4175,6 +4239,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + EB73F0451C210E6F008191E3 /* SecurityFeatures.h in Headers */, CD8B5A9D1B618ED9004D4AEF /* SOSPeerInfoPriv.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4277,6 +4342,7 @@ 18FE68591471A46600A2CBE3 /* ocspTemplates.h in Headers */, 44B2606A18F81C0F008DF20F /* SecAccessControlPriv.h in Headers */, 18FE685A1471A46600A2CBE3 /* osKeyTemplates.h in Headers */, + 1FDA9ABC1C4489280083929D /* SecTranslocate.h in Headers */, 18FE685B1471A46600A2CBE3 /* SecAccessPriv.h in Headers */, 18FE685C1471A46600A2CBE3 /* secasn1t.h in Headers */, 18FE685D1471A46600A2CBE3 /* SecAssessment.h in Headers */, @@ -4286,6 +4352,7 @@ 18FE68621471A46600A2CBE3 /* SecCertificateRequest.h in Headers */, 18FE68631471A46600A2CBE3 /* SecCmsBase.h in Headers */, AC5688BC18B4396D00F0526C /* SecCMS.h in Headers */, + D47F51221C3B80DF00A7CEFE /* SecCFAllocator.h in Headers */, 18FE68641471A46600A2CBE3 /* SecCmsContentInfo.h in Headers */, 18FE68651471A46600A2CBE3 /* SecCmsDecoder.h in Headers */, 18FE68661471A46600A2CBE3 /* SecCmsDigestContext.h in Headers */, @@ -4322,6 +4389,7 @@ 18FE68831471A46700A2CBE3 /* SecRequirementPriv.h in Headers */, 18FE68841471A46700A2CBE3 /* SecSMIME.h in Headers */, 18FE68851471A46700A2CBE3 /* SecStaticCodePriv.h in Headers */, + D4D9B9FE1C7E5CCA008785EB /* SecServerEncryptionSupport.h in Headers */, 18FE68861471A46700A2CBE3 /* SecTransformInternal.h in Headers */, 18FE68871471A46700A2CBE3 /* SecTrustedApplicationPriv.h in Headers */, BEC3A76816F79497003E5634 /* SecTaskPriv.h in Headers */, @@ -4350,6 +4418,23 @@ }; /* End PBXHeadersBuildPhase section */ +/* Begin PBXLegacyTarget section */ + EBE011D31C21357200CB6A63 /* SecurityFeatures */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(PROJECT_DIR)/../SecurityFeatures/ExternalProject.sh $(ACTION)"; + buildConfigurationList = EBE011FE1C21357200CB6A63 /* Build configuration list for PBXLegacyTarget "SecurityFeatures" */; + buildPhases = ( + ); + buildToolPath = /bin/bash; + buildWorkingDirectory = "$(PROJECT_DIR)/../SecurityFeatures"; + dependencies = ( + ); + name = SecurityFeatures; + passBuildSettingsInEnvironment = 1; + productName = SecurityFeature; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ 0C6C630A15D193C800BC68CD /* sectests */ = { isa = PBXNativeTarget; @@ -4366,6 +4451,7 @@ ACB6173F18B5232700EBEDD7 /* PBXTargetDependency */, 0CBD50C716C3260D00713B6C /* PBXTargetDependency */, 0CCEBDB316C2CFD4001BD7F6 /* PBXTargetDependency */, + DC872EEA1CC983EE0076C0E7 /* PBXTargetDependency */, ); name = sectests; productName = sectests; @@ -4401,6 +4487,7 @@ isa = PBXNativeTarget; buildConfigurationList = 18073875146D0D4E00F05C24 /* Build configuration list for PBXNativeTarget "Security" */; buildPhases = ( + EB73F0431C210DA9008191E3 /* Copy Security Feature header */, 18073846146D0D4E00F05C24 /* Sources */, 18073847146D0D4E00F05C24 /* Frameworks */, 18073848146D0D4E00F05C24 /* Headers */, @@ -4414,12 +4501,15 @@ E778BFB91717461800302C14 /* PBXBuildRule */, ); dependencies = ( + 4C12894415FFED03008CE3E3 /* PBXTargetDependency */, + D46B08A81C8FD8D900B5939A /* PBXTargetDependency */, + EBE012011C21368400CB6A63 /* PBXTargetDependency */, 1879B545146DE18D007E536C /* PBXTargetDependency */, + 1FDA9A5F1C4471EC0083929D /* PBXTargetDependency */, + D46B08021C8FBE6A00B5939A /* PBXTargetDependency */, BE8D22951ABB747A009A4E18 /* PBXTargetDependency */, 4AD6F6F41651CC2500DB4CE6 /* PBXTargetDependency */, - 4C12894415FFED03008CE3E3 /* PBXTargetDependency */, 18FE688F1471A4C900A2CBE3 /* PBXTargetDependency */, - 1885B45114D9AB3D00519375 /* PBXTargetDependency */, 18270F5D14CF655B00B05E7F /* PBXTargetDependency */, 18AD56A614CDED59008233F2 /* PBXTargetDependency */, 182BB410146F248D000BF1F3 /* PBXTargetDependency */, @@ -4495,6 +4585,7 @@ ); dependencies = ( 182BB596146FE27F000BF1F3 /* PBXTargetDependency */, + DC311CC71CCEC81D00E14E8D /* PBXTargetDependency */, 182BB58F146FE11C000BF1F3 /* PBXTargetDependency */, 182BB58D146FE0FF000BF1F3 /* PBXTargetDependency */, 182BB588146FE001000BF1F3 /* PBXTargetDependency */, @@ -4531,6 +4622,7 @@ buildPhases = ( 18FE67E71471A3AA00A2CBE3 /* Headers */, 4CB86AE4167A6F3D00F46643 /* Copy SecureObjectSync Headers */, + 5E3BDC291CD20B4300C80B61 /* Unifdef RC_HIDE_J79/J80 */, ); buildRules = ( ); @@ -4648,26 +4740,6 @@ productReference = 4CC7A7B316CC2A84003E10C1 /* Cloud Keychain Utility.app */; productType = "com.apple.product-type.application"; }; - 5214700516977CB800DF0DB3 /* CloudKeychainProxy */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5214701416977CB800DF0DB3 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */; - buildPhases = ( - 5214700216977CB800DF0DB3 /* Sources */, - 5214700316977CB800DF0DB3 /* Frameworks */, - 5214700416977CB800DF0DB3 /* Resources */, - 5214702316977EA600DF0DB3 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - 5214701A16977D2500DF0DB3 /* PBXTargetDependency */, - 5214701816977D1D00DF0DB3 /* PBXTargetDependency */, - ); - name = CloudKeychainProxy; - productName = CloudKeychainProxy; - productReference = 5214700616977CB800DF0DB3 /* CloudKeychainProxy.bundle */; - productType = "com.apple.product-type.bundle"; - }; 5EF7C2091B00E25400E5E99C /* secacltests */ = { isa = PBXNativeTarget; buildConfigurationList = 5EF7C2381B00E25400E5E99C /* Build configuration list for PBXNativeTarget "secacltests" */; @@ -4679,7 +4751,6 @@ ); dependencies = ( 5ED88B701B0DEF4700F3B047 /* PBXTargetDependency */, - 5ED88B6E1B0DEF3100F3B047 /* PBXTargetDependency */, 5EFB69C21B0CBFC30095A36E /* PBXTargetDependency */, 5EE556971B01DA3E006F78F2 /* PBXTargetDependency */, 5EE556951B01DA33006F78F2 /* PBXTargetDependency */, @@ -4692,23 +4763,6 @@ productReference = 5EF7C20A1B00E25400E5E99C /* secacltests */; productType = "com.apple.product-type.tool"; }; - 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */ = { - isa = PBXNativeTarget; - buildConfigurationList = 72756C2F175D485D00F52070 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */; - buildPhases = ( - 72756BFA175D485D00F52070 /* Sources */, - 72756BFB175D485D00F52070 /* Frameworks */, - 72756BFC175D485D00F52070 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = cloud_keychain_diagnose; - productName = cloud_keychain_diagnose; - productReference = 72756BFE175D485D00F52070 /* cloud_keychain_diagnose */; - productType = "com.apple.product-type.tool"; - }; BE48ADF71ADF1DF4000836C1 /* trustd */ = { isa = PBXNativeTarget; buildConfigurationList = BE48AE1E1ADF1DF4000836C1 /* Build configuration list for PBXNativeTarget "trustd" */; @@ -4721,62 +4775,61 @@ buildRules = ( ); dependencies = ( + D45FC3E61C9E06BD00509CDA /* PBXTargetDependency */, + D45FC3E31C9E069000509CDA /* PBXTargetDependency */, BE48ADF81ADF1DF4000836C1 /* PBXTargetDependency */, - BE48AE001ADF1DF4000836C1 /* PBXTargetDependency */, - BE48ADFE1ADF1DF4000836C1 /* PBXTargetDependency */, - BE48ADFA1ADF1DF4000836C1 /* PBXTargetDependency */, BE48ADFC1ADF1DF4000836C1 /* PBXTargetDependency */, - BE48AE231ADF1E66000836C1 /* PBXTargetDependency */, ); name = trustd; productName = secd; productReference = BE48AE211ADF1DF4000836C1 /* trustd */; productType = "com.apple.product-type.tool"; }; - BE94B77E1AD83AF700A7216D /* trustd.xpc */ = { + D42FA8231C9B8D3C003E46A7 /* SecurityTestsOSX */ = { isa = PBXNativeTarget; - buildConfigurationList = BE94B7A11AD83AF700A7216D /* Build configuration list for PBXNativeTarget "trustd.xpc" */; + buildConfigurationList = D42FA8321C9B8D3D003E46A7 /* Build configuration list for PBXNativeTarget "SecurityTestsOSX" */; buildPhases = ( - BE94B7801AD83AF700A7216D /* Sources */, - BE94B7931AD83AF700A7216D /* Frameworks */, - BE94B79B1AD83AF700A7216D /* Copy sandbox profile */, - BE94B79F1AD83AF700A7216D /* Copy asl module */, + D42FA8201C9B8D3C003E46A7 /* Sources */, + D42FA8211C9B8D3C003E46A7 /* Frameworks */, + D42FA8221C9B8D3C003E46A7 /* Resources */, + D4D886F61CED070600DC7583 /* Copy DigiNotar Resources */, + D4D886F71CED070800DC7583 /* Copy DigiNotar-Entrust Resources */, + D4D886F81CED070A00DC7583 /* Copy DigiNotar-ok Resources */, + D4D886F91CED070C00DC7583 /* Copy DigicertMalaysia Resources */, ); buildRules = ( ); dependencies = ( - BE94B7E11AD8442600A7216D /* PBXTargetDependency */, - BE94B7E91AD8447B00A7216D /* PBXTargetDependency */, - BE94B7E71AD8446C00A7216D /* PBXTargetDependency */, - BE94B7EF1AD8453300A7216D /* PBXTargetDependency */, - BE94B7E51AD8446500A7216D /* PBXTargetDependency */, - BE94B7EB1AD8449300A7216D /* PBXTargetDependency */, - ); - name = trustd.xpc; - productName = security.auth; - productReference = BE94B7A41AD83AF700A7216D /* trustd.xpc */; - productType = "com.apple.product-type.bundle"; + D42FA83B1C9B8F94003E46A7 /* PBXTargetDependency */, + D42FA83D1C9B8F94003E46A7 /* PBXTargetDependency */, + D42FA83F1C9B8F94003E46A7 /* PBXTargetDependency */, + D42FA8371C9B8F77003E46A7 /* PBXTargetDependency */, + D42FA8391C9B8F7D003E46A7 /* PBXTargetDependency */, + D42FA8431C9B8FD0003E46A7 /* PBXTargetDependency */, + DC872F151CC983F70076C0E7 /* PBXTargetDependency */, + D42FA8411C9B8FA7003E46A7 /* PBXTargetDependency */, + ); + name = SecurityTestsOSX; + productName = SecurityTestsOSX; + productReference = D42FA8241C9B8D3C003E46A7 /* SecurityTestsOSX.app */; + productType = "com.apple.product-type.application"; }; - CD63ACDF1A8061FA001B5671 /* IDSKeychainSyncingProxy */ = { + EBB697031BE208FC00715F16 /* secbackupntest */ = { isa = PBXNativeTarget; - buildConfigurationList = CD63AD101A8061FA001B5671 /* Build configuration list for PBXNativeTarget "IDSKeychainSyncingProxy" */; + buildConfigurationList = EBB697081BE208FC00715F16 /* Build configuration list for PBXNativeTarget "secbackupntest" */; buildPhases = ( - CD63ACDC1A8061FA001B5671 /* Sources */, - CD63ACDD1A8061FA001B5671 /* Frameworks */, - CD63ACDE1A8061FA001B5671 /* Resources */, - CD63AD1D1A806552001B5671 /* CopyFiles */, - CDF91EF41AAE025C00E88CF7 /* CopyFiles */, + EBB697001BE208FC00715F16 /* Sources */, + EBB697011BE208FC00715F16 /* Frameworks */, + EBB697021BE208FC00715F16 /* CopyFiles */, ); buildRules = ( ); dependencies = ( - CD63AD141A8063B7001B5671 /* PBXTargetDependency */, - CD63AD121A8063AF001B5671 /* PBXTargetDependency */, ); - name = IDSKeychainSyncingProxy; - productName = IDSKeychainSyncingProxy; - productReference = CD63ACE01A8061FA001B5671 /* IDSKeychainSyncingProxy.bundle */; - productType = "com.apple.product-type.bundle"; + name = secbackupntest; + productName = secbackupntest; + productReference = EBB697041BE208FC00715F16 /* secbackupntest */; + productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ @@ -4784,7 +4837,7 @@ 18073841146D0D4E00F05C24 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; TargetAttributes = { 3705CAD11A896DE800402F75 = { CreatedOnToolsVersion = 7.0; @@ -4798,8 +4851,14 @@ 5EF7C2091B00E25400E5E99C = { CreatedOnToolsVersion = 7.0; }; - CD63ACDF1A8061FA001B5671 = { - CreatedOnToolsVersion = 7.0; + D42FA8231C9B8D3C003E46A7 = { + CreatedOnToolsVersion = 8.0; + }; + EBB697031BE208FC00715F16 = { + CreatedOnToolsVersion = 7.2; + }; + EBE011D31C21357200CB6A63 = { + CreatedOnToolsVersion = 7.2; }; F93C49311AB8FD350047E01A = { CreatedOnToolsVersion = 6.3; @@ -4930,6 +4989,10 @@ ProductGroup = 1879B72C146DE844007E536C /* Products */; ProjectRef = 1879B72B146DE844007E536C /* libsecurity_transform.xcodeproj */; }, + { + ProductGroup = 1F6FC5E01C3D9D90001C758F /* Products */; + ProjectRef = 1F6FC5DF1C3D9D90001C758F /* libsecurity_translocate.xcodeproj */; + }, { ProductGroup = 1879B533146DDBE5007E536C /* Products */; ProjectRef = 1879B532146DDBE5007E536C /* libsecurity_utilities.xcodeproj */; @@ -4946,10 +5009,6 @@ ProductGroup = 186CDD1714CA11C700AF9171 /* Products */; ProjectRef = 186CDD1614CA11C700AF9171 /* sec.xcodeproj */; }, - { - ProductGroup = 0C6D77DF15C8C06500BB4405 /* Products */; - ProjectRef = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; - }, { ProductGroup = 4C12893815FFECF3008CE3E3 /* Products */; ProjectRef = 4C12893715FFECF3008CE3E3 /* utilities.xcodeproj */; @@ -4959,29 +5018,26 @@ targets = ( 186F778814E59FB200434E1F /* Security_frameworks */, 186F778C14E59FDA00434E1F /* Security_executables */, - 0C6C642915D5ADB500BC68CD /* Security_kexts */, - 182BB598146FE295000BF1F3 /* World */, + 4CE4729E16D833FD009070D1 /* Security_temporary_UI */, 1807384A146D0D4E00F05C24 /* Security */, 182BB567146F4DCA000BF1F3 /* csparser */, 18FE67E91471A3AA00A2CBE3 /* copyHeaders */, 18270ED514CF282600B05E7F /* secd */, 0CC3350716C1ED8000399E53 /* secdtests */, + D42FA8231C9B8D3C003E46A7 /* SecurityTestsOSX */, 0C6C630A15D193C800BC68CD /* sectests */, 18F234EA15C9F9A600060520 /* authd */, - BE94B77E1AD83AF700A7216D /* trustd.xpc */, BE48ADF71ADF1DF4000836C1 /* trustd */, - 5214700516977CB800DF0DB3 /* CloudKeychainProxy */, - CD63ACDF1A8061FA001B5671 /* IDSKeychainSyncingProxy */, 4CB23B45169F5873003A0131 /* security2 */, 4CC7A7B216CC2A84003E10C1 /* Cloud Keychain Utility */, 4C96F7C016D6DF8300D3B39D /* Keychain Circle Notification */, - 4CE4729E16D833FD009070D1 /* Security_temporary_UI */, - 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */, 37A7CEAA197DB8FA00926CE8 /* codesign_tests */, 37AB390E1A44A88000B56E04 /* gk_reset_check */, 3705CAD11A896DE800402F75 /* SecTaskTest */, F93C49311AB8FD350047E01A /* ckcdiagnose.sh */, 5EF7C2091B00E25400E5E99C /* secacltests */, + EBB697031BE208FC00715F16 /* secbackupntest */, + EBE011D31C21357200CB6A63 /* SecurityFeatures */, ); }; /* End PBXProject section */ @@ -5015,20 +5071,6 @@ remoteRef = 0C6D77D215C8B66000BB4405 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 0C6D77EB15C8C06600BB4405 /* tlsnketest */ = { - isa = PBXReferenceProxy; - fileType = "compiled.mach-o.executable"; - path = tlsnketest; - remoteRef = 0C6D77EA15C8C06600BB4405 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 0C6D77ED15C8C06600BB4405 /* libtlssocket.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libtlssocket.a; - remoteRef = 0C6D77EC15C8C06600BB4405 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 0CBD50B316C325F000713B6C /* libsecurity_keychain_regressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -5372,10 +5414,10 @@ remoteRef = 1879B738146DE845007E536C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 1879B73D146DE845007E536C /* unit-tests.octest */ = { + 1879B73D146DE845007E536C /* unit-tests.xctest */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; - path = "unit-tests.octest"; + path = "unit-tests.xctest"; remoteRef = 1879B73C146DE845007E536C /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -5407,11 +5449,11 @@ remoteRef = 18D4053A14CE2C1600A2BE4E /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 4C01DE32164C3793006798CD /* libCloudKeychainProxy.a */ = { + 1F6FC6001C3D9D90001C758F /* libsecurity_translocate.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libCloudKeychainProxy.a; - remoteRef = 4C01DE31164C3793006798CD /* PBXContainerItemProxy */; + path = libsecurity_translocate.a; + remoteRef = 1F6FC5FF1C3D9D90001C758F /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 4C1288EA15FFE9D7008CE3E3 /* libSecureObjectSync.a */ = { @@ -5512,11 +5554,11 @@ remoteRef = C2432A0715C7112A0096DB5B /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - CD63AD0C1A8061FA001B5671 /* libIDSKeychainSyncingProxy.a */ = { + D40772181C9B52210016AA66 /* libSharedRegressions.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libIDSKeychainSyncingProxy.a; - remoteRef = CD63AD0B1A8061FA001B5671 /* PBXContainerItemProxy */; + path = libSharedRegressions.a; + remoteRef = D40772171C9B52210016AA66 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */ = { @@ -5526,13 +5568,6 @@ remoteRef = D4CBC1271BE981DE00C5795E /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - E7421C7E1ADC8E0D005FC1C0 /* tlsnke.kext */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = tlsnke.kext; - remoteRef = E7421C7D1ADC8E0D005FC1C0 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; E760796F1951F99600F69731 /* libSWCAgent.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -5587,7 +5622,6 @@ 188AD8DD1471FE3E0081C619 /* InfoPlist.strings in Resources */, 52B006C015238F76005D4556 /* TimeStampingPrefs.plist in Resources */, 187D6B9315D435BD00E27494 /* authorization.buttons.strings in Resources */, - BEFB63691B6834AB0052149A /* AppWorkaround.plist in Resources */, 187D6B9415D435C700E27494 /* authorization.prompts.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -5621,23 +5655,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5214700416977CB800DF0DB3 /* Resources */ = { + D42FA8221C9B8D3C003E46A7 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - CDAE4BC21A86F6FF0000AA84 /* cloudkeychain.entitlements.plist in Resources */, - 5214701216977CB800DF0DB3 /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD63ACDE1A8061FA001B5671 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CDB22CE31A9D2EA70043E348 /* IDSKeychainSyncingProxy-Info.plist in Resources */, - CDAE4B9A1A86F6F20000AA84 /* idskeychainsyncingproxy.entitlements.plist in Resources */, - CDF91EC91AAE022600E88CF7 /* com.apple.private.alloy.keychainsync.plist in Resources */, - CD276BE41A83F204003226BC /* InfoPlist.strings in Resources */, + D4D886F31CED01F800DC7583 /* nist-certs in Resources */, + D4D886C41CEBDBEB00DC7583 /* ssl-policy-certs in Resources */, + D4EC94D61CEA48000083E753 /* si-20-sectrust-policies-data in Resources */, + 0C0C887D1CCED19E00617D1B /* si-82-sectrust-ct-data in Resources */, + D42FA87D1C9B9186003E46A7 /* si-82-sectrust-ct-logs.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5670,7 +5696,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "DST=${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/XPCServices\n\nXPC_SERVICE=XPCKeychainSandboxCheck.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\nif [ $0 -ne 0 ]; then\n\texit $0;\nfi\n\nif [ ! -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"; + 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"; showEnvVarsInLog = 0; }; 18500F961470828E006F9AB4 /* Run Script Generate Strings */ = { @@ -5679,29 +5705,57 @@ files = ( ); inputPaths = ( + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/Authorization.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/AuthSession.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecureTransport.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecBase.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmerr.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmapple.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/Headers/CSCommon.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/AuthorizationPriv.h", + "${PROJECT_DIR}/libsecurity_keychain/lib/MacOSErrorStrings.h", + "${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/SecureTransportPriv.h", ); name = "Run Script Generate Strings"; outputPaths = ( + "${BUILT_PRODUCTS_DIR}/derived_src/SecDebugErrorMessages.strings", + "${BUILT_PRODUCTS_DIR}/derived_src/en.lproj/SecErrorMessages.strings", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "DERIVED_SRC=${BUILT_PRODUCTS_DIR}/derived_src\nmkdir -p ${DERIVED_SRC}\n\n# make error message string files\n\nGENDEBUGSTRS[0]=YES; ERRORSTRINGS[0]=${DERIVED_SRC}/SecDebugErrorMessages.strings\nGENDEBUGSTRS[1]=NO ; ERRORSTRINGS[1]=${DERIVED_SRC}/en.lproj/SecErrorMessages.strings\n\nmkdir -p ${DERIVED_SRC}/en.lproj\n\nfor ((ix=0;ix<2;ix++)) ; do\nperl lib/generateErrStrings.pl \\\n${GENDEBUGSTRS[ix]} \\\n${DERIVED_SRC} \\\n${ERRORSTRINGS[ix]} \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/Authorization.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/AuthSession.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecureTransport.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/SecBase.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmerr.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/cssmapple.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/Headers/CSCommon.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/AuthorizationPriv.h \\\n${PROJECT_DIR}/libsecurity_keychain/lib/MacOSErrorStrings.h \\\n${BUILT_PRODUCTS_DIR}/Security.framework/PrivateHeaders/SecureTransportPriv.h\ndone"; showEnvVarsInLog = 0; }; - 18F2360315CB30EC00060520 /* ShellScript */ = { + 5E3BDC291CD20B4300C80B61 /* Unifdef RC_HIDE_J79/J80 */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); + name = "Unifdef RC_HIDE_J79/J80"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "DST=${BUILT_PRODUCTS_DIR}/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices\n\nXPC_SERVICE=authd.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\n\nXPC_SERVICE=trustd.xpc\nditto -v ${BUILT_PRODUCTS_DIR}/${XPC_SERVICE} ${DST}/${XPC_SERVICE}\n\nexit 0"; + shellScript = "if [ -d $DSTROOT ]; then\n RC_HIDE_J79_VAL=0\n RC_HIDE_J80_VAL=0\n SEC_HDRS_PATH=\"System/Library/Frameworks/Security.framework/Headers\"\n\n if [ ! -z $RC_HIDE_J79 ]; then\n RC_HIDE_J79_VAL=1\n fi\n\n if [ ! -z $RC_HIDE_J80 ]; then\n RC_HIDE_J80_VAL=1\n fi\n\n if [ -a $DSTROOT/$SEC_HDRS_PATH/SecAccessControl.h ]; then\n unifdef -B -DRC_HIDE_J79=$RC_HIDE_J79_VAL -DRC_HIDE_J80=$RC_HIDE_J80_VAL -o $DSTROOT/$SEC_HDRS_PATH/SecAccessControl.h $DSTROOT/$SEC_HDRS_PATH/SecAccessControl.h\n if [$? eq 2]; then\n exit 2\n fi\n fi\n\n if [ -a $DSTROOT/$SEC_HDRS_PATH/SecItem.h ]; then\n unifdef -B -DRC_HIDE_J79=$RC_HIDE_J79_VAL -DRC_HIDE_J80=$RC_HIDE_J80_VAL -o $DSTROOT/$SEC_HDRS_PATH/SecItem.h $DSTROOT/$SEC_HDRS_PATH/SecItem.h\n if [$? eq 2]; then\n exit 2\n fi\n fi\n\n exit 0\nfi"; showEnvVarsInLog = 0; }; + EB73F0431C210DA9008191E3 /* Copy Security Feature header */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Security Feature header"; + outputPaths = ( + "$(BUILT_PRODUCTS_DIR)/include/Security/SecurityFeatures.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "sh ${PROJECT_DIR}/../SecurityFeatures/CopyHeaders.sh OSX"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -5710,7 +5764,7 @@ buildActionMask = 2147483647; files = ( 0CCEBDB116C2CFC1001BD7F6 /* main.c in Sources */, - EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.c in Sources */, + EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5834,14 +5888,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5214700216977CB800DF0DB3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 52C3D236169B56860091D9D3 /* ckdmain.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 5EF7C2061B00E25400E5E99C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -5851,14 +5897,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 72756BFA175D485D00F52070 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 72756C31175D48C100F52070 /* cloud_keychain_diagnose.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; BE48AE021ADF1DF4000836C1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -5867,19 +5905,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - BE94B7801AD83AF700A7216D /* Sources */ = { + D42FA8201C9B8D3C003E46A7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BE94B7CD1AD83B9900A7216D /* server.c in Sources */, + D42FA82B1C9B8D3D003E46A7 /* main.m in Sources */, + D42FA8EA1C9BAA44003E46A7 /* bc-10-knife-on-bread.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - CD63ACDC1A8061FA001B5671 /* Sources */ = { + EBB697001BE208FC00715F16 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CD63AD161A8064C2001B5671 /* idksmain.m in Sources */, + EBB6970F1BE209D400715F16 /* secbackupntest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6136,16 +6175,6 @@ target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; targetProxy = 186F779614E5A04200434E1F /* PBXContainerItemProxy */; }; - 186F779914E5A06500434E1F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 186F778814E59FB200434E1F /* Security_frameworks */; - targetProxy = 186F779814E5A06500434E1F /* PBXContainerItemProxy */; - }; - 186F779B14E5A06800434E1F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 186F778C14E59FDA00434E1F /* Security_executables */; - targetProxy = 186F779A14E5A06800434E1F /* PBXContainerItemProxy */; - }; 1879B545146DE18D007E536C /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libsecurity_utilities; @@ -6161,11 +6190,6 @@ name = libsecurity_cssm; targetProxy = 1879B56D146DE2D3007E536C /* PBXContainerItemProxy */; }; - 1885B45114D9AB3D00519375 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libASN1; - targetProxy = 1885B45014D9AB3D00519375 /* PBXContainerItemProxy */; - }; 18AD56A614CDED59008233F2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = sec; @@ -6186,6 +6210,11 @@ target = 18FE67E91471A3AA00A2CBE3 /* copyHeaders */; targetProxy = 18FE688E1471A4C900A2CBE3 /* PBXContainerItemProxy */; }; + 1FDA9A5F1C4471EC0083929D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_translocate; + targetProxy = 1FDA9A5E1C4471EC0083929D /* PBXContainerItemProxy */; + }; 3705CADE1A8971DF00402F75 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 3705CAD11A896DE800402F75 /* SecTaskTest */; @@ -6271,26 +6300,6 @@ name = libSecureObjectSync; targetProxy = 5208C0FD16A0D3980062DDC5 /* PBXContainerItemProxy */; }; - 5214701816977D1D00DF0DB3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = utilities; - targetProxy = 5214701716977D1D00DF0DB3 /* PBXContainerItemProxy */; - }; - 5214701A16977D2500DF0DB3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libCloudKeychainProxy; - targetProxy = 5214701916977D2500DF0DB3 /* PBXContainerItemProxy */; - }; - 521470291697842500DF0DB3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 5214700516977CB800DF0DB3 /* CloudKeychainProxy */; - targetProxy = 521470281697842500DF0DB3 /* PBXContainerItemProxy */; - }; - 5ED88B6E1B0DEF3100F3B047 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libDER; - targetProxy = 5ED88B6D1B0DEF3100F3B047 /* PBXContainerItemProxy */; - }; 5ED88B701B0DEF4700F3B047 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libsecipc_client; @@ -6331,11 +6340,6 @@ name = libSecItemShimOSX; targetProxy = 5EFB69C11B0CBFC30095A36E /* PBXContainerItemProxy */; }; - 722CF218175D602F00BCE0A5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 72756BFD175D485D00F52070 /* cloud_keychain_diagnose */; - targetProxy = 722CF217175D602F00BCE0A5 /* PBXContainerItemProxy */; - }; ACB6173F18B5232700EBEDD7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libsecurity_smime_regressions; @@ -6346,31 +6350,11 @@ name = libsecipc_client; targetProxy = BE48ADF91ADF1DF4000836C1 /* PBXContainerItemProxy */; }; - BE48ADFA1ADF1DF4000836C1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libSecureObjectSync; - targetProxy = BE48ADFB1ADF1DF4000836C1 /* PBXContainerItemProxy */; - }; BE48ADFC1ADF1DF4000836C1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = utilities; targetProxy = BE48ADFD1ADF1DF4000836C1 /* PBXContainerItemProxy */; }; - BE48ADFE1ADF1DF4000836C1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurityd; - targetProxy = BE48ADFF1ADF1DF4000836C1 /* PBXContainerItemProxy */; - }; - BE48AE001ADF1DF4000836C1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity; - targetProxy = BE48AE011ADF1DF4000836C1 /* PBXContainerItemProxy */; - }; - BE48AE231ADF1E66000836C1 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libSecTrustOSX; - targetProxy = BE48AE221ADF1E66000836C1 /* PBXContainerItemProxy */; - }; BE48AE291ADF204E000836C1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BE48ADF71ADF1DF4000836C1 /* trustd */; @@ -6381,55 +6365,70 @@ name = libSecTrustOSX; targetProxy = BE8D22941ABB747A009A4E18 /* PBXContainerItemProxy */; }; - BE94B7E11AD8442600A7216D /* PBXTargetDependency */ = { + C2432A2515C726B50096DB5B /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecipc_client; - targetProxy = BE94B7E01AD8442600A7216D /* PBXContainerItemProxy */; - }; - BE94B7E51AD8446500A7216D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = utilities; - targetProxy = BE94B7E41AD8446500A7216D /* PBXContainerItemProxy */; + name = gkunpack; + targetProxy = C2432A2415C726B50096DB5B /* PBXContainerItemProxy */; }; - BE94B7E71AD8446C00A7216D /* PBXTargetDependency */ = { + D42FA8371C9B8F77003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurityd; - targetProxy = BE94B7E61AD8446C00A7216D /* PBXContainerItemProxy */; + name = libsecurity_cms_regressions; + targetProxy = D42FA8361C9B8F77003E46A7 /* PBXContainerItemProxy */; }; - BE94B7E91AD8447B00A7216D /* PBXTargetDependency */ = { + D42FA8391C9B8F7D003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libsecurity; - targetProxy = BE94B7E81AD8447B00A7216D /* PBXContainerItemProxy */; + name = regressions; + targetProxy = D42FA8381C9B8F7D003E46A7 /* PBXContainerItemProxy */; }; - BE94B7EB1AD8449300A7216D /* PBXTargetDependency */ = { + D42FA83B1C9B8F94003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecTrustOSX; - targetProxy = BE94B7EA1AD8449300A7216D /* PBXContainerItemProxy */; + name = libsecurity_keychain_regressions; + targetProxy = D42FA83A1C9B8F94003E46A7 /* PBXContainerItemProxy */; }; - BE94B7EF1AD8453300A7216D /* PBXTargetDependency */ = { + D42FA83D1C9B8F94003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libSecureObjectSync; - targetProxy = BE94B7EE1AD8453300A7216D /* PBXContainerItemProxy */; + name = libsecurity_ssl_regressions; + targetProxy = D42FA83C1C9B8F94003E46A7 /* PBXContainerItemProxy */; }; - C2432A2515C726B50096DB5B /* PBXTargetDependency */ = { + D42FA83F1C9B8F94003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = gkunpack; - targetProxy = C2432A2415C726B50096DB5B /* PBXContainerItemProxy */; + name = libsecurity_smime_regressions; + targetProxy = D42FA83E1C9B8F94003E46A7 /* PBXContainerItemProxy */; }; - CD63AD121A8063AF001B5671 /* PBXTargetDependency */ = { + D42FA8411C9B8FA7003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = libIDSKeychainSyncingProxy; - targetProxy = CD63AD111A8063AF001B5671 /* PBXContainerItemProxy */; + name = libSharedRegressions; + targetProxy = D42FA8401C9B8FA7003E46A7 /* PBXContainerItemProxy */; }; - CD63AD141A8063B7001B5671 /* PBXTargetDependency */ = { + D42FA8431C9B8FD0003E46A7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = utilities; - targetProxy = CD63AD131A8063B7001B5671 /* PBXContainerItemProxy */; + targetProxy = D42FA8421C9B8FD0003E46A7 /* PBXContainerItemProxy */; }; - CDEB2BD21A8151CD00B0E23A /* PBXTargetDependency */ = { + D45FC3E31C9E069000509CDA /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = CD63ACDF1A8061FA001B5671 /* IDSKeychainSyncingProxy */; - targetProxy = CDEB2BD11A8151CD00B0E23A /* PBXContainerItemProxy */; + name = libsecurityd; + targetProxy = D45FC3E21C9E069000509CDA /* PBXContainerItemProxy */; + }; + D45FC3E61C9E06BD00509CDA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libSecureObjectSync; + targetProxy = D45FC3E51C9E06BD00509CDA /* PBXContainerItemProxy */; + }; + D466FA771CA0C2A500433142 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D42FA8231C9B8D3C003E46A7 /* SecurityTestsOSX */; + targetProxy = D466FA761CA0C2A500433142 /* PBXContainerItemProxy */; + }; + D46B08021C8FBE6A00B5939A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libDERInstall; + targetProxy = D46B08011C8FBE6A00B5939A /* PBXContainerItemProxy */; + }; + D46B08A81C8FD8D900B5939A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libASN1Install; + targetProxy = D46B08A71C8FD8D900B5939A /* PBXContainerItemProxy */; }; D4A2FC7E1BC89D5200BF6E56 /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -6441,16 +6440,41 @@ name = libsecurity_cms_regressions; targetProxy = D4CBC1191BE981DE00C5795E /* PBXContainerItemProxy */; }; + DC311CC71CCEC81D00E14E8D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = utilities; + targetProxy = DC311CC61CCEC81D00E14E8D /* PBXContainerItemProxy */; + }; + DC872EEA1CC983EE0076C0E7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libDER; + targetProxy = DC872EE91CC983EE0076C0E7 /* PBXContainerItemProxy */; + }; + DC872F151CC983F70076C0E7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libDER; + targetProxy = DC872F141CC983F70076C0E7 /* PBXContainerItemProxy */; + }; E76079FA1951FDF600F69731 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = liblogging; targetProxy = E76079F91951FDF600F69731 /* PBXContainerItemProxy */; }; + EBB6970E1BE2095F00715F16 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EBB697031BE208FC00715F16 /* secbackupntest */; + targetProxy = EBB6970D1BE2095F00715F16 /* PBXContainerItemProxy */; + }; EBB9FFE01682E71F00FF9774 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = CodeSigningHelper; targetProxy = EBB9FFDF1682E71F00FF9774 /* PBXContainerItemProxy */; }; + EBE012011C21368400CB6A63 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EBE011D31C21357200CB6A63 /* SecurityFeatures */; + targetProxy = EBE012001C21368400CB6A63 /* PBXContainerItemProxy */; + }; F94E7A971ACC8CC200F23132 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = F93C49311AB8FD350047E01A /* ckcdiagnose.sh */; @@ -6558,14 +6582,6 @@ name = MainMenu.xib; sourceTree = ""; }; - 5214701016977CB800DF0DB3 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 5214701116977CB800DF0DB3 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; 5328475117850741009118DC /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( @@ -6589,13 +6605,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; CODE_SIGN_ENTITLEMENTS = "sectests/SecurityTests-Entitlements.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", /usr/lib/system, ); OTHER_LDFLAGS = "-t"; - VALID_ARCHS = x86_64; }; name = Debug; }; @@ -6603,27 +6619,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; CODE_SIGN_ENTITLEMENTS = "sectests/SecurityTests-Entitlements.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", /usr/lib/system, ); OTHER_LDFLAGS = "-t"; - VALID_ARCHS = x86_64; - }; - name = Release; - }; - 0C6C642B15D5ADB500BC68CD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 0C6C642C15D5ADB500BC68CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; @@ -6631,11 +6633,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/sec", "$(PROJECT_DIR)/utilities", + "$(PROJECT_DIR)", ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -6649,7 +6654,6 @@ AppleSystemInfo, ); PRODUCT_NAME = secdtests; - VALID_ARCHS = x86_64; }; name = Debug; }; @@ -6657,11 +6661,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; HEADER_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/sec", "$(PROJECT_DIR)/utilities", + "$(PROJECT_DIR)", ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", @@ -6675,7 +6682,6 @@ AppleSystemInfo, ); PRODUCT_NAME = secdtests; - VALID_ARCHS = x86_64; }; name = Release; }; @@ -6683,6 +6689,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = 181EA423146D4A2A00A6D320 /* debug.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + ENABLE_TESTABILITY = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx.internal; }; name = Debug; }; @@ -6690,6 +6701,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 181EA425146D4A2A00A6D320 /* release.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + SDKROOT = macosx.internal; }; name = Release; }; @@ -6698,15 +6712,23 @@ baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; INFOPLIST_FILE = "lib/Info-Security.plist"; + INSTALLHDRS_SCRIPT_PHASE = YES; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", /usr/lib/system, ); - OTHER_LDFLAGS = "-laks"; - "OTHER_LDFLAGS[sdk=*simulator*]" = ""; + MODULEMAP_FILE = Modules/Security.macOS.modulemap; + OTHER_LDFLAGS = ( + "-Wl,-upward-lcoretls", + "-Wl,-upward-lcoretls_cfhelpers", + "-laks", + "-lCrashReporterClient", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security; }; name = Debug; }; @@ -6715,16 +6737,24 @@ baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + DEFINES_MODULE = YES; EXPORTED_SYMBOLS_FILE = "$(BUILT_PRODUCTS_DIR)/$(TARGETNAME).$(CURRENT_ARCH).exp"; INFOPLIST_FILE = "lib/Info-Security.plist"; + INSTALLHDRS_SCRIPT_PHASE = YES; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", /usr/lib/system, ); + MODULEMAP_FILE = Modules/Security.macOS.modulemap; ORDER_FILE = lib/Security.order; - OTHER_LDFLAGS = "-laks"; - "OTHER_LDFLAGS[sdk=*simulator*]" = ""; + OTHER_LDFLAGS = ( + "-Wl,-upward-lcoretls", + "-Wl,-upward-lcoretls_cfhelpers", + "-laks", + "-lCrashReporterClient", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security; SECTORDER_FLAGS = "-order_file_statistics"; }; name = Release; @@ -6733,10 +6763,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "SECITEM_SHIM_OSX=1", - "SECTRUST_OSX=0", + "SECTRUST_OSX=1", "$(inherited)", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -6759,7 +6794,6 @@ AppleSystemInfo, ); USE_HEADERMAP = NO; - VALID_ARCHS = x86_64; }; name = Debug; }; @@ -6767,10 +6801,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; CODE_SIGN_ENTITLEMENTS = sec/securityd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "SECITEM_SHIM_OSX=1", - "SECTRUST_OSX=0", + "SECTRUST_OSX=1", "$(inherited)", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -6793,7 +6832,6 @@ AppleSystemInfo, ); USE_HEADERMAP = NO; - VALID_ARCHS = x86_64; }; name = Release; }; @@ -6806,6 +6844,7 @@ INFOPLIST_FILE = "lib/plugins/csparser-Info.plist"; INSTALLHDRS_SCRIPT_PHASE = NO; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/PlugIns"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.csparser; WRAPPER_EXTENSION = bundle; }; name = Debug; @@ -6819,24 +6858,11 @@ INFOPLIST_FILE = "lib/plugins/csparser-Info.plist"; INSTALLHDRS_SCRIPT_PHASE = NO; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/PlugIns"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.csparser; WRAPPER_EXTENSION = bundle; }; name = Release; }; - 182BB59A146FE295000BF1F3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 182BB59B146FE295000BF1F3 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; 186F778A14E59FB200434E1F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -6896,9 +6922,10 @@ INFOPLIST_FILE = authd/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; MACH_O_TYPE = mh_execute; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; RUN_CLANG_STATIC_ANALYZER = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; WRAPPER_EXTENSION = xpc; }; name = Debug; @@ -6934,8 +6961,9 @@ INFOPLIST_FILE = authd/Info.plist; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; MACH_O_TYPE = mh_execute; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; WRAPPER_EXTENSION = xpc; }; name = Release; @@ -6969,7 +6997,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -7013,7 +7040,6 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -7200,7 +7226,6 @@ 4C96F7D616D6DF8400D3B39D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -7215,8 +7240,8 @@ COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/System/Library/PrivateFrameworks", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -7233,17 +7258,19 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/System/Library/Frameworks/Security.framework/PrivateHeaders", - "$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders", + "$(PROJECT_DIR)/Keychain", + Circle, + Notification, + "$(PROJECT_DIR)/sec/ProjectHeaders", + "$(PROJECT_DIR)/utilities", "$(PROJECT_DIR)/sec", + "$(inherited)", ); INFOPLIST_FILE = "Keychain Circle Notification/Keychain Circle Notification-Info.plist"; INSTALL_PATH = /System/Library/CoreServices; ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; WRAPPER_EXTENSION = app; }; name = Debug; @@ -7251,7 +7278,6 @@ 4C96F7D716D6DF8400D3B39D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -7268,8 +7294,8 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/System/Library/PrivateFrameworks", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -7279,16 +7305,18 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/System/Library/Frameworks/Security.framework/PrivateHeaders", - "$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders", + "$(PROJECT_DIR)/Keychain", + Circle, + Notification, + "$(PROJECT_DIR)/sec/ProjectHeaders", + "$(PROJECT_DIR)/utilities", "$(PROJECT_DIR)/sec", + "$(inherited)", ); INFOPLIST_FILE = "Keychain Circle Notification/Keychain Circle Notification-Info.plist"; INSTALL_PATH = /System/Library/CoreServices; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; WRAPPER_EXTENSION = app; }; name = Release; @@ -7337,8 +7365,7 @@ COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -7355,17 +7382,16 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/System/Library/Frameworks/Security.framework/PrivateHeaders", - "$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders", + "$(PROJECT_DIR)/sec/ProjectHeaders", + "$(PROJECT_DIR)/utilities", "$(PROJECT_DIR)/sec", + "$(inherited)", ); INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; INSTALL_PATH = /AppleInternal/Applications; ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; WRAPPER_EXTENSION = app; }; name = Debug; @@ -7391,8 +7417,7 @@ ENABLE_NS_ASSERTIONS = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", - "$(SDKROOT)/System/Library/PrivateFrameworks", - "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -7402,16 +7427,15 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SDKROOT)/System/Library/Frameworks/Security.framework/PrivateHeaders", - "$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework/PrivateHeaders", + "$(PROJECT_DIR)/sec/ProjectHeaders", + "$(PROJECT_DIR)/utilities", "$(PROJECT_DIR)/sec", + "$(inherited)", ); INFOPLIST_FILE = "Keychain/Keychain-Info.plist"; INSTALL_PATH = /AppleInternal/Applications; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - VALID_ARCHS = x86_64; WRAPPER_EXTENSION = app; }; name = Release; @@ -7430,103 +7454,11 @@ }; name = Release; }; - 5214701516977CB800DF0DB3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = CloudKeychainProxy/cloudkeychain.entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - "$(SDKROOT)/System/Library/Frameworks", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; - INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; - MACH_O_TYPE = mh_execute; - ONLY_ACTIVE_ARCH = YES; - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(inherited)", - "-framework", - MobileKeyBag, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - VALID_ARCHS = "armv6 armv7 x86_64"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - 5214701616977CB800DF0DB3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_ENTITLEMENTS = CloudKeychainProxy/cloudkeychain.entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - "$(SDKROOT)/System/Library/Frameworks", - ); - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "CloudKeychainProxy/CloudKeychainProxy-Info.plist"; - INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; - MACH_O_TYPE = mh_execute; - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(inherited)", - "-framework", - MobileKeyBag, - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - VALID_ARCHS = "armv6 armv7 x86_64"; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; 5EF7C20E1B00E25400E5E99C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = "../secacltests/secacltests-entitlements.plist"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -7550,7 +7482,6 @@ "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); PRODUCT_NAME = "$(TARGET_NAME)"; - VALID_ARCHS = x86_64; }; name = Debug; }; @@ -7558,6 +7489,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = "../secacltests/secacltests-entitlements.plist"; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -7576,94 +7508,23 @@ "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", ); PRODUCT_NAME = "$(TARGET_NAME)"; - VALID_ARCHS = x86_64; }; name = Release; }; - 72756C07175D485D00F52070 /* Debug */ = { + BE48AE1F1ADF1DF4000836C1 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4CB23B91169F5CFF003A0131 /* command.xcconfig */; + baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PRECOMPILE_PREFIX_HEADER = NO; + CODE_SIGN_ENTITLEMENTS = trustd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = "-laks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 72756C08175D485D00F52070 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4CB23B91169F5CFF003A0131 /* command.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - 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__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PRECOMPILE_PREFIX_HEADER = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - OTHER_LDFLAGS = "-laks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - BE48AE1F1ADF1DF4000836C1 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = ( - "SECITEM_SHIM_OSX=1", - "SECTRUST_OSX=0", - "TRUSTD_SERVER=1", + "SECITEM_SHIM_OSX=1", + "SECTRUST_OSX=1", + "TRUSTD_SERVER=1", "$(inherited)", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -7675,9 +7536,10 @@ "$(PROJECT_DIR)/utilities", "$(PROJECT_DIR)", "$(PROJECT_DIR)/../ios/asn1", - "$(PROJECT_DIR)/../libsecurity_keychain/libDER", + "$(PROJECT_DIR)/libsecurity_keychain/libDER", "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", "$(inherited)", + "$(PROJECT_DIR)/trustd/", ); INSTALL_PATH = /usr/libexec; "OTHER_LDFLAGS[sdk=macosx*]" = ( @@ -7687,7 +7549,6 @@ ); PRODUCT_NAME = trustd; USE_HEADERMAP = NO; - VALID_ARCHS = x86_64; }; name = Debug; }; @@ -7695,9 +7556,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18BBC6801471EF1600F2B224 /* security.xcconfig */; buildSettings = { + ARCHS = "$(ARCHS_STANDARD)"; + CODE_SIGN_ENTITLEMENTS = trustd/entitlements.plist; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_PREPROCESSOR_DEFINITIONS = ( "SECITEM_SHIM_OSX=1", - "SECTRUST_OSX=0", + "SECTRUST_OSX=1", "TRUSTD_SERVER=1", "$(inherited)", ); @@ -7710,9 +7577,10 @@ "$(PROJECT_DIR)/utilities", "$(PROJECT_DIR)", "$(PROJECT_DIR)/../ios/asn1", - "$(PROJECT_DIR)/../libsecurity_keychain/libDER", + "$(PROJECT_DIR)/libsecurity_keychain/libDER", "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", "$(inherited)", + "$(PROJECT_DIR)/trustd/", ); INSTALL_PATH = /usr/libexec; "OTHER_LDFLAGS[sdk=macosx*]" = ( @@ -7722,229 +7590,213 @@ ); PRODUCT_NAME = trustd; USE_HEADERMAP = NO; - VALID_ARCHS = x86_64; }; name = Release; }; - BE94B7A21AD83AF700A7216D /* Debug */ = { + D42FA8331C9B8D3D003E46A7 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = "SecurityTestsOSX/SecurityTests-Entitlements.plist"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = SecurityTestsOSX/Info.plist; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security/; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_LDFLAGS = "-t"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SecurityTestsOSX; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D42FA8341C9B8D3D003E46A7 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C6C632F15D19DE600BC68CD /* test.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CODE_SIGN_ENTITLEMENTS = "SecurityTestsOSX/SecurityTests-Entitlements.plist"; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = SecurityTestsOSX/Info.plist; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security/; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + /usr/lib/system, + ); + OTHER_LDFLAGS = "-t"; + PRODUCT_BUNDLE_IDENTIFIER = com.apple.security.SecurityTestsOSX; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + EBB697091BE208FC00715F16 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; 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_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = 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; - COMBINE_HIDPI_IMAGES = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + 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_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "SECITEM_SHIM_OSX=1", - "SECTRUST_OSX=0", - "TRUSTD_SERVER=1", + "DEBUG=1", "$(inherited)", ); - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/sec", - "$(PROJECT_DIR)/sec/securityd", - "$(PROJECT_DIR)/sec/ipc", - "$(PROJECT_DIR)/sec/SOSCircle", - "$(PROJECT_DIR)/utilities", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../ios/asn1", - "$(PROJECT_DIR)/../libsecurity_keychain/libDER", - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(inherited)", - ); - INFOPLIST_FILE = "trustd/trustd-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; - MACH_O_TYPE = mh_execute; - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - "-framework", - AppleSystemInfo, - ); - PRODUCT_NAME = trustd; - RUN_CLANG_STATIC_ANALYZER = YES; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - USE_HEADERMAP = NO; - VALID_ARCHS = "armv6 armv7 x86_64 x86_64h"; - WRAPPER_EXTENSION = xpc; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-laks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; }; name = Debug; }; - BE94B7A31AD83AF700A7216D /* Release */ = { + EBB6970A1BE208FC00715F16 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; 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_IMPLICIT_SIGN_CONVERSION = YES; - CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = 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; - COMBINE_HIDPI_IMAGES = YES; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "SECITEM_SHIM_OSX=1", - "SECTRUST_OSX=0", - "TRUSTD_SERVER=1", - "$(inherited)", - ); - GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; - GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + 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_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; - GCC_WARN_SHADOW = YES; - GCC_WARN_SIGN_COMPARE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_LABEL = YES; - GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ( - "$(PROJECT_DIR)/sec", - "$(PROJECT_DIR)/sec/securityd", - "$(PROJECT_DIR)/sec/ipc", - "$(PROJECT_DIR)/sec/SOSCircle", - "$(PROJECT_DIR)/utilities", - "$(PROJECT_DIR)", - "$(PROJECT_DIR)/../ios/asn1", - "$(PROJECT_DIR)/../libsecurity_keychain/libDER", - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(inherited)", - ); - INFOPLIST_FILE = "trustd/trustd-Info.plist"; - INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; - MACH_O_TYPE = mh_execute; - "OTHER_LDFLAGS[sdk=macosx*]" = ( - "-F$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - "-framework", - AppleSystemInfo, - ); - PRODUCT_NAME = trustd; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - USE_HEADERMAP = NO; - VALID_ARCHS = "armv6 armv7 x86_64 x86_64h"; - WRAPPER_EXTENSION = xpc; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = "-laks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; }; name = Release; }; - CD63ACE41A8061FA001B5671 /* Debug */ = { + EBE011D41C21357200CB6A63 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; 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 = IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - ); + DEBUGGING_SYMBOLS = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist"; - INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.Internal.sdk/usr/local/lib", - ); - MACH_O_TYPE = mh_execute; + MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(inherited)", - "-framework", - MobileKeyBag, - ); + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - VALID_ARCHS = "armv6 armv7 x86_64"; - WRAPPER_EXTENSION = bundle; }; name = Debug; }; - CD63ACE51A8061FA001B5671 /* Release */ = { + EBE011D51C21357200CB6A63 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18BFC44017C43393005DE6C3 /* executable.xcconfig */; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; 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 = IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist; - CODE_SIGN_IDENTITY = "-"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; + COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", - ); + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "IDSKeychainSyncingProxy/IDSKeychainSyncingProxy-Info.plist"; - INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/A/Resources"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.Internal.sdk/usr/local/lib", - ); - MACH_O_TYPE = mh_execute; - "OTHER_LDFLAGS[sdk=iphoneos*]" = ( - "$(inherited)", - "-framework", - MobileKeyBag, - ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - VALID_ARCHS = "armv6 armv7 x86_64"; - WRAPPER_EXTENSION = bundle; }; name = Release; }; @@ -7974,15 +7826,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 0C6C642A15D5ADB500BC68CD /* Build configuration list for PBXAggregateTarget "Security_kexts" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 0C6C642B15D5ADB500BC68CD /* Debug */, - 0C6C642C15D5ADB500BC68CD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 0CC3352A16C1ED8000399E53 /* Build configuration list for PBXNativeTarget "secdtests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -8028,15 +7871,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 182BB599146FE295000BF1F3 /* Build configuration list for PBXAggregateTarget "World" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 182BB59A146FE295000BF1F3 /* Debug */, - 182BB59B146FE295000BF1F3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 186F778914E59FB200434E1F /* Build configuration list for PBXAggregateTarget "Security_frameworks" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -8136,15 +7970,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5214701416977CB800DF0DB3 /* Build configuration list for PBXNativeTarget "CloudKeychainProxy" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5214701516977CB800DF0DB3 /* Debug */, - 5214701616977CB800DF0DB3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 5EF7C2381B00E25400E5E99C /* Build configuration list for PBXNativeTarget "secacltests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -8154,38 +7979,38 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 72756C2F175D485D00F52070 /* Build configuration list for PBXNativeTarget "cloud_keychain_diagnose" */ = { + BE48AE1E1ADF1DF4000836C1 /* Build configuration list for PBXNativeTarget "trustd" */ = { isa = XCConfigurationList; buildConfigurations = ( - 72756C07175D485D00F52070 /* Debug */, - 72756C08175D485D00F52070 /* Release */, + BE48AE1F1ADF1DF4000836C1 /* Debug */, + BE48AE201ADF1DF4000836C1 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BE48AE1E1ADF1DF4000836C1 /* Build configuration list for PBXNativeTarget "trustd" */ = { + D42FA8321C9B8D3D003E46A7 /* Build configuration list for PBXNativeTarget "SecurityTestsOSX" */ = { isa = XCConfigurationList; buildConfigurations = ( - BE48AE1F1ADF1DF4000836C1 /* Debug */, - BE48AE201ADF1DF4000836C1 /* Release */, + D42FA8331C9B8D3D003E46A7 /* Debug */, + D42FA8341C9B8D3D003E46A7 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BE94B7A11AD83AF700A7216D /* Build configuration list for PBXNativeTarget "trustd.xpc" */ = { + EBB697081BE208FC00715F16 /* Build configuration list for PBXNativeTarget "secbackupntest" */ = { isa = XCConfigurationList; buildConfigurations = ( - BE94B7A21AD83AF700A7216D /* Debug */, - BE94B7A31AD83AF700A7216D /* Release */, + EBB697091BE208FC00715F16 /* Debug */, + EBB6970A1BE208FC00715F16 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CD63AD101A8061FA001B5671 /* Build configuration list for PBXNativeTarget "IDSKeychainSyncingProxy" */ = { + EBE011FE1C21357200CB6A63 /* Build configuration list for PBXLegacyTarget "SecurityFeatures" */ = { isa = XCConfigurationList; buildConfigurations = ( - CD63ACE41A8061FA001B5671 /* Debug */, - CD63ACE51A8061FA001B5671 /* Release */, + EBE011D41C21357200CB6A63 /* Debug */, + EBE011D51C21357200CB6A63 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme deleted file mode 100644 index 081a81f4..00000000 --- a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme deleted file mode 100644 index cf5e1e5c..00000000 --- a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/copyHeaders.xcscheme +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme new file mode 100644 index 00000000..09f31817 --- /dev/null +++ b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - World.xcscheme @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme similarity index 81% rename from OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme rename to OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme index f92e458a..3173d32d 100644 --- a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme +++ b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - secdtests.xcscheme @@ -1,24 +1,23 @@ + buildImplicitDependencies = "NO"> + buildForAnalyzing = "YES"> + BlueprintIdentifier = "E74584661BF68EBA001B54A4" + BuildableName = "osx" + BlueprintName = "osx" + ReferencedContainer = "container:../Security.xcodeproj"> + buildForAnalyzing = "YES"> + + + + + + + + + + @@ -198,18 +216,27 @@ argument = "secd_70_engine_corrupt" isEnabled = "NO"> + + + + + + + + - - - - diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/sectests.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - sectests.xcscheme similarity index 82% rename from OSX/OSX.xcodeproj/xcshareddata/xcschemes/sectests.xcscheme rename to OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - sectests.xcscheme index cf04ed9c..1b9c7b70 100644 --- a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/sectests.xcscheme +++ b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/osx - sectests.xcscheme @@ -1,11 +1,25 @@ + parallelizeBuildables = "NO" + buildImplicitDependencies = "NO"> + + + + - Application-Group - - InternetAccounts - CFBundleDevelopmentRegion - English + en CFBundleExecutable - ${EXECUTABLE_NAME} + $(EXECUTABLE_NAME) CFBundleIconFile CFBundleIdentifier - com.apple.security.idskeychainsyncingproxy + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName - ${PRODUCT_NAME} + $(PRODUCT_NAME) CFBundlePackageType - BNDL + APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSHumanReadableCopyright - Copyright © 2013 Apple, Inc. All rights reserved. + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication diff --git a/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist new file mode 100644 index 00000000..f1509978 --- /dev/null +++ b/OSX/SecurityTestsOSX/SecurityTests-Entitlements.plist @@ -0,0 +1,47 @@ + + + + + keychain-cloud-circle + + com.apple.keystore.access-keychain-keys + + com.apple.keystore.device + + restore-keychain + + migrate-keychain + + com.apple.private.system-keychain + + modify-anchor-certificates + + com.apple.springboard.wipedevice + + application-identifier + com.apple.security.regressions + com.apple.private.uninstall.deletion + + keychain-access-groups + + com.apple.security.regressions + lockdown-identities + apple + com.apple.security.sos + 123456.test.group + 123456.test.group2 + + com.apple.private.ubiquity-kvstore-access + + com.apple.securityd + + com.apple.developer.ubiquity-kvstore-identifier + com.apple.security.cloudkeychainproxy3 + com.apple.developer.ubiquity-container-identifiers + + com.apple.security.cloudkeychainproxy3 + com.apple.security.cloudkeychain + CloudKeychainProxy.xpc + + + diff --git a/OSX/SecurityTestsOSX/main.m b/OSX/SecurityTestsOSX/main.m new file mode 100644 index 00000000..223fb6c9 --- /dev/null +++ b/OSX/SecurityTestsOSX/main.m @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2012,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 "test/testenv.h" + +#include "testlist.h" +#include +#include "testlist.h" +#include + +int main(int argc, char *argv[]) +{ + //printf("Build date : %s %s\n", __DATE__, __TIME__); + + int result = tests_begin(argc, argv); + + fflush(stdout); + fflush(stderr); + + sleep(1); + + return result; +} diff --git a/OSX/SecurityTestsOSX/testlist.h b/OSX/SecurityTestsOSX/testlist.h new file mode 100644 index 00000000..5e7364ea --- /dev/null +++ b/OSX/SecurityTestsOSX/testlist.h @@ -0,0 +1,7 @@ +/* Don't prevent multiple inclusion of this file. */ +#include +#include +#include +#include +#include +#include diff --git a/OSX/authd/Info.plist b/OSX/authd/Info.plist index 0573db37..171006a9 100644 --- a/OSX/authd/Info.plist +++ b/OSX/authd/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.apple.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/authd/agent.c b/OSX/authd/agent.c index 653734e6..3ca68d34 100644 --- a/OSX/authd/agent.c +++ b/OSX/authd/agent.c @@ -130,7 +130,7 @@ agent_create(engine_t engine, mechanism_t mech, auth_token_t auth, process_t pro agent->actionQueue = dispatch_queue_create("Agent Action Queue", 0); if (!mechanism_is_privileged(mech)) { - if (auid != AU_DEFAUDITID) { + if (auid != AU_DEFAUDITID && audit_info->auid != AU_DEFAUDITID) { // User => regular user-level SecurityAgent agent->agentConnection = xpc_connection_create_mach_service(SECURITYAGENT_BOOTSTRAP_NAME_BASE, NULL, 0); xpc_connection_set_target_uid(agent->agentConnection, auid); diff --git a/OSX/authd/authdb.c b/OSX/authd/authdb.c index 535a7ae0..fcf6160d 100644 --- a/OSX/authd/authdb.c +++ b/OSX/authd/authdb.c @@ -106,6 +106,8 @@ static const char * const authdb_upgrade_sql[] = { "INSERT INTO config VALUES('version', "AUTHDB_VERSION_STRING");" }; +static sqlite3 * _create_handle(authdb_t db); + static int32_t _sqlite3_exec(sqlite3 * handle, const char * query) { @@ -272,9 +274,13 @@ static void _handle_corrupt_db(authdb_connection_t dbconn) } else { LOGE("Tried to copy corrupt database at path %s, but we failed with SQLite error %i.", dbconn->db->db_path, rc); } - sqlite3_close(corrupt_db); } - + + // SQLite documentation says: + // Whether or not an error occurs when it is opened, resources associated with the database connection handle should be released by passing it to sqlite3_close() when it is no longer required. + if (corrupt_db) + sqlite3_close(corrupt_db); + _truncate_db(dbconn); } @@ -285,7 +291,7 @@ static int32_t _db_maintenance(authdb_connection_t dbconn) authdb_transaction(dbconn, AuthDBTransactionNormal, ^bool(void) { - authdb_get_key_value(dbconn, "config", &config); + authdb_get_key_value(dbconn, "config", true, &config); // We don't have a config table if (NULL == config) { @@ -293,7 +299,7 @@ static int32_t _db_maintenance(authdb_connection_t dbconn) s3e = _db_upgrade_from_version(dbconn, 0); require_noerr_action(s3e, done, LOGE("authdb: failed to initialize database %i", s3e)); - s3e = authdb_get_key_value(dbconn, "config", &config); + s3e = authdb_get_key_value(dbconn, "config", true, &config); require_noerr_action(s3e, done, LOGE("authdb: failed to get config %i", s3e)); } @@ -346,13 +352,17 @@ static bool _is_busy(int32_t rc) return SQLITE_BUSY == rc || SQLITE_LOCKED == rc; } -static void _checkResult(authdb_connection_t dbconn, int32_t rc, const char * fn_name, sqlite3_stmt * stmt) +static void _checkResult(authdb_connection_t dbconn, int32_t rc, const char * fn_name, sqlite3_stmt * stmt, const bool skip_maintenance) { bool isCorrupt = (SQLITE_CORRUPT == rc) || (SQLITE_NOTADB == rc) || (SQLITE_IOERR == rc); if (isCorrupt) { + if (skip_maintenance) { + LOGV("authdb: corrupted db, skipping maintenance %s %s", fn_name, sqlite3_errmsg(dbconn->handle)); + } else { _handle_corrupt_db(dbconn); authdb_maintenance(dbconn); + } } else if (SQLITE_CONSTRAINT == rc || SQLITE_READONLY == rc) { if (stmt) { LOGV("authdb: %s %s for %s", fn_name, sqlite3_errmsg(dbconn->handle), sqlite3_sql(stmt)); @@ -457,7 +467,7 @@ authdb_connection_t authdb_connection_acquire(authdb_t db) void authdb_connection_release(authdb_connection_t * dbconn) { - if (!dbconn || !(*dbconn)) + if (!(*dbconn)) return; authdb_connection_t tmp = *dbconn; @@ -479,6 +489,9 @@ static bool _db_check_corrupted(authdb_connection_t dbconn) bool isCorrupted = true; sqlite3_stmt *stmt = NULL; int32_t rc; + + if (!dbconn->handle) + return true; rc = sqlite3_prepare_v2(dbconn->handle, "PRAGMA integrity_check;", -1, &stmt, NULL); if (rc == SQLITE_LOCKED || rc == SQLITE_BUSY) { @@ -517,13 +530,19 @@ bool authdb_maintenance(authdb_connection_t dbconn) _handle_corrupt_db(dbconn); } - _db_maintenance(dbconn); - - rc = authdb_get_key_value(dbconn, "config", &config); - require_noerr_action(rc, done, LOGV("authdb: maintenance failed %i", rc)); - + if (dbconn->handle == NULL) { + dbconn->handle = _create_handle(dbconn->db); + } + + require_action(dbconn->handle, done, LOGE("authdb: maintenance cannot open database")); + + _db_maintenance(dbconn); + + rc = authdb_get_key_value(dbconn, "config", true, &config); + require_noerr_action(rc, done, LOGV("authdb: maintenance failed %i", rc)); + _db_load_data(dbconn, config); - + done: CFReleaseSafe(config); LOGD("authdb: finished maintenance"); @@ -537,13 +556,13 @@ authdb_exec(authdb_connection_t dbconn, const char * query) require(query != NULL, done); rc = _sqlite3_exec(dbconn->handle, query); - _checkResult(dbconn, rc, __FUNCTION__, NULL); + _checkResult(dbconn, rc, __FUNCTION__, NULL, false); done: return rc; } -static int32_t _prepare(authdb_connection_t dbconn, const char * sql, sqlite3_stmt ** out_stmt) +static int32_t _prepare(authdb_connection_t dbconn, const char * sql, const bool skip_maintenance, sqlite3_stmt ** out_stmt) { int32_t rc; sqlite3_stmt * stmt = NULL; @@ -557,7 +576,7 @@ static int32_t _prepare(authdb_connection_t dbconn, const char * sql, sqlite3_st *out_stmt = stmt; done: - _checkResult(dbconn, rc, __FUNCTION__, stmt); + _checkResult(dbconn, rc, __FUNCTION__, stmt, skip_maintenance); return rc; } @@ -629,7 +648,7 @@ static int32_t _bindItemsAtIndex(sqlite3_stmt * stmt, int col, auth_items_t item return rc; } -int32_t authdb_get_key_value(authdb_connection_t dbconn, const char * table, auth_items_t * out_items) +int32_t authdb_get_key_value(authdb_connection_t dbconn, const char * table, const bool skip_maintenance, auth_items_t * out_items) { int32_t rc = SQLITE_ERROR; char * query = NULL; @@ -641,7 +660,7 @@ int32_t authdb_get_key_value(authdb_connection_t dbconn, const char * table, aut asprintf(&query, "SELECT * FROM %s", table); - rc = _prepare(dbconn, query, &stmt); + rc = _prepare(dbconn, query, skip_maintenance, &stmt); require_noerr(rc, done); items = auth_items_create(); @@ -651,7 +670,7 @@ int32_t authdb_get_key_value(authdb_connection_t dbconn, const char * table, aut _parseItemsAtIndex(stmt, 1, items, (const char*)sqlite3_column_text(stmt, 0)); break; default: - _checkResult(dbconn, rc, __FUNCTION__, stmt); + _checkResult(dbconn, rc, __FUNCTION__, stmt, skip_maintenance); if (_is_busy(rc)) { sleep(AUTHDB_BUSY_DELAY); } else { @@ -683,19 +702,19 @@ int32_t authdb_set_key_value(authdb_connection_t dbconn, const char * table, aut asprintf(&query, "INSERT OR REPLACE INTO %s VALUES (?,?)", table); - rc = _prepare(dbconn, query, &stmt); + rc = _prepare(dbconn, query, false, &stmt); require_noerr(rc, done); auth_items_iterate(items, ^bool(const char *key) { sqlite3_reset(stmt); - _checkResult(dbconn, rc, __FUNCTION__, stmt); + _checkResult(dbconn, rc, __FUNCTION__, stmt, false); sqlite3_bind_text(stmt, 1, key, -1, NULL); _bindItemsAtIndex(stmt, 2, items, key); rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) { - _checkResult(dbconn, rc, __FUNCTION__, stmt); + _checkResult(dbconn, rc, __FUNCTION__, stmt, false); LOGV("authdb: set_key_value, step (%i) %s", rc, sqlite3_errmsg(dbconn->handle)); } @@ -770,7 +789,7 @@ bool authdb_step(authdb_connection_t dbconn, const char * sql, void (^bind_stmt) require_action(sql != NULL, done, rc = SQLITE_ERROR); - rc = _prepare(dbconn, sql, &stmt); + rc = _prepare(dbconn, sql, false, &stmt); require_noerr(rc, done); if (bind_stmt) { @@ -810,7 +829,7 @@ bool authdb_step(authdb_connection_t dbconn, const char * sql, void (^bind_stmt) } done: - _checkResult(dbconn, rc, __FUNCTION__, stmt); + _checkResult(dbconn, rc, __FUNCTION__, stmt, false); sqlite3_finalize(stmt); return rc == SQLITE_DONE; } @@ -1006,15 +1025,27 @@ static sqlite3 * _create_handle(authdb_t db) int32_t rc = sqlite3_open_v2(db->db_path, &handle, SQLITE_OPEN_READWRITE, NULL); if (rc != SQLITE_OK) { + LOGE("authdb: open %s (%i) %s", db->db_path, rc, handle ? sqlite3_errmsg(handle) : "no memory for handle"); + if (handle) { + sqlite3_close(handle); + } char * tmp = dirname(db->db_path); if (tmp) { mkpath_np(tmp, 0700); - } - rc = sqlite3_open_v2(db->db_path, &handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); - dbcreated = true; - } - require_noerr_action(rc, done, LOGE("authdb: open %s (%i) %s", db->db_path, rc, sqlite3_errmsg(handle))); - + } + rc = sqlite3_open_v2(db->db_path, &handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); + dbcreated = true; + + if (rc != SQLITE_OK) { + LOGE("authdb: create %s (%i) %s", db->db_path, rc, handle ? sqlite3_errmsg(handle) : "no memory for handle"); + if (handle) { + sqlite3_close(handle); + handle = NULL; + } + goto done; + } + } + if (_sql_profile_enabled()) { sqlite3_profile(handle, _profile, NULL); } diff --git a/OSX/authd/authdb.h b/OSX/authd/authdb.h index abe29998..6e5f6b64 100644 --- a/OSX/authd/authdb.h +++ b/OSX/authd/authdb.h @@ -48,7 +48,7 @@ AUTH_NONNULL1 AUTH_NONNULL2 AUTH_NONNULL3 bool authdb_step(authdb_connection_t, const char * sql, void (^bind_stmt)(sqlite3_stmt* stmt), authdb_iterator_t iter); AUTH_NONNULL_ALL -int32_t authdb_get_key_value(authdb_connection_t, const char * table, auth_items_t * out_items); +int32_t authdb_get_key_value(authdb_connection_t, const char * table, const bool skip_maintenance, auth_items_t * out_items); AUTH_NONNULL_ALL int32_t authdb_set_key_value(authdb_connection_t, const char * table, auth_items_t items); diff --git a/OSX/authd/authitems.c b/OSX/authd/authitems.c index a27aa355..4bfe9c9a 100644 --- a/OSX/authd/authitems.c +++ b/OSX/authd/authitems.c @@ -489,6 +489,10 @@ auth_items_get_flags(auth_items_t items, const char *key) bool auth_items_check_flags(auth_items_t items, const char *key, uint32_t flags) { + // When several bits are set in uint32_t flags, "(current & flags) != 0" checks if ANY flag is set, not all flags! + // This odd behavior is currently being relied upon in several places, so be careful when changing / fixing this. + // However, this also risks unwanted information leakage in + // AuthorizationCopyInfo ==> authorization_copy_info ==> [all info] auth_items_copy_with_flags uint32_t current = auth_items_get_flags(items,key); return flags ? (current & flags) != 0 : current == 0; } @@ -601,18 +605,18 @@ done: void auth_items_set_string(auth_items_t items, const char *key, const char *value) { - if (value) { - size_t valLen = strlen(value); - auth_item_t item = _find_item(items,key); - if (item && item->type == AI_TYPE_STRING && valLen < item->bufLen) { - memcpy(item->data.value, value, valLen+1); // copy null - item->data.valueLength = valLen; - } else { - item = auth_item_create(AI_TYPE_STRING, key, value, valLen, 0); - if (item) { - CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); - CFReleaseSafe(item); - } + assert(value); // marked non-null + + size_t valLen = strlen(value); + auth_item_t item = _find_item(items,key); + if (item && item->type == AI_TYPE_STRING && valLen < item->bufLen) { + memcpy(item->data.value, value, valLen+1); // copy null + item->data.valueLength = valLen; + } else { + item = auth_item_create(AI_TYPE_STRING, key, value, valLen, 0); + if (item) { + CFDictionarySetValue(items->dictionary, auth_item_get_cf_key(item), item); + CFReleaseSafe(item); } } } @@ -637,7 +641,9 @@ auth_items_get_string(auth_items_t items, const char *key) void auth_items_set_data(auth_items_t items, const char *key, const void *value, size_t len) { - if (value && len) { + assert(value); // marked non-null + + if (len) { auth_item_t item = _find_item(items,key); if (item && item->type == AI_TYPE_DATA && len <= item->bufLen) { memcpy(item->data.value, value, len); @@ -655,6 +661,8 @@ auth_items_set_data(auth_items_t items, const char *key, const void *value, size const void * auth_items_get_data(auth_items_t items, const char *key, size_t *len) { + assert(len); // marked non-null + auth_item_t item = _find_item(items,key); if (item) { #if DEBUG @@ -663,15 +671,34 @@ auth_items_get_data(auth_items_t items, const char *key, size_t *len) item->data.name, item->type, AI_TYPE_DATA); } #endif - if (len) { - *len = item->data.valueLength; - } + *len = item->data.valueLength; return item->data.value; } return NULL; } +const void * +auth_items_get_data_with_flags(auth_items_t items, const char *key, size_t *len, uint32_t flags) +{ + assert(len); // marked non-null + + auth_item_t item = _find_item(items,key); + if (item && (item->data.flags & flags) == flags) { +#if DEBUG + if (!(item->type == AI_TYPE_DATA || item->type == AI_TYPE_UNKNOWN)) { + LOGV("auth_items: key = %s, invalid type=%i expected=%i", + item->data.name, item->type, AI_TYPE_DATA); + } +#endif + *len = item->data.valueLength; + + return item->data.value; + } + + return NULL; +} + void auth_items_set_bool(auth_items_t items, const char *key, bool value) { diff --git a/OSX/authd/authitems.h b/OSX/authd/authitems.h index 94455b79..2fe97095 100644 --- a/OSX/authd/authitems.h +++ b/OSX/authd/authitems.h @@ -102,7 +102,10 @@ void auth_items_set_data(auth_items_t, const char *key, const void *value, size_ AUTH_WARN_RESULT AUTH_NONNULL_ALL const void * auth_items_get_data(auth_items_t, const char *key, size_t * len); - + +AUTH_WARN_RESULT AUTH_NONNULL_ALL +const void * auth_items_get_data_with_flags(auth_items_t items, const char *key, size_t *len, uint32_t flags); + AUTH_NONNULL_ALL void auth_items_set_bool(auth_items_t, const char *key, bool value); diff --git a/OSX/authd/authorization.plist b/OSX/authd/authorization.plist index 618ae61e..96879f0d 100644 --- a/OSX/authd/authorization.plist +++ b/OSX/authd/authorization.plist @@ -495,6 +495,22 @@ See remaining rules for examples. rule entitled-session-owner-or-authenticate-session-owner + com.apple.ctk.pair + + class + rule + rule + kcunlock + + com.apple.ctkbind.admin + + class + user + group + admin + shared + + com.apple.pf.rule authenticate-user @@ -828,8 +844,9 @@ See remaining rules for examples. loginKC:queryCreate loginKC:showPasswordUI - authinternal + version + 1 session-owner shared @@ -870,10 +887,11 @@ See remaining rules for examples. HomeDirMechanism:login,privileged HomeDirMechanism:status MCXMechanism:login + CryptoTokenKit:login loginwindow:done version - 3 + 4 system.login.fus @@ -1468,6 +1486,28 @@ See remaining rules for examples. rule authenticate-session-owner + system.localauthentication.ui + + class + evaluate-mechanisms + comment + Used by LocalAuthentication to display its UI. + mechanisms + + LocalAuthentication:UI + + + system.preferences.continuity + + class + rule + comment + Used by Password And Continuity PrefPane to request the user's password. + rule + + authenticate-staff-extract-context + + rules @@ -1520,6 +1560,20 @@ See remaining rules for examples. PKINITMechanism:auth,privileged + kcunlock + + class + evaluate-mechanisms + extract-password + + mechanisms + + builtin:unlock-keychain + builtin:kc-verify,privileged + + version + 1 + authenticate-admin class @@ -1557,12 +1611,16 @@ See remaining rules for examples. Authenticate as an administrator + allow password extraction. extract-password + password-only + group admin require-apple-signed timeout 0 + version + 1 authenticate-staff-extract @@ -1572,12 +1630,28 @@ See remaining rules for examples. Authenticate as group staff + allow password to be extracted. extract-password + password-only + group staff require-apple-signed timeout 0 + version + 1 + + authenticate-staff-extract-context + + class + rule + k-of-n + 2 + rule + + authenticate-staff-extract + localauthentication-context + authenticate-admin-or-staff-extract @@ -1925,6 +1999,17 @@ See remaining rules for examples. shared + localauthentication-context + + class + evaluate-mechanisms + comment + Used by LocalAuthentication to pass externalized context. + mechanisms + + LocalAuthentication:context + + diff --git a/OSX/authd/authtoken.c b/OSX/authd/authtoken.c index 51f93105..6f123e6f 100644 --- a/OSX/authd/authtoken.c +++ b/OSX/authd/authtoken.c @@ -292,13 +292,15 @@ auth_token_least_privileged(auth_token_t auth) uid_t auth_token_get_uid(auth_token_t auth) { - return auth ? auth->auditInfo.euid : (uid_t)-2; + assert(auth); // marked non-null + return auth->auditInfo.euid; } pid_t auth_token_get_pid(auth_token_t auth) { - return auth ? auth->auditInfo.pid : -1; + assert(auth); // marked non-null + return auth->auditInfo.pid; } session_t @@ -479,14 +481,13 @@ auth_token_apple_signed(auth_token_t auth) bool auth_token_is_creator(auth_token_t auth, process_t proc) { + assert(proc); // marked non-null __block bool creator = false; - if (proc) { - dispatch_sync(auth->dispatch_queue, ^{ - if (auth->creator == proc) { - creator = true; - } - }); - } + dispatch_sync(auth->dispatch_queue, ^{ + if (auth->creator == proc) { + creator = true; + } + }); return creator; } diff --git a/OSX/authd/ccaudit.c b/OSX/authd/ccaudit.c index 52a1504e..4a147303 100644 --- a/OSX/authd/ccaudit.c +++ b/OSX/authd/ccaudit.c @@ -191,6 +191,9 @@ void ccaudit_log_success(ccaudit_t ccaudit, credential_t cred, const char * righ _close(ccaudit); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" + void ccaudit_log_failure(ccaudit_t ccaudit, const char * credName, const char * right) { @@ -201,16 +204,14 @@ void ccaudit_log_failure(ccaudit_t ccaudit, const char * credName, const char * _write(ccaudit, au_to_text(right), "right"); _write(ccaudit, au_to_arg32(1, "authenticated as ", auth_token_get_uid(ccaudit->auth)), "authenticator"); - if (NULL == credName) { - _write(ccaudit, au_to_text(""), "target username"); - } else { - _write(ccaudit, au_to_text(credName), "target username"); - } + _write(ccaudit, au_to_text(""), "target username"); _write(ccaudit, au_to_return32(EPERM, (uint32_t)errAuthorizationDenied), "return"); _close(ccaudit); } +#pragma clang diagnostic pop + void ccaudit_log_mechanism(ccaudit_t ccaudit, const char * right, const char * mech, uint32_t status, const char * interrupted) { diff --git a/OSX/authd/engine.c b/OSX/authd/engine.c index 5e6d2ae8..6e2d250c 100644 --- a/OSX/authd/engine.c +++ b/OSX/authd/engine.c @@ -30,6 +30,8 @@ static void _set_auth_token_hints(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); enum { kEngineHintsFlagTemporary = (1 << 30) @@ -552,9 +554,8 @@ _evaluate_authentication(engine_t engine, rule_t rule) auth_items_set_data(engine->hints, AGENT_HINT_RETRY_REASON, &engine->reason, sizeof(engine->reason)); auth_items_set_int(engine->hints, AGENT_HINT_TRIES, engine->tries); - status = _evaluate_mechanisms(engine, mechanisms); - + LOGV("engine[%i]: evaluate mechanisms result %d", connection_get_pid(engine->conn), (int)status); // successfully ran mechanisms to obtain credential @@ -794,6 +795,23 @@ _evaluate_class_rule(engine_t engine, rule_t rule, bool *save_pwd) return status; } +static bool +_preevaluate_class_rule(engine_t engine, rule_t rule) +{ + LOGV("engine[%i]: _preevaluate_class_rule %s", connection_get_pid(engine->conn), rule_get_name(rule)); + + __block bool password_only = false; + rule_delegates_iterator(rule, ^bool(rule_t delegate) { + if (_preevaluate_rule(engine, delegate)) { + password_only = true; + return false; + } + return true; + }); + + return password_only; +} + static OSStatus _evaluate_class_mechanism(engine_t engine, rule_t rule) { @@ -876,7 +894,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) *save_pwd |= rule_get_extract_password(rule); - switch (rule_get_class(rule)) { + switch (rule_get_class(rule)) { case RC_ALLOW: LOGV("engine[%i]: rule set to allow", connection_get_pid(engine->conn)); return errAuthorizationSuccess; @@ -890,11 +908,32 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) case RC_MECHANISM: return _evaluate_class_mechanism(engine, rule); default: - LOGE("engine[%i]: invalid class for rule or rule not found", connection_get_pid(engine->conn)); + LOGE("engine[%i]: invalid class for rule or rule not found: %s", connection_get_pid(engine->conn), rule_get_name(rule)); return errAuthorizationInternal; } } +// 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) +{ + LOGV("engine[%i]: _preevaluate_rule %s", connection_get_pid(engine->conn), rule_get_name(rule)); + + switch (rule_get_class(rule)) { + case RC_ALLOW: + case RC_DENY: + return false; + case RC_USER: + return rule_get_password_only(rule); + case RC_RULE: + return _preevaluate_class_rule(engine, rule); + case RC_MECHANISM: + return false; + default: + return false; + } +} + static rule_t _find_rule(engine_t engine, authdb_connection_t dbconn, const char * string) { @@ -963,8 +1002,11 @@ static void _parse_environment(engine_t engine, auth_items_t environment) if (engine->flags & kAuthorizationFlagExtendRights) { const char * user = auth_items_get_string(environment, kAuthorizationEnvironmentUsername); const char * pass = auth_items_get_string(environment, kAuthorizationEnvironmentPassword); + const bool password_was_used = auth_items_get_string(environment, AGENT_CONTEXT_AP_PAM_SERVICE_NAME) == nil; // AGENT_CONTEXT_AP_PAM_SERVICE_NAME in the context means alternative PAM was used + require(password_was_used == true, done); + bool shared = auth_items_exist(environment, kAuthorizationEnvironmentShared); - require(user != NULL, done); + require_action(user != NULL, done, LOGV("engine[%i]: user not used password", connection_get_pid(engine->conn))); struct passwd *pw = getpwnam(user); require_action(pw != NULL, done, LOGE("engine[%i]: user not found %s", connection_get_pid(engine->conn), user)); @@ -1012,6 +1054,8 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en { __block OSStatus status = errAuthorizationSuccess; __block bool savePassword = false; + __block bool password_only = false; + ccaudit_t ccaudit = NULL; require(rights != NULL, done); @@ -1032,7 +1076,32 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en engine->dismissed = false; auth_rights_clear(engine->grantedRights); - + + { + // 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 + auth_rights_iterate(rights, ^bool(const char *key) { + if (!key) + return true; + LOGV("engine[%i]: checking if rule %s contains password-only item", connection_get_pid(engine->conn), key); + + rule_t rule = _find_rule(engine, dbconn, key); + + if (rule && _preevaluate_rule(engine, rule)) { + password_only = true; + return false; + } + return true; + }); + authdb_connection_release(&dbconn); // release db handle + } + + if (password_only) { + LOGV("engine[%i]: password-only item found, forcing SecurityAgent to use password-only UI", connection_get_pid(engine->conn)); + auth_items_set_bool(engine->immutable_hints, AGENT_HINT_PASSWORD_ONLY, true); + } + auth_rights_iterate(rights, ^bool(const char *key) { if (!key) return true; @@ -1119,13 +1188,18 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en return true; }); + + if (password_only) { + LOGV("engine[%i]: removing password-only flag", connection_get_pid(engine->conn)); + auth_items_remove(engine->immutable_hints, AGENT_HINT_PASSWORD_ONLY); + } if ((engine->flags & kAuthorizationFlagPartialRights) && (auth_rights_get_count(engine->grantedRights) > 0)) { status = errAuthorizationSuccess; } if (engine->dismissed) { - LOGE("engine[%i]: engine dismissed"); + LOGE("engine: engine dismissed"); status = errAuthorizationDenied; } diff --git a/OSX/authd/process.c b/OSX/authd/process.c index ce530651..19f71229 100644 --- a/OSX/authd/process.c +++ b/OSX/authd/process.c @@ -207,29 +207,34 @@ process_get_key(process_t proc) uid_t process_get_uid(process_t proc) { - return proc ? proc->auditInfo.euid : (uid_t)-2; + assert(proc); // marked non-null + return proc->auditInfo.euid; } pid_t process_get_pid(process_t proc) { - return proc ? proc->auditInfo.pid : -1; + assert(proc); // marked non-null + return proc->auditInfo.pid; } int32_t process_get_generation(process_t proc) { + assert(proc); // marked non-null return proc->auditInfo.tid; } session_id_t process_get_session_id(process_t proc) { - return proc ? proc->auditInfo.asid : -1; + assert(proc); // marked non-null + return proc->auditInfo.asid; } session_t process_get_session(process_t proc) { + assert(proc); // marked non-null return proc->session; } diff --git a/OSX/authd/rule.c b/OSX/authd/rule.c index a307f81e..097e1038 100644 --- a/OSX/authd/rule.c +++ b/OSX/authd/rule.c @@ -279,7 +279,10 @@ rule_create_with_plist(RuleType type, CFStringRef name, CFDictionaryRef plist, a if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup)), false)) { flags |= RuleFlagVPNEntitledAndGroup; } - + if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterPasswordOnly)), false)) { + flags |= RuleFlagPasswordOnly; + } + _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn); break; @@ -296,8 +299,8 @@ rule_create_with_plist(RuleType type, CFStringRef name, CFDictionaryRef plist, a if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) { flags |= RuleFlagExtractPassword; } - - _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn); + + _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn); break; case RC_DENY: @@ -502,7 +505,7 @@ _sql_bind(rule_t rule, sqlite3_stmt * stmt) rc = sqlite3_bind_text(stmt, column++, rule_get_identifier(rule), -1, NULL); require_noerr(rc, err); - CFDataRef data = rule_get_requirment_data(rule); + CFDataRef data = rule_get_requirement_data(rule); if (data) { rc = sqlite3_bind_blob(stmt, column++, CFDataGetBytePtr(data), (int32_t)CFDataGetLength(data), NULL); } else { @@ -862,7 +865,7 @@ rule_copy_to_cfobject(rule_t rule, authdb_connection_t dbconn) { CFReleaseSafe(tmp); } - SecRequirementRef req = rule_get_requirment(rule); + SecRequirementRef req = rule_get_requirement(rule); if (req) { CFStringRef reqStr = NULL; SecRequirementCopyString(req, kSecCSDefaultFlags, &reqStr); @@ -950,7 +953,10 @@ rule_copy_to_cfobject(rule_t rule, authdb_connection_t dbconn) { if (rule_get_extract_password(rule)) { CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue); } - + if (rule_get_password_only(rule)) { + CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterPasswordOnly), kCFBooleanTrue); + } + count = CFArrayGetCount(rule->mechanisms); if (count) { array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); @@ -993,7 +999,7 @@ rule_copy_to_cfobject(rule_t rule, authdb_connection_t dbconn) { if (rule_get_extract_password(rule)) { CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue); } - + n = rule_get_tries(rule); tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n); CFDictionarySetValue(dict, CFSTR("tries"), tmp); @@ -1156,6 +1162,12 @@ rule_get_extract_password(rule_t rule) return rule_check_flags(rule, RuleFlagExtractPassword); } +bool +rule_get_password_only(rule_t rule) +{ + return rule_check_flags(rule, RuleFlagPasswordOnly); +} + int64_t rule_get_tries(rule_t rule) { @@ -1189,7 +1201,7 @@ const char * rule_get_identifier(rule_t rule) return auth_items_get_string(rule->data, RULE_IDENTIFIER); } -CFDataRef rule_get_requirment_data(rule_t rule) +CFDataRef rule_get_requirement_data(rule_t rule) { if (!rule->requirement_data && auth_items_exist(rule->data, RULE_REQUIREMENT)) { size_t len; @@ -1200,10 +1212,10 @@ CFDataRef rule_get_requirment_data(rule_t rule) return rule->requirement_data; } -SecRequirementRef rule_get_requirment(rule_t rule) +SecRequirementRef rule_get_requirement(rule_t rule) { if (!rule->requirement) { - CFDataRef data = rule_get_requirment_data(rule); + CFDataRef data = rule_get_requirement_data(rule); if (data) { SecRequirementCreateWithData(data, kSecCSDefaultFlags, &rule->requirement); } diff --git a/OSX/authd/rule.h b/OSX/authd/rule.h index 1d757949..b5499d1d 100644 --- a/OSX/authd/rule.h +++ b/OSX/authd/rule.h @@ -36,7 +36,8 @@ enum { RuleFlagEntitled = 1 << 5, RuleFlagEntitledAndGroup = 1 << 6, RuleFlagRequireAppleSigned = 1 << 7, - RuleFlagVPNEntitledAndGroup = 1 << 8 + RuleFlagVPNEntitledAndGroup = 1 << 8, + RuleFlagPasswordOnly = 1 << 9 }; typedef uint32_t RuleFlags; @@ -114,7 +115,10 @@ bool rule_get_authenticate_user(rule_t); AUTH_NONNULL_ALL bool rule_get_extract_password(rule_t); - + +AUTH_NONNULL_ALL +bool rule_get_password_only(rule_t); + AUTH_NONNULL_ALL int64_t rule_get_tries(rule_t); @@ -134,10 +138,10 @@ AUTH_NONNULL_ALL const char * rule_get_identifier(rule_t); AUTH_NONNULL_ALL -CFDataRef rule_get_requirment_data(rule_t); +CFDataRef rule_get_requirement_data(rule_t); AUTH_NONNULL_ALL -SecRequirementRef rule_get_requirment(rule_t); +SecRequirementRef rule_get_requirement(rule_t); #if defined(__cplusplus) } diff --git a/OSX/authd/server.c b/OSX/authd/server.c index ef07e325..86943950 100644 --- a/OSX/authd/server.c +++ b/OSX/authd/server.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -199,7 +200,7 @@ static void _setupAuditSessionMonitor() continue; } LOGD("server: au_sdev_handle_t event=%i, session=%i", event, aia.ai_asid); - if (event == AUE_SESSION_CLOSE) { + if (event == AUE_SESSION_END) { dispatch_async(get_server_dispatch_queue(), ^{ LOGV("server: session %i destroyed", aia.ai_asid); CFDictionaryRemoveValue(gSessionMap, &aia.ai_asid); @@ -338,63 +339,59 @@ done: void server_unregister_connection(connection_t conn) { - if (conn != NULL) { - process_t proc = connection_get_process(conn); - - dispatch_sync(get_server_dispatch_queue(), ^{ - CFIndex connectionCount = process_get_connection_count(proc); - LOGV("server[%i]: unregistered connection (total=%li)", process_get_pid(proc), connectionCount); + assert(conn); // marked non-null + process_t proc = connection_get_process(conn); + + dispatch_sync(get_server_dispatch_queue(), ^{ + CFIndex connectionCount = process_get_connection_count(proc); + LOGV("server[%i]: unregistered connection (total=%li)", process_get_pid(proc), connectionCount); - if (connectionCount == 1) { - CFDictionaryRemoveValue(gProcessMap, process_get_key(proc)); - } - - if (CFDictionaryGetCount(gProcessMap) == 0) { - xpc_transaction_end(); - gXPCTransaction = false; - } - }); - // move the destruction of the connection/process off the server queue - CFRelease(conn); - } + if (connectionCount == 1) { + CFDictionaryRemoveValue(gProcessMap, process_get_key(proc)); + } + + if (CFDictionaryGetCount(gProcessMap) == 0) { + xpc_transaction_end(); + gXPCTransaction = false; + } + }); + // move the destruction of the connection/process off the server queue + CFRelease(conn); } void server_register_auth_token(auth_token_t auth) { - if (auth != NULL) { - dispatch_sync(get_server_dispatch_queue(), ^{ - LOGV("server: registering auth %p", auth); - CFDictionarySetValue(gAuthTokenMap, auth_token_get_key(auth), auth); - auth_token_set_state(auth, auth_token_state_registered); - }); - } + assert(auth); // marked non-null + dispatch_sync(get_server_dispatch_queue(), ^{ + LOGV("server: registering auth %p", auth); + CFDictionarySetValue(gAuthTokenMap, auth_token_get_key(auth), auth); + auth_token_set_state(auth, auth_token_state_registered); + }); } void server_unregister_auth_token(auth_token_t auth) { - if (auth != NULL) { - AuthorizationBlob blob = *(AuthorizationBlob*)auth_token_get_key(auth); - dispatch_async(get_server_dispatch_queue(), ^{ - LOGV("server: unregistering auth %p", auth); - CFDictionaryRemoveValue(gAuthTokenMap, &blob); - }); - } + assert(auth); + AuthorizationBlob blob = *(AuthorizationBlob*)auth_token_get_key(auth); + dispatch_async(get_server_dispatch_queue(), ^{ + LOGV("server: unregistering auth %p", auth); + CFDictionaryRemoveValue(gAuthTokenMap, &blob); + }); } auth_token_t server_find_copy_auth_token(AuthorizationBlob * blob) { + assert(blob); // marked non-null __block auth_token_t auth = NULL; - if (blob != NULL) { - dispatch_sync(get_server_dispatch_queue(), ^{ - auth = (auth_token_t)CFDictionaryGetValue(gAuthTokenMap, blob); - if (auth) { - CFRetain(auth); - } - }); - } + dispatch_sync(get_server_dispatch_queue(), ^{ + auth = (auth_token_t)CFDictionaryGetValue(gAuthTokenMap, blob); + if (auth) { + CFRetain(auth); + } + }); return auth; } @@ -640,15 +637,14 @@ authorization_copy_info(connection_t conn, xpc_object_t message, xpc_object_t re tag = xpc_dictionary_get_string(message, AUTH_XPC_TAG); LOGV("server[%i]: requested tag: %s", connection_get_pid(conn), tag ? tag : "(all)"); - if (tag) { - size_t len; - const void * data = auth_items_get_data(auth_token_get_context(auth), tag, &len); - if (data) { - auth_items_set_data(items, tag, data, len); - } - } else { - auth_items_copy(items, auth_token_get_context(auth)); - } + if (tag) { + size_t len; + const void * data = auth_items_get_data_with_flags(auth_token_get_context(auth), tag, &len, kAuthorizationContextFlagExtractable); + if (data) + auth_items_set_data(items, tag, data, len); + } else { + auth_items_copy_with_flags(items, auth_token_get_context(auth), kAuthorizationContextFlagExtractable); + } #if DEBUG LOGV("server[%i]: Dumping requested AuthRef items", connection_get_pid(conn)); @@ -663,7 +659,7 @@ authorization_copy_info(connection_t conn, xpc_object_t message, xpc_object_t re done: CFReleaseSafe(items); CFReleaseSafe(auth); - LOGV("server[%i]: AuthorizationCopyInfo %i", connection_get_pid(conn), status); + LOGV("server[%i]: AuthorizationCopyInfo %i", connection_get_pid(conn), (int) status); return status; } @@ -762,7 +758,7 @@ done: static bool _prompt_for_modifications(process_t __unused proc, rule_t __unused rule) { // will put back it back at some later date -// SecRequirementRef ruleReq = rule_get_requirment(rule); +// SecRequirementRef ruleReq = rule_get_requirement(rule); // // if (ruleReq && process_verify_requirment(proc, ruleReq)) { // return false; diff --git a/OSX/authd/session.c b/OSX/authd/session.c index 3e0d76f6..e1ed31c7 100644 --- a/OSX/authd/session.c +++ b/OSX/authd/session.c @@ -122,13 +122,15 @@ session_get_key(session_t session) session_id_t session_get_id(session_t session) { - return session ? session->auditinfo.ai_asid : -1; + assert(session); // marked non-null + return session->auditinfo.ai_asid; } uid_t session_get_uid(session_t session) { - return session ? session->auditinfo.ai_auid : (uid_t)-2; + assert(session); // marked non-null + return session->auditinfo.ai_auid; } CFIndex diff --git a/OSX/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch b/OSX/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch deleted file mode 100644 index b0e33d79..00000000 --- a/OSX/cloud_keychain_diagnose/cloud_keychain_diagnose-Prefix.pch +++ /dev/null @@ -1,5 +0,0 @@ -// -// Prefix header for all source files of the 'cloud_keychain_diagnose' target in the 'cloud_keychain_diagnose' project -// - -#inclucde diff --git a/OSX/codesign_tests/CaspianTests/CaspianTests b/OSX/codesign_tests/CaspianTests/CaspianTests index 6865b0dd..a332d01d 100755 --- a/OSX/codesign_tests/CaspianTests/CaspianTests +++ b/OSX/codesign_tests/CaspianTests/CaspianTests @@ -259,6 +259,13 @@ case $(sw_vers -buildVersion) in esac +# +# Misc regression cases +# + +runTest fail-evil-itunes spctl -a -t exec $ct/evil-itunes.app + + # # cleanup # diff --git a/OSX/config/base.xcconfig b/OSX/config/base.xcconfig index 930d45ed..63ced241 100644 --- a/OSX/config/base.xcconfig +++ b/OSX/config/base.xcconfig @@ -1,6 +1,6 @@ SDKROOT = macosx.internal -ARCHS = $(ARCHS_STANDARD_32_64_BIT) +ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) CODE_SIGN_IDENTITY = -; GCC_VERSION = com.apple.compilers.llvm.clang.1_0 DEBUG_INFORMATION_FORMAT = dwarf-with-dsym @@ -16,3 +16,4 @@ STRIP_STYLE = debugging STRIP_INSTALLED_PRODUCT = NO WARNING_CFLAGS = -Wno-deprecated-declarations $(inherited) +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/config/security.xcconfig b/OSX/config/security.xcconfig index fad4101e..afa05f70 100644 --- a/OSX/config/security.xcconfig +++ b/OSX/config/security.xcconfig @@ -27,3 +27,4 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES GCC_WARN_ABOUT_RETURN_TYPE = YES GCC_WARN_UNUSED_VARIABLE = YES +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/lib/AppWorkaround.plist b/OSX/lib/AppWorkaround.plist deleted file mode 100644 index f8e79f20..00000000 --- a/OSX/lib/AppWorkaround.plist +++ /dev/null @@ -1,90 +0,0 @@ - - - - - kCSCheckFixVersion - 1 - kCSCheckFixUniversal - - 21946795 - - com.autodesk.AdSync - - * - - com.autodesk.AutoCAD2014 - - * - - com.autodesk.AutoCAD2015 - - * - - com.autodesk.AutoCAD2016 - - * - - com.autodesk.fusion360 - - 2.* - - com.autodesk.Maya.2015 - - * - - com.autodesk.Maya.2016 - - * - - com.autodesk.Maya.2017 - - * - - com.autodesk.MayaIO.2017 - - * - - com.autodesk.MayaLT.2015 - - * - - com.autodesk.MayaLT.2016 - - * - - com.autodesk.MayaLT.2017 - - * - - com.autodesk.pkg.Mudbox2015 - - * - - com.autodesk.pkg.Mudbox2016 - - * - - com.autodesk.pkg.Mudbox2017 - - * - - com.ea.Origin - - 9.* - - com.pixar.RenderManNC-Installer - - 1.* - - com.viber.osx - - 5.* - - com.vmware.fusion - - 7.* - - - - - diff --git a/OSX/lib/Info-Security.plist b/OSX/lib/Info-Security.plist index dfb79010..a6a0716e 100644 --- a/OSX/lib/Info-Security.plist +++ b/OSX/lib/Info-Security.plist @@ -1,6 +1,6 @@ - - - + + + CFBundleDevelopmentRegion English @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.apple.security + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/OSX/lib/en.lproj/authorization.buttons.strings b/OSX/lib/en.lproj/authorization.buttons.strings index 32b139c1..6e6d04a3 100644 --- a/OSX/lib/en.lproj/authorization.buttons.strings +++ b/OSX/lib/en.lproj/authorization.buttons.strings @@ -135,3 +135,7 @@ "system.services.networkextension.filtering" = "Modify Configuration"; "com.apple.iCloud.passwordReset" = "Reset Password"; + +"system.preferences.continuity" = "Unlock"; + +"com.apple.ctkbind.admin" = "Pair"; diff --git a/OSX/lib/en.lproj/authorization.prompts.strings b/OSX/lib/en.lproj/authorization.prompts.strings index 2a7b73a3..bab9a0cc 100644 --- a/OSX/lib/en.lproj/authorization.prompts.strings +++ b/OSX/lib/en.lproj/authorization.prompts.strings @@ -151,3 +151,7 @@ "system.services.networkextension.filtering" = "__APPNAME__ is trying to modify the content filtering configuration."; "com.apple.iCloud.passwordReset" = "__APPNAME__ wants to reset your Apple ID password. This Mac can be used to reset your password because you are signed into iCloud on it."; + +"system.preferences.continuity" = "__APPNAME__ is trying to unlock the Touch ID preferences."; + +"com.apple.ctkbind.admin" = "__APPNAME__ is trying to pair the current user with the SmartCard identity."; diff --git a/OSX/lib/framework.sb b/OSX/lib/framework.sb index 74907d8d..7fa76f2d 100644 --- a/OSX/lib/framework.sb +++ b/OSX/lib/framework.sb @@ -2,3 +2,6 @@ (allow mach-lookup (global-name "com.apple.secd")) ;; allow clients to communicate with coreauthd (allow mach-lookup (global-name "com.apple.CoreAuthentication.daemon.libxpc")) +(allow mach-lookup (global-name "com.apple.CoreAuthentication.agent.libxpc")) +;; allow clients to communicate with ctkd +(allow mach-lookup (global-name "com.apple.ctkd.token-client")) diff --git a/OSX/lib/plugins/csparser-Info.plist b/OSX/lib/plugins/csparser-Info.plist index 42f9d3a8..7e030584 100644 --- a/OSX/lib/plugins/csparser-Info.plist +++ b/OSX/lib/plugins/csparser-Info.plist @@ -7,18 +7,18 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.apple.security.csparser - CFBundleName - Code Signing parser for Security.framework use + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 + CFBundleName + Code Signing parser for Security.framework use CFBundlePackageType BNDL + CFBundleShortVersionString + 3.0 CFBundleSignature ???? CFBundleVersion ${CURRENT_PROJECT_VERSION} - CFBundleShortVersionString - 3.0 diff --git a/OSX/lib/security.exp-in b/OSX/lib/security.exp-in index d308e7aa..637f8021 100644 --- a/OSX/lib/security.exp-in +++ b/OSX/lib/security.exp-in @@ -285,6 +285,8 @@ _SecCodeCopyDesignatedRequirement _SecCodeCopySigningInformation _SecCodeMapMemory _SecCodeSetDetachedSignature +_SecCodeCopyComponent +_SecCodeValidateFileResource _kSecCodeAttributeArchitecture _kSecCodeAttributeBundleVersion _kSecCodeAttributeSubarchitecture @@ -368,6 +370,11 @@ _kSecCodeInfoUnique _kSecCodeInfoCdHashes _kSecCodeInfoCodeDirectory _kSecCodeInfoCodeOffset +_kSecCodeInfoDiskRepInfo +_kSecCodeInfoDiskRepOSPlatform +_kSecCodeInfoDiskRepOSVersionMin +_kSecCodeInfoDiskRepOSSDKVersion +_kSecCodeInfoDiskRepNoLibraryValidation _kSecCodeInfoResourceDirectory _kSecGuestAttributeCanonical _kSecGuestAttributeDynamicCode @@ -375,6 +382,7 @@ _kSecGuestAttributeDynamicCodeInfoPlist _kSecGuestAttributeHash _kSecGuestAttributeMachPort _kSecGuestAttributePid +_kSecGuestAttributeAudit _kSecRequirementKeyInfoPlist _kSecRequirementKeyEntitlements _kSecRequirementKeyIdentifier @@ -385,15 +393,18 @@ _kSecCFErrorResourceSeal _kSecCFErrorResourceAdded _kSecCFErrorResourceAltered _kSecCFErrorResourceMissing +_kSecCFErrorResourceSideband _kSecCFErrorInfoPlist _kSecCFErrorGuestAttributes _kSecCFErrorRequirementSyntax -_SecTaskGetTypeID _SecTaskCreateWithAuditToken _SecTaskCreateFromSelf _SecTaskCopyValueForEntitlement _SecTaskCopyValuesForEntitlements +_SecTaskCopySigningIdentifier +_SecTaskGetCodeSignStatus +_SecTaskGetTypeID _SecTaskValidateForRequirement _SecAssessmentCreate @@ -444,6 +455,7 @@ _kSecAssessmentRuleKeyType _kSecAssessmentRuleKeyExpires _kSecAssessmentRuleKeyDisabled _kSecAssessmentRuleKeyBookmark +_kSecAssessmentContextKeyPrimarySignature // // libsecurity_cssm @@ -1124,13 +1136,16 @@ _kSecClassKey _kSecClassIdentity _kSecAttrAccess _kSecAttrAccessGroup +_kSecAttrAccessGroupToken _kSecAttrAccessible _kSecAttrAccessibleWhenUnlocked _kSecAttrAccessibleAfterFirstUnlock _kSecAttrAccessibleAlways +_kSecAttrAccessibleAlwaysPrivate _kSecAttrAccessibleWhenUnlockedThisDeviceOnly _kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly _kSecAttrAccessibleAlwaysThisDeviceOnly +_kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate _kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly _kSecAttrCreationDate _kSecAttrModificationDate @@ -1195,20 +1210,12 @@ _kSecAttrSynchronizable _kSecAttrSynchronizableAny _kSecAttrSyncViewHint _kSecAttrTokenID +_kSecAttrTokenOID +_kSecAttrTokenIDSecureEnclave _kSecAttrTombstone -_kSecAttrViewHintPCSMasterKey -_kSecAttrViewHintPCSiCloudDrive -_kSecAttrViewHintPCSPhotos -_kSecAttrViewHintPCSCloudKit -_kSecAttrViewHintPCSEscrow -_kSecAttrViewHintPCSFDE -_kSecAttrViewHintPCSMailDrop -_kSecAttrViewHintPCSiCloudBackup -_kSecAttrViewHintPCSNotes -_kSecAttrViewHintPCSiMessage -_kSecAttrViewHintAppleTV -_kSecAttrViewHintHomeKit -_kSecAttrViewHintThumper +#include "Security/SecureObjectSync/SOSViews.exp-in" +_kSecAttrMultiUser +_kSecUseTombstones _kSecMatchPolicy _kSecMatchItemList _kSecMatchSearchList @@ -1279,6 +1286,73 @@ _kSecAttrKeyClassPrivate _kSecAttrKeyClassSymmetric _kSecPrivateKeyAttrs _kSecPublicKeyAttrs +_kSecKeyAlgorithmRSASignatureRaw +_kSecKeyAlgorithmRSASignatureRawCCUnit +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224 +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512 +_kSecKeyAlgorithmECDSASignatureRFC4754 +_kSecKeyAlgorithmECDSASignatureDigestX962 +_kSecKeyAlgorithmECDSASignatureDigestX962SHA1 +_kSecKeyAlgorithmECDSASignatureDigestX962SHA224 +_kSecKeyAlgorithmECDSASignatureDigestX962SHA256 +_kSecKeyAlgorithmECDSASignatureDigestX962SHA384 +_kSecKeyAlgorithmECDSASignatureDigestX962SHA512 +_kSecKeyAlgorithmECDSASignatureMessageX962SHA1 +_kSecKeyAlgorithmECDSASignatureMessageX962SHA224 +_kSecKeyAlgorithmECDSASignatureMessageX962SHA256 +_kSecKeyAlgorithmECDSASignatureMessageX962SHA384 +_kSecKeyAlgorithmECDSASignatureMessageX962SHA512 +_kSecKeyAlgorithmRSAEncryptionRaw +_kSecKeyAlgorithmRSAEncryptionRawCCUnit +_kSecKeyAlgorithmRSAEncryptionPKCS1 +_kSecKeyAlgorithmRSAEncryptionOAEPSHA1 +_kSecKeyAlgorithmRSAEncryptionOAEPSHA224 +_kSecKeyAlgorithmRSAEncryptionOAEPSHA256 +_kSecKeyAlgorithmRSAEncryptionOAEPSHA384 +_kSecKeyAlgorithmRSAEncryptionOAEPSHA512 +_kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM +_kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM +_kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM +_kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM +_kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM +_kSecKeyAlgorithmECDHKeyExchangeStandard +_kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1 +_kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224 +_kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256 +_kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384 +_kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512 +_kSecKeyAlgorithmECDHKeyExchangeCofactor +_kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1 +_kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224 +_kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256 +_kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384 +_kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512 +_kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM +_kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM +_kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM +_kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM +_kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM +_kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM +_kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM +_kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM +_kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM +_kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw +_kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 +_kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5 +_kSecKeyKeyExchangeParameterRequestedSize +_kSecKeyKeyExchangeParameterSharedInfo _kSecImportExportPassphrase _kSecImportExportKeychain _kSecImportExportAccess @@ -1287,49 +1361,143 @@ _kSecImportItemKeyID _kSecImportItemTrust _kSecImportItemCertChain _kSecImportItemIdentity -_kSecPolicyAppleX509Basic -_kSecPolicyAppleSSL -_kSecPolicyAppleSMIME -_kSecPolicyAppleEAP -_kSecPolicyAppleSWUpdateSigning -_kSecPolicyApplePackageSigning -_kSecPolicyAppleIPsec -_kSecPolicyAppleiChat -_kSecPolicyApplePKINITClient -_kSecPolicyApplePKINITServer +_kSecPolicyAppleAST2DiagnosticsServerAuth +_kSecPolicyAppleATVVPNProfileSigning _kSecPolicyAppleCodeSigning -_kSecPolicyMacAppStoreReceipt +_kSecPolicyAppleEAP +_kSecPolicyAppleEscrowProxyCompatibilityServerAuth +_kSecPolicyAppleEscrowProxyServerAuth +_kSecPolicyAppleEscrowService +_kSecPolicyAppleExternalDeveloper +_kSecPolicyAppleFactoryDeviceCertificate +_kSecPolicyAppleFMiPServerAuth +_kSecPolicyAppleGenericApplePinned +_kSecPolicyAppleGenericAppleSSLPinned +_kSecPolicyAppleGSService +_kSecPolicyAppleHomeKitServerAuth +_kSecPolicyAppleiAP +_kSecPolicyAppleIDAuthority +_kSecPolicyAppleIDSService +_kSecPolicyAppleIDSServiceContext _kSecPolicyAppleIDValidation -_kSecPolicyAppleTimeStamping -_kSecPolicyAppleRevocation -_kSecPolicyApplePassbookSigning +_kSecPolicyAppleIDValidationRecordSigning +_kSecPolicyAppleIDValidationRecordSigningPolicy +_kSecPolicyAppleiPhoneActivation +_kSecPolicyAppleiPhoneApplicationSigning +_kSecPolicyAppleiPhoneDeviceCertificate +_kSecPolicyAppleiPhoneProfileApplicationSigning +_kSecPolicyAppleiPhoneProvisioningProfileSigning +_kSecPolicyAppleIPsec +_kSecPolicyAppleiTunesStoreURLBag +_kSecPolicyAppleLegacyPushService +_kSecPolicyAppleLockdownPairing +_kSecPolicyAppleMMCSCompatibilityServerAuth +_kSecPolicyAppleMMCSService +_kSecPolicyAppleMobileAsset _kSecPolicyAppleMobileStore -_kSecPolicyAppleEscrowService +_kSecPolicyAppleOCSPSigner +_kSecPolicyAppleOSXProvisioningProfileSigning +_kSecPolicyAppleOTAPKISigner +_kSecPolicyAppleOTATasking +_kSecPolicyApplePackageSigning +_kSecPolicyApplePassbookSigning +_kSecPolicyApplePayIssuerEncryption _kSecPolicyApplePCSEscrowService +_kSecPolicyApplePKINITClient +_kSecPolicyApplePKINITServer +_kSecPolicyApplePPQService +_kSecPolicyApplePPQSigning _kSecPolicyAppleProfileSigner +_kSecPolicyApplePushService _kSecPolicyAppleQAProfileSigner -_kSecPolicyAppleTestMobileStore +_kSecPolicyAppleRevocation _kSecPolicyAppleServerAuthentication -_kSecPolicyAppleATVAppSigning -_kSecPolicyAppleTestATVAppSigning -_kSecPolicyApplePayIssuerEncryption -_kSecPolicyAppleOSXProvisioningProfileSigning -_kSecPolicyAppleATVVPNProfileSigning -_kSecPolicyAppleAST2DiagnosticsServerAuth -_kSecPolicyOid -_kSecPolicyName +_kSecPolicyAppleSMIME +_kSecPolicyAppleSMPEncryption +_kSecPolicyAppleSoftwareSigning +_kSecPolicyAppleSSL +_kSecPolicyAppleSWUpdateSigning +_kSecPolicyAppleTestMobileStore +_kSecPolicyAppleTestOTAPKISigner +_kSecPolicyAppleTestPPQSigning +_kSecPolicyAppleTestSMPEncryption +_kSecPolicyAppleTimeStamping +_kSecPolicyAppleTVOSApplicationSigning +_kSecPolicyAppleUniqueDeviceIdentifierCertificate +_kSecPolicyAppleURLBag +_kSecPolicyAppleX509Basic +_kSecPolicyMacAppStoreReceipt +_kSecPolicyAppleAnchorIncludeTestRoots +_kSecPolicyCheckAnchorSHA1 +_kSecPolicyCheckAnchorSHA256 +_kSecPolicyCheckAnchorApple +_kSecPolicyCheckAnchorTrusted +_kSecPolicyCheckBasicCertificateProcessing +_kSecPolicyCheckBasicConstraints +_kSecPolicyCheckBlackListedKey +_kSecPolicyCheckBlackListedLeaf +_kSecPolicyCheckCertificatePolicy +_kSecPolicyCheckCertificateTransparency +_kSecPolicyCheckChainLength +_kSecPolicyCheckCriticalExtensions +_kSecPolicyCheckEAPTrustedServerNames +_kSecPolicyCheckEmail +_kSecPolicyCheckExtendedKeyUsage +_kSecPolicyCheckExtendedValidation +_kSecPolicyCheckGrayListedKey +_kSecPolicyCheckGrayListedLeaf +_kSecPolicyCheckIdLinkage +_kSecPolicyCheckIntermediateEKU +_kSecPolicyCheckIntermediateMarkerOid +_kSecPolicyCheckIntermediateSPKISHA256 +_kSecPolicyCheckIssuerCommonName +_kSecPolicyCheckKeySize +_kSecPolicyCheckKeyUsage +_kSecPolicyCheckLeafMarkerOid +_kSecPolicyCheckLeafMarkerOidWithoutValueCheck +_kSecPolicyCheckNoNetworkAccess +_kSecPolicyCheckNonEmptySubject +_kSecPolicyCheckNotValidBefore +_kSecPolicyCheckQualifiedCertStatements +_kSecPolicyCheckRevocation +_kSecPolicyCheckRevocationResponseRequired +_kSecPolicyCheckRevocationOCSP +_kSecPolicyCheckRevocationCRL +_kSecPolicyCheckRevocationAny +_kSecPolicyCheckSignatureHashAlgorithms +_kSecPolicyCheckSSLHostname +_kSecPolicyCheckSubjectCommonName +_kSecPolicyCheckSubjectCommonNamePrefix +_kSecPolicyCheckSubjectCommonNameTEST +_kSecPolicyCheckSubjectOrganization +_kSecPolicyCheckSubjectOrganizationalUnit +_kSecPolicyCheckUsageConstraints +_kSecPolicyCheckValidIntermediates +_kSecPolicyCheckValidLeaf +_kSecPolicyCheckValidRoot +_kSecPolicyCheckWeakIntermediates +_kSecPolicyCheckWeakLeaf +_kSecPolicyCheckWeakRoot _kSecPolicyClient +_kSecPolicyContext +_kSecPolicyIntermediateMarkerOid +_kSecPolicyLeafMarkerOid +_kSecPolicyName +_kSecPolicyOid +_kSecPolicyPolicyName _kSecPolicyRevocationFlags _kSecPolicyTeamIdentifier -_kSecPolicyKU_DigitalSignature -_kSecPolicyKU_NonRepudiation -_kSecPolicyKU_KeyEncipherment +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +_kSecPolicyKU_CRLSign _kSecPolicyKU_DataEncipherment +_kSecPolicyKU_DecipherOnly +_kSecPolicyKU_DigitalSignature +_kSecPolicyKU_EncipherOnly _kSecPolicyKU_KeyAgreement _kSecPolicyKU_KeyCertSign -_kSecPolicyKU_CRLSign -_kSecPolicyKU_EncipherOnly -_kSecPolicyKU_DecipherOnly +_kSecPolicyKU_KeyEncipherment +_kSecPolicyKU_NonRepudiation +#endif _kSecPropertyTypeTitle _kSecPropertyTypeError _kSecPropertyKeyType @@ -1461,8 +1629,25 @@ _kSecOIDX509V3SignedCertificate _kSecOIDX509V3SignedCertificateCStruct _kSecOIDSRVName _kSecRandomDefault +_kSecSignatureDigestAlgorithmUnknown +_kSecSignatureDigestAlgorithmMD2 +_kSecSignatureDigestAlgorithmMD4 +_kSecSignatureDigestAlgorithmMD5 +_kSecSignatureDigestAlgorithmSHA1 +_kSecSignatureDigestAlgorithmSHA224 +_kSecSignatureDigestAlgorithmSHA256 +_kSecSignatureDigestAlgorithmSHA384 +_kSecSignatureDigestAlgorithmSHA512 +_kSecTrustCertificateTransparency +_kSecTrustCertificateTransparencyWhiteList _kSecTrustEvaluationDate _kSecTrustExtendedValidation +_kSecTrustInfoCertificateTransparencyKey +_kSecTrustInfoCertificateTransparencyWhiteListKey +_kSecTrustInfoCompanyNameKey +_kSecTrustInfoExtendedValidationKey +_kSecTrustInfoRevocationKey +_kSecTrustInfoRevocationValidUntilKey _kSecTrustOrganizationName _kSecTrustResultDetails _kSecTrustResultValue @@ -1481,6 +1666,7 @@ _SecACLSetAuthorizations _SecACLUpdateAuthorizations _SecACLSetContents _SecACLSetSimpleContents +_SecBase64Encode _SecAccessCopyACLList _SecAccessCopySelectedACLList _SecAccessCopyMatchingACLList @@ -1496,19 +1682,36 @@ _SecCertificateAddToKeychain _SecCertificateBundleExport _SecCertificateBundleImport _SecCertificateCopyCommonName +_SecCertificateCopyCompanyName _SecCertificateCopyData -_SecCertificateCopySubjectComponent +_SecCertificateCopyDNSNames _SecCertificateCopyEmailAddresses +_SecCertificateCopyEscrowRoots _SecCertificateCopyFieldValues _SecCertificateCopyFirstFieldValue +_SecCertificateCopyiAPAuthCapabilities +_SecCertificateCopyIssuerSHA1Digest +_SecCertificateCopyIssuerSummary +_SecCertificateCopyLongDescription +_SecCertificateCopyNTPrincipalNames +_SecCertificateCopyPrecertTBS _SecCertificateCopyPreference _SecCertificateCopyPreferred _SecCertificateCopyPublicKey +_SecCertificateCopyPublicKey_ios _SecCertificateCopyPublicKeySHA1Digest _SecCertificateCopyPublicKeySHA1DigestFromCertificateData +_SecCertificateCopyRFC822Names _SecCertificateCopySHA256Digest +_SecCertificateCopyShortDescription +_SecCertificateCopySignedCertificateTimestamps +_SecCertificateCopySubjectComponent +_SecCertificateCopySubjectPublicKeyInfoSHA1Digest +_SecCertificateCopySubjectPublicKeyInfoSHA256Digest _SecCertificateCopySubjectSummary -_SecCertificateCopyDNSNames +_SecCertificateCopySubjectString +_SecCertificateCopySummaryProperties +_SecCertificateCopyValues _SecCertificateCreateItemImplInstance _SecCertificateCreateFromData _SecCertificateCreateWithBytes @@ -1524,15 +1727,48 @@ _SecCertificateGetCLHandle_legacy _SecCertificateGetCommonName _SecCertificateGetData _SecCertificateGetEmailAddress +_SecCertificateGetExcludedSubtrees _SecCertificateGetIssuer +_SecCertificateGetKeyUsage _SecCertificateGetLength +_SecCertificateGetPermittedSubtrees _SecCertificateGetSHA1Digest _SecCertificateGetSignatureHashAlgorithm _SecCertificateGetSubject +_SecCertificateGetSubjectAltName _SecCertificateGetType _SecCertificateGetTypeID +_SecCertificateHasMarkerExtension _SecCertificateInferLabel +_SecCertificateIsAtLeastMinKeySize +_SecCertificateIsCA _SecCertificateIsSelfSigned +_SecCertificateIsSelfSignedCA +_SecCertificateIsSignedBy +_SecCertificateIsWeak +_SecCertificateParseGeneralNameContentProperty +_SecCertificateParseGeneralNames +_SecCertificatePathCopyAddingLeaf +_SecCertificatePathCopyCertificates +_SecCertificatePathCopyFromParent +_SecCertificatePathCopyPublicKeyAtIndex +_SecCertificatePathCopyXPCArray +_SecCertificatePathCreate +_SecCertificatePathCreateSerialized +_SecCertificatePathGetCertificateAtIndex +_SecCertificatePathGetCount +_SecCertificatePathGetIndexOfCertificate +_SecCertificatePathGetNextSourceIndex +_SecCertificatePathGetRoot +_SecCertificatePathGetUsageConstraintsAtIndex +_SecCertificatePathHasWeakHash +_SecCertificatePathIsAnchored +_SecCertificatePathScore +_SecCertificatePathSelfSignedIndex +_SecCertificatePathSetIsAnchored +_SecCertificatePathSetNextSourceIndex +_SecCertificatePathSetSelfIssued +_SecCertificatePathVerify _SecCertificateRequestCreate _SecCertificateRequestGetTypeID _SecCertificateRequestSubmit @@ -1544,15 +1780,20 @@ _SecCertificateRequestGetData _SecCertificateReleaseFirstFieldValue _SecCertificateSetPreference _SecCertificateSetPreferred -_SecCertificateCopyValues -_SecCertificateCopyLongDescription -_SecCertificateCopyShortDescription -_SecCertificateCopyEscrowRoots +_SecCertificateVersion +_SecCertificateXPCArrayCopyArray _kSecCertificateProductionEscrowKey _kSecCertificateProductionPCSEscrowKey _kSecCertificateEscrowFileName +_SecCopyEncryptedToServer +_SecCopyEncryptedToServerKey +_SecCopyDecryptedForServer _SecCopyErrorMessageString +_SecDigestCreate _SecDigestGetData +_SecSHA256DigestCreateFromData +_SecDistinguishedNameCopyNormalizedContent +_SecErrorGetOSStatus _SecIdentityAddPreferenceItem _SecIdentityCompare _SecIdentityCopyCertificate @@ -1578,6 +1819,12 @@ _SecInferLabelFromX509Name _SecItemAdd _SecItemCopyDisplayNames _SecItemCopyMatching +_SecItemCopyParentCertificates +_SecItemCopyStoredCertificate +#if TARGET_OS_EMBEDDED +_SecCopyLastError +_SecItemUpdateWithError +#endif #if TARGET_OS_MAC _SecItemAdd_ios _SecItemCopyMatching_ios @@ -1586,7 +1833,11 @@ _SecItemUpdate_ios #endif _SecItemDelete _SecItemUpdate +_SecItemUpdateTokenItems +_SecItemDeleteAllWithAccessGroups __SecItemGetPersistentReference +__SecItemMakePersistentRef +__SecItemParsePersistentRef _kSecAttrKeyTypeRSA _kSecAttrKeyTypeDSA _kSecAttrKeyTypeAES @@ -1597,6 +1848,7 @@ _kSecAttrKeyTypeRC2 _kSecAttrKeyTypeCAST _kSecAttrKeyTypeECDSA _kSecAttrKeyTypeEC +_kSecAttrKeyTypeECSECPrimeRandom _kSecAttrPRF _kSecAttrPRFHmacAlgSHA1 _kSecAttrPRFHmacAlgSHA224 @@ -1608,14 +1860,33 @@ _kSecAttrRounds _SecECKeyGetNamedCurve _SecItemExport _SecItemImport +_CreatePrivateKeyMatchingQuery +_SecKeyCopyAttestationKey +_SecKeyCopyAttributes +_SecKeyCopyExponent +_SecKeyCopyExternalRepresentation +_SecKeyCopyKeyExchangeResult +_SecKeyCopyPersistentRef _SecKeyCopyPublicBytes +_SecKeyCopyPublicKey +_SecKeyCopyMatchingPrivateKey _SecKeyCopyModulus -_SecKeyCopyExponent _SecKeyCreate +_SecKeyCreateAttestation +_SecKeyCreateDecryptedData +_SecKeyCreateEncryptedData +_SecKeyCreateFromAttributeDictionary +_SecKeyCreateFromPublicBytes +_SecKeyCreateFromSubjectPublicKeyInfoData _SecKeyCreatePair +_SecKeyCreatePersistentRefToMatchingPrivateKey _SecKeyCreateRSAPublicKey +_SecKeyCreateRandomKey +_SecKeyCreateSignature _SecKeyCreateWithCSSMKey +_SecKeyCreateWithData _SecKeyDecrypt +_SecKeyDigestAndVerify _SecKeyEncrypt _SecKeyGenerate _SecKeyGeneratePair @@ -1625,13 +1896,18 @@ _SecKeyGetBlockSize _SecKeyGetCSPHandle _SecKeyGetCSSMKey _SecKeyGetCredentials +_SecKeyGetMatchingPrivateKeyStatus +_SecKeyGetSize _SecKeyGetStrengthInBits _SecKeyGetTypeID _SecKeyImportPair +_SecKeyIsAlgorithmSupported _SecKeyRawSign _SecKeyRawVerify +_SecKeySetParameter _SecKeySignDigest _SecKeyVerifyDigest +_SecKeyVerifySignature _SecKeyGenerateSymmetric _SecKeyCreateFromData _SecKeyCreateFromPublicData @@ -1646,6 +1922,7 @@ _SecKeychainAddGenericPassword _SecKeychainAddIToolsPassword _SecKeychainAddInternetPassword _SecKeychainAttributeInfoForItemID +_SecKeychainAttemptMigrationWithMasterKey _SecKeychainChangePassword _SecKeychainCopyAccess _SecKeychainCopyBlob @@ -1674,6 +1951,7 @@ _SecKeychainGetTypeID _SecKeychainGetUserInteractionAllowed _SecKeychainGetVersion _SecKeychainGetKeychainVersion +_SecKeychainGetUserPromptAttempts _SecKeychainMDSInstall _SecKeychainIsValid _SecKeychainItemAdd @@ -1751,81 +2029,165 @@ __SecKeychainSyncUpdateMessage _SecKeychainUnlock _SecKeychainVerifyKeyStorePassphrase _SecKeychainChangeKeyStorePassphrase +_SecKeychainStoreUnlockKeyWithPubKeyHash +_SecKeychainEraseUnlockKeyWithPubKeyHash _SecGenericPasswordCreate _SecPasswordSetInitialAccess _SecPasswordAction _SecPKCS12Import +_SecPolicyCheckCertEAPTrustedServerNames +_SecPolicyCheckCertEmail +_SecPolicyCheckCertExtendedKeyUsage +_SecPolicyCheckCertLeafMarkerOid +_SecPolicyCheckCertLeafMarkerOidWithoutValueCheck +_SecPolicyCheckCertKeyUsage +_SecPolicyCheckCertNotValidBefore +_SecPolicyCheckCertSignatureHashAlgorithms +_SecPolicyCheckCertSSLHostname +_SecPolicyCheckCertSubjectCommonName +_SecPolicyCheckCertSubjectCommonNamePrefix +_SecPolicyCheckCertSubjectCommonNameTEST +_SecPolicyCheckCertSubjectOrganization +_SecPolicyCheckCertSubjectOrganizationalUnit +_SecPolicyCopyProperties +_SecPolicyCreate +_SecPolicyCreateAppleAST2Service +_SecPolicyCreateAppleATVVPNProfileSigning +_SecPolicyCreateAppleCompatibilityEscrowProxyService +_SecPolicyCreateAppleCompatibilityMMCSService +_SecPolicyCreateAppleEscrowProxyService +_SecPolicyCreateAppleExternalDeveloper +_SecPolicyCreateAppleFMiPService _SecPolicyCreateAppleGSService +_SecPolicyCreateAppleHomeKitServerAuth +_SecPolicyCreateAppleIDAuthorityPolicy _SecPolicyCreateAppleIDSService _SecPolicyCreateAppleIDSServiceContext -_SecPolicyCreateApplePushService -_SecPolicyCreateApplePushServiceLegacy +_SecPolicyCreateAppleIDValidationRecordSigningPolicy _SecPolicyCreateAppleMMCSService -_SecPolicyCreateApplePPQService -_SecPolicyCreateAppleAST2Service -_SecPolicyCreateAppleATVAppSigning -_SecPolicyCreateTestAppleATVAppSigning -_SecPolicyCreateAppleATVVPNProfileSigning +_SecPolicyCreateApplePackageSigning _SecPolicyCreateApplePayIssuerEncryption +_SecPolicyCreateApplePinned +_SecPolicyCreateApplePPQService +_SecPolicyCreateApplePPQSigning +_SecPolicyCreateApplePushService +_SecPolicyCreateApplePushServiceLegacy +_SecPolicyCreateAppleSMPEncryption +_SecPolicyCreateAppleSoftwareSigning +_SecPolicyCreateAppleSSLPinned _SecPolicyCreateAppleSSLService +_SecPolicyCreateAppleTimeStamping +_SecPolicyCreateAppleTVOSApplicationSigning _SecPolicyCreateBasicX509 +_SecPolicyCreateCodeSigning +_SecPolicyCreateConfigurationProfileSigner +_SecPolicyCreateEAP +_SecPolicyCreateEscrowServiceSigner +_SecPolicyCreateFactoryDeviceCertificate +_SecPolicyCreateiAP +_SecPolicyCreateiPhoneActivation +_SecPolicyCreateiPhoneApplicationSigning +_SecPolicyCreateiPhoneDeviceCertificate +_SecPolicyCreateiPhoneProfileApplicationSigning +_SecPolicyCreateiPhoneProvisioningProfileSigning +_SecPolicyCreateIPSec +_SecPolicyCreateiTunesStoreURLBag +_SecPolicyCreateLockdownPairing +_SecPolicyCreateMacAppStoreReceipt +_SecPolicyCreateMobileAsset +_SecPolicyCreateMobileStoreSigner +_SecPolicyCreateOCSPSigner _SecPolicyCreateOSXProvisioningProfileSigning +_SecPolicyCreateOTAPKISigner +_SecPolicyCreateOTATasking +_SecPolicyCreatePassbookCardSigner +_SecPolicyCreatePCSEscrowServiceSigner +_SecPolicyCreateQAConfigurationProfileSigner _SecPolicyCreateRevocation _SecPolicyCreateSSL -_SecPolicyCreateWithOID +_SecPolicyCreateSMIME +_SecPolicyCreateTestApplePPQSigning +_SecPolicyCreateTestAppleSMPEncryption +_SecPolicyCreateTestMobileStoreSigner +_SecPolicyCreateTestOTAPKISigner +_SecPolicyCreateAppleUniqueDeviceCertificate +_SecPolicyCreateURLBag _SecPolicyCreateWithProperties +_SecPolicyGetName +_SecPolicyGetOidString +_SecPolicyGetTypeID +_SecPolicyXPCArrayCopyArray +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +_SecPolicyCopy +_SecPolicyCopyAll _SecPolicyCreateAppleTimeStampingAndRevocationPolicies -_SecPolicyCreateApplePackageSigning -_SecPolicyCreateAppleSWUpdateSigning -_SecPolicyCreateAppleHomeKitServerAuth +_SecPolicyCreateItemImplInstance +_SecPolicyCreateWithOID _SecPolicyGetOID +_SecPolicyGetStringForOID _SecPolicyGetTPHandle -_SecPolicyGetTypeID _SecPolicyGetValue _SecPolicySearchCopyNext _SecPolicySearchCreate _SecPolicySearchGetTypeID -_SecPolicySetValue -_SecPolicyCopy -_SecPolicyCopyAll -_SecPolicyCopyProperties _SecPolicySetProperties -_SecPolicyCopyEscrowRootCertificates -_SecTrustCopyAnchorCertificates +_SecPolicySetValue +#endif _SecTrustCopyCustomAnchorCertificates +_SecTrustCopyDetailedPropertiesAtIndex _SecTrustCopyExceptions -_SecTrustCopyExtendedResult +_SecTrustCopyFailureDescription +_SecTrustCopyInfo _SecTrustCopyPolicies _SecTrustCopyProperties _SecTrustCopyPublicKey _SecTrustCopyResult +_SecTrustCopySummaryPropertiesAtIndex _SecTrustCreateWithCertificates +_SecTrustDeserialize _SecTrustEvaluate _SecTrustEvaluateAsync +_SecTrustEvaluateLeafOnly _SecTrustGetCertificateAtIndex _SecTrustGetCertificateCount -_SecTrustGetCSSMAnchorCertificates -_SecTrustGetCssmResult -_SecTrustGetCssmResultCode +_SecTrustGetDetails +_SecTrustGetKeychainsAllowed _SecTrustGetNetworkFetchAllowed -_SecTrustGetResult +_SecTrustGetOTAPKIAssetVersionNumber _SecTrustGetTrustResult -_SecTrustGetTPHandle _SecTrustGetTypeID -_SecTrustGetUserTrust _SecTrustGetVerifyTime +_SecTrustOTAPKIGetUpdatedAsset +_SecTrustSerialize _SecTrustSetAnchorCertificates _SecTrustSetAnchorCertificatesOnly _SecTrustSetExceptions -_SecTrustSetKeychains +_SecTrustSetKeychainsAllowed _SecTrustSetNetworkFetchAllowed _SecTrustSetOCSPResponse +_SecTrustSetPolicies +_SecTrustSetSignedCertificateTimestamps +_SecTrustSetTrustedLogs +_SecTrustSetVerifyDate +#if TARGET_OS_MAC && !TARGET_OS_IPHONE +_SecTrustCopyAnchorCertificates +_SecTrustCopyExtendedResult +_SecTrustCopyProperties_ios +_SecTrustGetCSSMAnchorCertificates +_SecTrustGetCssmResult +_SecTrustGetCssmResultCode +_SecTrustGetResult +_SecTrustGetTPHandle +_SecTrustGetUserTrust +_SecTrustLegacySourcesEventRunloopCreate +_SecTrustLegacyCRLFetch +_SecTrustLegacyCRLStatus +_SecTrustSetKeychains _SecTrustSetOptions _SecTrustSetParameters -_SecTrustSetPolicies _SecTrustSetUserTrust _SecTrustSetUserTrustLegacy -_SecTrustSetVerifyDate +#endif _SecTrustedApplicationCopyData _SecTrustedApplicationCreateFromPath _SecTrustedApplicationCreateApplicationGroup @@ -1845,6 +2207,7 @@ _SecTrustSettingsCopyTrustSettings _SecTrustSettingsSetTrustSettings _SecTrustSettingsRemoveTrustSettings _SecTrustSettingsCopyCertificates +_SecTrustSettingsCopyCertificatesForUserAdminDomains _SecTrustSettingsCopyModificationDate _SecTrustSettingsCreateExternalRepresentation _SecTrustSettingsImportExternalRepresentation @@ -1858,6 +2221,7 @@ _SecCertificateGetCRLDistributionPoints _SecCertificateGetOCSPResponders _SecCertificateGetCAIssuers _SecCertificateShow +_SecCertificateCreateOidDataFromString _SecCertificateCopyIssuerSequence _SecCertificateCopySubjectSequence _SecCertificateGetNormalizedIssuerContent @@ -1865,6 +2229,7 @@ _SecCertificateGetNormalizedSubjectContent _SecCertificateHasSubject _SecCertificateHasCriticalSubjectAltName _SecCertificateHasUnknownCriticalExtension +_SecCertificateIsOidString _SecCertificateIsValid _SecCertificateIsValidX _SecCertificateNotValidBefore @@ -1876,6 +2241,7 @@ _SecCertificateGetBasicConstraints _SecCertificateGetPolicyConstraints _SecCertificateGetPolicyMappings _SecCertificateGetCertificatePolicies +_SecCertificateGetiAuthVersion _SecCertificateGetInhibitAnyPolicySkipCerts _SecCertificateGetPublicKeyAlgorithm _SecCertificateGetPublicKeyData @@ -1883,6 +2249,7 @@ _SecCertificateCreateWithPEM _SecCertificateCopySerialNumber _SecCertificateCopyNormalizedIssuerContent _SecCertificateCopyNormalizedSubjectContent +_SecCertificateCopyProperties _SecDERItemCopyOIDDecimalRepresentation _SecAbsoluteTimeFromDateContent _SecWrapRecoveryPasswordWithAnswers @@ -1906,6 +2273,7 @@ __SecKeychainBackupSyncable __SecKeychainRestoreSyncable __SecKeychainWriteBackupToFileDescriptor __SecKeychainRestoreBackupFromFileDescriptor +__SecKeychainCopyKeybagUUIDFromFileDescriptor _SecItemBackupWithRegisteredBackups _SecItemBackupSetConfirmedManifest _SecItemBackupRestore @@ -1915,7 +2283,23 @@ __SecSecuritydCopyWhoAmI __SecSyncBubbleTransfer __SecSystemKeychainTransfer __SecSyncDeleteUserViews - +_SecOTRFullIdentityCreateFromSecKeyRef +_SecOTRPublicIdentityCreateFromSecKeyRef +_SecOTRSAppendRestartPacket +_SecOTRSAppendSerialization +_SecOTRSAppendStartPacket +_SecOTRSessionCreateFromData +_SecOTRSessionCreateFromID +_SecOTRSessionCreateFromIDAndFlags +_SecOTRSessionReset +_SecOTRSGetIsIdle +_SecOTRSGetIsReadyForMessages +_SecOTRSGetMessageKind +_SecOTRSIsForKeys +_SecOTRSProcessPacket +_SecOTRSSignAndProtectMessage +_SecOTRSVerifyAndExposeMessage +__SecTokenItemCopyValueData // // libsecurity_manifest @@ -1953,6 +2337,18 @@ _MDS_RemoveSubservice // // libsecurity_smime // +_kSecCMSSignDigest +_kSecCMSSignDetached +_kSecCMSSignHashAlgorithm +_kSecCMSCertChainMode +_kSecCMSAdditionalCerts +_kSecCMSSignedAttributes +_kSecCMSSignDate +_kSecCMSAllCerts +_kSecCMSHashingAlgorithmSHA1 +_kSecCMSHashingAlgorithmSHA256 +_kSecCMSHashingAlgorithmSHA384 +_kSecCMSHashingAlgorithmSHA512 _SecArenaPoolCreate _SecArenaPoolFree _SecCmsContentInfoGetBulkKey @@ -1973,6 +2369,7 @@ _SecCmsContentInfoSetContentEncryptedData _SecCmsContentInfoSetContentEnvelopedData _SecCmsContentInfoSetContentSignedData _SecCmsContentInfoSetContentOther +_SecCMSCreateSignedData _SecCmsDecoderCreate _SecCmsDecoderDestroy _SecCmsDecoderFinish @@ -2067,7 +2464,11 @@ _SecCmsSignerInfoSaveSMIMEProfile _SecCmsUtilVerificationStatusToString _SecSMIMEFindBulkAlgForRecipients _SecCMSCertificatesOnlyMessageCopyCertificates +_SecCMSCreateCertificatesOnlyMessage _SecCMSCreateCertificatesOnlyMessageIAP +_SecCMSVerify +_SecCMSVerifyCopyDataAndAttributes +_SecCMSVerifySignedData // // libsecurity_ssl @@ -2119,6 +2520,7 @@ _SSLGetCipherSizes _SSLInternal_PRF _SSLNewContext _SSLRead +_SSLReHandshake _SSLSetAllowsAnyRoot _SSLSetAllowsExpiredCerts _SSLSetAllowsExpiredRoots @@ -2177,11 +2579,9 @@ _SSLSetPSKSharedSecret _SSLSetPSKIdentity _SSLSetMinimumDHGroupSize _SSLGetMinimumDHGroupSize -_SSLSetSessionStrengthPolicy _SSLSetDHEEnabled _SSLGetDHEEnabled _SSLSetSessionConfig -_SSLGetSessionConfig _kSSLSessionConfig_default _kSSLSessionConfig_ATSv1 @@ -2192,6 +2592,7 @@ _kSSLSessionConfig_RC4_fallback _kSSLSessionConfig_TLSv1_fallback _kSSLSessionConfig_TLSv1_RC4_fallback _kSSLSessionConfig_legacy_DHE +_kSSLSessionConfig_anonymous // // libsecurity_transform @@ -2298,10 +2699,20 @@ _SecKeyCreatePublicFromPrivate // // libsecurity_utilities // -_add_security_log_handler -_remove_security_log_handler _secdebug_internal _secdebugfunc_internal +#ifdef TARGET_OS_OSX +_weak_os_log_impl +_weak_os_log_create +_weak_os_log_type_enabled +_logObjForScope +#endif + +// +// utilities +// +_readFileSizet +_writeFileSizet // // libSecureObjectSync @@ -2331,6 +2742,7 @@ _kSecPasswordCharacterCount _kSecPasswordGroupSize _kSecPasswordNumberOfGroups _kSecPasswordSeparator +_SecCFAllocatorZeroize // // Logging @@ -2345,11 +2757,6 @@ _SecSetLoggingInfoForCircleScope // #include "../sec/Security/SecAccessControlExports.exp-in" -// -// utilities -// -_SecSecdUsage - // SecDH _SecDHComputeKey _SecDHCreate @@ -2460,3 +2867,24 @@ _oidExtendedKeyUsageMicrosoftSGC _oidExtendedKeyUsageNetscapeSGC _oidGoogleEmbeddedSignedCertificateTimestamp _oidGoogleOCSPSignedCertificateTimestamp + +// +// anchor-test SPIs +// +_SecIsAppleTrustAnchorData +_SecIsAppleTrustAnchor + +// +// libsecurity_translocate +// +_SecTranslocateStartListening +_SecTranslocateStartListeningWithOptions +_SecTranslocateCreateSecureDirectoryForURL +_SecTranslocateDeleteSecureDirectory +_SecTranslocateAppLaunchCheckin +_SecTranslocateURLShouldRunTranslocated +_SecTranslocateIsTranslocatedURL +_SecTranslocateCreateOriginalPathForURL + +_secLogDisable +_secLogEnable diff --git a/OSX/libsecurity_apple_csp/TODO b/OSX/libsecurity_apple_csp/TODO deleted file mode 100644 index cbdab795..00000000 --- a/OSX/libsecurity_apple_csp/TODO +++ /dev/null @@ -1 +0,0 @@ -Things TODO in AppleCSPDL diff --git a/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp b/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp index ec9e78ca..1d536c06 100644 --- a/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp +++ b/OSX/libsecurity_apple_csp/lib/AppleCSP.cpp @@ -378,7 +378,7 @@ void AppleCSPSession::addRefKey( cssmKey.KeyHeader.BlobType = CSSM_KEYBLOB_REFERENCE; cssmKey.KeyHeader.Format = CSSM_KEYBLOB_REF_FORMAT_INTEGER; keyRefToCssmData(keyRef, cssmKey.KeyData, normAllocator); - secdebug("freeKey", "CSP addRefKey key %p keyData %p keyRef %p", + secinfo("freeKey", "CSP addRefKey key %p keyData %p keyRef %p", &cssmKey, cssmKey.KeyData.Data, &binKey); } @@ -432,7 +432,7 @@ void AppleCSPSession::FreeKey( StLock _(refKeyMapLock); BinaryKey *binKey = lookupKeyRef(keyRef); if(binKey != NULL) { - secdebug("freeKey", "CSP FreeKey key %p keyData %p binKey %p", + secinfo("freeKey", "CSP FreeKey key %p keyData %p binKey %p", &KeyPtr, KeyPtr.KeyData.Data, binKey); try { refKeyMap.erase(keyRef); @@ -444,7 +444,7 @@ void AppleCSPSession::FreeKey( } } else { - secdebug("freeKey", "CSP freeKey unknown key"); + secinfo("freeKey", "CSP freeKey unknown key"); } } } diff --git a/OSX/libsecurity_apple_csp/lib/AppleCSPUtils.cpp b/OSX/libsecurity_apple_csp/lib/AppleCSPUtils.cpp index 5ba459d3..a167f25a 100644 --- a/OSX/libsecurity_apple_csp/lib/AppleCSPUtils.cpp +++ b/OSX/libsecurity_apple_csp/lib/AppleCSPUtils.cpp @@ -625,7 +625,7 @@ static CssmUniformDate *cspNow() return new CssmUniformDate(cfTime); } -#define keyDateDebug(args...) secdebug("keyDate", ## args) +#define keyDateDebug(args...) secinfo("keyDate", ## args) /* * Verify temporal validity of specified key. diff --git a/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp b/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp index d694ee91..72e5e058 100644 --- a/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp +++ b/OSX/libsecurity_apple_csp/lib/BlockCryptor.cpp @@ -30,9 +30,9 @@ #include #include -#define BlockCryptDebug(args...) secdebug("blockCrypt", ## args) -#define bprintf(args...) secdebug("blockCryptBuf", ## args) -#define ioprintf(args...) secdebug("blockCryptIo", ## args) +#define BlockCryptDebug(args...) secinfo("blockCrypt", ## args) +#define bprintf(args...) secinfo("blockCryptBuf", ## args) +#define ioprintf(args...) secinfo("blockCryptIo", ## args) BlockCryptor::~BlockCryptor() { diff --git a/OSX/libsecurity_apple_csp/lib/DH_keys.cpp b/OSX/libsecurity_apple_csp/lib/DH_keys.cpp index 81fbafee..6060dfe5 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_keys.cpp +++ b/OSX/libsecurity_apple_csp/lib/DH_keys.cpp @@ -32,7 +32,7 @@ #include #include -#define dhKeyDebug(args...) secdebug("dhKey", ## args) +#define dhKeyDebug(args...) secinfo("dhKey", ## args) /* * FIXME - the CDSA Algorithm Guide claims that the incoming params argument diff --git a/OSX/libsecurity_apple_csp/lib/DH_keys.h b/OSX/libsecurity_apple_csp/lib/DH_keys.h index 95966cb2..b6602116 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_keys.h +++ b/OSX/libsecurity_apple_csp/lib/DH_keys.h @@ -39,7 +39,7 @@ #define DH_MIN_KEY_SIZE 512 /* FIXME */ #define DH_MAX_KEY_SIZE 2048 -#define cspDhDebug(args...) secdebug("dhDebug", ## args) +#define cspDhDebug(args...) secinfo("dhDebug", ## args) /* * Diffie-Hellman version of a BinaryKey. diff --git a/OSX/libsecurity_apple_csp/lib/DH_utils.cpp b/OSX/libsecurity_apple_csp/lib/DH_utils.cpp index 3eccf481..895e6dc0 100644 --- a/OSX/libsecurity_apple_csp/lib/DH_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/DH_utils.cpp @@ -30,7 +30,7 @@ #include #include -#define dhMiscDebug(args...) secdebug("dhMisc", ## args) +#define dhMiscDebug(args...) secinfo("dhMisc", ## args) /* * Given a Context: diff --git a/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp b/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp index 7e29a84c..8c317b80 100644 --- a/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEECSPUtils.cpp @@ -30,7 +30,7 @@ #include #include -#define feeMiscDebug(args...) secdebug("feeMisc", ## args) +#define feeMiscDebug(args...) secinfo("feeMisc", ## args) /* Given a FEE error, throw appropriate CssmError */ void CryptKit::throwCryptKit( diff --git a/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp b/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp index 5571510d..7ce18248 100644 --- a/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEEKeys.cpp @@ -34,7 +34,7 @@ #include #include -#define feeKeyDebug(args...) secdebug("feeKey", ## args) +#define feeKeyDebug(args...) secinfo("feeKey", ## args) /*** *** FEE-style BinaryKey @@ -69,7 +69,7 @@ void CryptKit::FEEBinaryKey::generateKeyBlob( CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ { unsigned char *keyBlob; - unsigned len; + unsigned len = 0; feeReturn frtn = FR_Internal; bool freeTheKey = false; feePubKey keyToEncode = mFeeKey; @@ -243,7 +243,11 @@ void CryptKit::FEEKeyPairGenContext::generate( } } - + +void CryptKit::FEEKeyPairGenContext::generate(const Context &context, uint32, CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs) { + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + // this one is specified in, and called from, AppleKeyPairGenContext void CryptKit::FEEKeyPairGenContext::generate( const Context &context, diff --git a/OSX/libsecurity_apple_csp/lib/FEEKeys.h b/OSX/libsecurity_apple_csp/lib/FEEKeys.h index 54d6b009..58830615 100644 --- a/OSX/libsecurity_apple_csp/lib/FEEKeys.h +++ b/OSX/libsecurity_apple_csp/lib/FEEKeys.h @@ -74,6 +74,9 @@ public: const Context &context, CssmKey &pubKey, CssmKey &privKey); + + // declared in CSPFullPluginSession, but not implemented here + void generate(const Context &context, uint32, CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs); // this one is specified in, and called from, AppleKeyPairGenContext void generate( diff --git a/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp b/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp index 6cd2dffb..6b868b7a 100644 --- a/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp +++ b/OSX/libsecurity_apple_csp/lib/FEESignatureObject.cpp @@ -31,7 +31,7 @@ #include #include -#define feeSigObjDebug(args...) secdebug("feeSig", ##args) +#define feeSigObjDebug(args...) secinfo("feeSig", ##args) CryptKit::FEESigner::~FEESigner() { diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp index 8a7a9553..e73c092f 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.cpp @@ -34,7 +34,7 @@ #define RSA_PUB_EXPONENT 0x10001 /* recommended by RSA */ -#define rsaKeyDebug(args...) secdebug("rsaKey", ## args) +#define rsaKeyDebug(args...) secinfo("rsaKey", ## args) /*** @@ -193,6 +193,10 @@ void RSAKeyPairGenContext::generate( } } + +void RSAKeyPairGenContext::generate(const Context &context, uint32, CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs) { + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} // this one is specified in, and called from, AppleKeyPairGenContext void RSAKeyPairGenContext::generate( diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.h b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.h index 83a0e735..dc24124c 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.h +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_keys.h @@ -103,6 +103,9 @@ public: CssmKey &pubKey, CssmKey &privKey); + // declared in CSPFullPluginSession, but not implemented here + void generate(const Context &context, uint32, CssmData ¶ms, uint32 &attrCount, Context::Attr * &attrs); + // this one is specified in, and called from, AppleKeyPairGenContext void generate( const Context &context, diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp index d1be94cb..ae818296 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_signature.cpp @@ -29,7 +29,7 @@ #include #include -#define rsaSigDebug(args...) secdebug("rsaSig", ## args) +#define rsaSigDebug(args...) secinfo("rsaSig", ## args) static ModuleNexus gMutex; diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp index 6f15d7a5..8b88333a 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp @@ -35,7 +35,7 @@ #include #include -#define rsaMiscDebug(args...) secdebug("rsaMisc", ## args) +#define rsaMiscDebug(args...) secinfo("rsaMisc", ## args) /* * Obtain and cache max key sizes. System preferences only consulted diff --git a/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp b/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp index 7d0f0222..d0983f5b 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_asymmetric.cpp @@ -25,8 +25,8 @@ #include #include -#define rsaCryptDebug(args...) secdebug("rsaCrypt", ## args) -#define rbprintf(args...) secdebug("rsaBuf", ## args) +#define rsaCryptDebug(args...) secinfo("rsaCrypt", ## args) +#define rbprintf(args...) secinfo("rsaBuf", ## args) static ModuleNexus gMutex; diff --git a/OSX/libsecurity_apple_csp/lib/SignatureContext.cpp b/OSX/libsecurity_apple_csp/lib/SignatureContext.cpp index 22591749..3f2ac891 100644 --- a/OSX/libsecurity_apple_csp/lib/SignatureContext.cpp +++ b/OSX/libsecurity_apple_csp/lib/SignatureContext.cpp @@ -27,7 +27,7 @@ #include -#define cspSigDebug(args...) secdebug("cspSig", ## args) +#define cspSigDebug(args...) secinfo("cspSig", ## args) SignatureContext::~SignatureContext() { diff --git a/OSX/libsecurity_apple_csp/lib/ascContext.cpp b/OSX/libsecurity_apple_csp/lib/ascContext.cpp index e1b88e84..96a3efb9 100644 --- a/OSX/libsecurity_apple_csp/lib/ascContext.cpp +++ b/OSX/libsecurity_apple_csp/lib/ascContext.cpp @@ -30,8 +30,8 @@ #include #include -#define abprintf(args...) secdebug("ascBuf", ## args) /* buffer sizes */ -#define aioprintf(args...) secdebug("ascIo", ## args) /* all I/O */ +#define abprintf(args...) secinfo("ascBuf", ## args) /* buffer sizes */ +#define aioprintf(args...) secinfo("ascIo", ## args) /* all I/O */ static Allocator *ascAllocator; diff --git a/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp b/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp index db15758c..477166bb 100644 --- a/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp +++ b/OSX/libsecurity_apple_csp/lib/bsafeSymmetric.cpp @@ -24,7 +24,7 @@ #include "bsafecspi.h" #include -#define bbprintf(args...) secdebug("BSafeBuf", ## args) +#define bbprintf(args...) secinfo("BSafeBuf", ## args) #define VERBOSE_DEBUG 0 #if VERBOSE_DEBUG diff --git a/OSX/libsecurity_apple_csp/lib/cspdebugging.h b/OSX/libsecurity_apple_csp/lib/cspdebugging.h index 8648f239..91fdd945 100644 --- a/OSX/libsecurity_apple_csp/lib/cspdebugging.h +++ b/OSX/libsecurity_apple_csp/lib/cspdebugging.h @@ -108,10 +108,13 @@ extern void dblog4(char *str, void * arg1, void * arg2, void * arg3, void * arg4 extern "C" { #endif +#include + static inline void _panic(const char *str) { printf("%s\n", str); - exit(1); + CRSetCrashLogMessage(str); + abort(); } #ifdef __cplusplus diff --git a/OSX/libsecurity_apple_csp/lib/desContext.cpp b/OSX/libsecurity_apple_csp/lib/desContext.cpp index 2e93686a..43890cfd 100644 --- a/OSX/libsecurity_apple_csp/lib/desContext.cpp +++ b/OSX/libsecurity_apple_csp/lib/desContext.cpp @@ -25,7 +25,7 @@ #include #include -#define DESDebug(args...) secdebug("desContext", ## args) +#define DESDebug(args...) secinfo("desContext", ## args) /* * DES encrypt/decrypt. diff --git a/OSX/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj b/OSX/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj index 80686068..ff7ee6a0 100644 --- a/OSX/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_apple_csp/libsecurity_apple_csp.xcodeproj/project.pbxproj @@ -250,13 +250,6 @@ remoteGlobalIDString = 0539107D0A37721E00B9E848; remoteInfo = "Copy Open Source Docs"; }; - 182BB344146F10ED000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; 18446095146DFBC900B12992 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 18446090146DFBC800B12992 /* libsecurity_cdsa_plugin.xcodeproj */; @@ -403,9 +396,9 @@ C280AE570534BBD900F7E802 /* stack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack.h; sourceTree = ""; }; C280AE580534BBD900F7E802 /* x509.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = x509.h; sourceTree = ""; }; C280AE590534BBD900F7E802 /* x509_vfy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = x509_vfy.h; sourceTree = ""; }; - C280AE5B0534BBD900F7E802 /* opensslAsn1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = opensslAsn1.cpp; sourceTree = ""; }; + C280AE5B0534BBD900F7E802 /* opensslAsn1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = opensslAsn1.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C280AE5C0534BBD900F7E802 /* opensslAsn1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = opensslAsn1.h; sourceTree = ""; }; - C280AE5D0534BBD900F7E802 /* opensslUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = opensslUtils.cpp; sourceTree = ""; }; + C280AE5D0534BBD900F7E802 /* opensslUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = opensslUtils.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C280AE5E0534BBD900F7E802 /* opensslUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = opensslUtils.h; sourceTree = ""; }; C280AE620534BBD900F7E802 /* rsa_chk.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_chk.c; sourceTree = ""; }; C280AE630534BBD900F7E802 /* rsa_eay.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rsa_eay.c; sourceTree = ""; }; @@ -423,7 +416,7 @@ C28436FE053488AB000AE0FC /* aescsp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = aescsp.cpp; sourceTree = ""; }; C28436FF053488AB000AE0FC /* aescspi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aescspi.h; sourceTree = ""; }; C2843700053488AB000AE0FC /* algmaker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = algmaker.cpp; sourceTree = ""; }; - C2843701053488AB000AE0FC /* AppleCSP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSP.cpp; sourceTree = ""; }; + C2843701053488AB000AE0FC /* AppleCSP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleCSP.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2843702053488AB000AE0FC /* AppleCSP.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSP.h; sourceTree = ""; }; C2843703053488AB000AE0FC /* AppleCSPContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPContext.cpp; sourceTree = ""; }; C2843704053488AB000AE0FC /* AppleCSPContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPContext.h; sourceTree = ""; }; @@ -431,15 +424,15 @@ C2843706053488AB000AE0FC /* AppleCSPKeys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPKeys.h; sourceTree = ""; }; C2843707053488AB000AE0FC /* AppleCSPPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPPlugin.cpp; sourceTree = ""; }; C2843708053488AB000AE0FC /* AppleCSPSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPSession.h; sourceTree = ""; }; - C2843709053488AB000AE0FC /* AppleCSPUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleCSPUtils.cpp; sourceTree = ""; }; + C2843709053488AB000AE0FC /* AppleCSPUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleCSPUtils.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284370A053488AB000AE0FC /* AppleCSPUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleCSPUtils.h; sourceTree = ""; }; - C284370B053488AB000AE0FC /* ascContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ascContext.cpp; sourceTree = ""; }; + C284370B053488AB000AE0FC /* ascContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ascContext.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284370C053488AB000AE0FC /* ascContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ascContext.h; sourceTree = ""; }; C284370D053488AB000AE0FC /* ascFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ascFactory.h; sourceTree = ""; }; C284370E053488AB000AE0FC /* bfContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bfContext.cpp; sourceTree = ""; }; C284370F053488AB000AE0FC /* bfContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bfContext.h; sourceTree = ""; }; C2843710053488AB000AE0FC /* BinaryKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BinaryKey.h; sourceTree = ""; }; - C2843711053488AB000AE0FC /* BlockCryptor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BlockCryptor.cpp; sourceTree = ""; }; + C2843711053488AB000AE0FC /* BlockCryptor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = BlockCryptor.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2843712053488AB000AE0FC /* BlockCryptor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BlockCryptor.h; sourceTree = ""; }; C2843713053488AB000AE0FC /* boxes-ref.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "boxes-ref.c"; sourceTree = ""; }; C2843714053488AB000AE0FC /* boxes-ref.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "boxes-ref.h"; sourceTree = ""; }; @@ -450,7 +443,7 @@ C2843719053488AB000AE0FC /* bsafeKeyGen.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafeKeyGen.cpp; sourceTree = ""; }; C284371A053488AB000AE0FC /* bsafePKCS1.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafePKCS1.cpp; sourceTree = ""; }; C284371B053488AB000AE0FC /* bsafePKCS1.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bsafePKCS1.h; sourceTree = ""; }; - C284371C053488AB000AE0FC /* bsafeSymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bsafeSymmetric.cpp; sourceTree = ""; }; + C284371C053488AB000AE0FC /* bsafeSymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = bsafeSymmetric.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284371D053488AB000AE0FC /* bsobjects.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bsobjects.h; sourceTree = ""; }; C284371E053488AB000AE0FC /* castContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = castContext.cpp; sourceTree = ""; }; C284371F053488AB000AE0FC /* castContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = castContext.h; sourceTree = ""; }; @@ -461,25 +454,25 @@ C2843727053488AB000AE0FC /* cspdebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cspdebugging.h; sourceTree = ""; }; C2843728053488AB000AE0FC /* cssmplugin.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = cssmplugin.exp; sourceTree = ""; }; C2843729053488AB000AE0FC /* deriveKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = deriveKey.cpp; sourceTree = ""; }; - C284372C053488AB000AE0FC /* desContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = desContext.cpp; sourceTree = ""; }; + C284372C053488AB000AE0FC /* desContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = desContext.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284372D053488AB000AE0FC /* desContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = desContext.h; sourceTree = ""; }; C284372E053488AB000AE0FC /* DH_csp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_csp.cpp; sourceTree = ""; }; C284372F053488AB000AE0FC /* DH_csp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_csp.h; sourceTree = ""; }; C2843730053488AB000AE0FC /* DH_exchange.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_exchange.cpp; sourceTree = ""; }; C2843731053488AB000AE0FC /* DH_exchange.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_exchange.h; sourceTree = ""; }; - C2843732053488AB000AE0FC /* DH_keys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_keys.cpp; sourceTree = ""; }; - C2843733053488AB000AE0FC /* DH_keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_keys.h; sourceTree = ""; }; - C2843734053488AB000AE0FC /* DH_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DH_utils.cpp; sourceTree = ""; }; + C2843732053488AB000AE0FC /* DH_keys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = DH_keys.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + C2843733053488AB000AE0FC /* DH_keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = DH_keys.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + C2843734053488AB000AE0FC /* DH_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = DH_utils.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2843735053488AB000AE0FC /* DH_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DH_utils.h; sourceTree = ""; }; C2843736053488AB000AE0FC /* DigestContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DigestContext.cpp; sourceTree = ""; }; C2843737053488AB000AE0FC /* DigestContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DigestContext.h; sourceTree = ""; }; C2843738053488AB000AE0FC /* FEEAsymmetricContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEEAsymmetricContext.cpp; sourceTree = ""; }; C2843739053488AB000AE0FC /* FEEAsymmetricContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEEAsymmetricContext.h; sourceTree = ""; }; - C284373A053488AB000AE0FC /* FEECSPUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEECSPUtils.cpp; sourceTree = ""; }; + C284373A053488AB000AE0FC /* FEECSPUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = FEECSPUtils.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284373B053488AB000AE0FC /* FEECSPUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEECSPUtils.h; sourceTree = ""; }; - C284373C053488AB000AE0FC /* FEEKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEEKeys.cpp; sourceTree = ""; }; + C284373C053488AB000AE0FC /* FEEKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = FEEKeys.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284373D053488AB000AE0FC /* FEEKeys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEEKeys.h; sourceTree = ""; }; - C284373E053488AB000AE0FC /* FEESignatureObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FEESignatureObject.cpp; sourceTree = ""; }; + C284373E053488AB000AE0FC /* FEESignatureObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = FEESignatureObject.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284373F053488AB000AE0FC /* FEESignatureObject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FEESignatureObject.h; sourceTree = ""; }; C2843740053488AB000AE0FC /* gladmanContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = gladmanContext.cpp; sourceTree = ""; }; C2843741053488AB000AE0FC /* gladmanContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gladmanContext.h; sourceTree = ""; }; @@ -511,19 +504,19 @@ C2843760053488AC000AE0FC /* rijndael-alg-ref.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "rijndael-alg-ref.h"; sourceTree = ""; }; C2843761053488AC000AE0FC /* rijndaelApi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rijndaelApi.c; sourceTree = ""; }; C2843762053488AC000AE0FC /* rijndaelApi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rijndaelApi.h; sourceTree = ""; }; - C2843765053488AC000AE0FC /* RSA_asymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_asymmetric.cpp; sourceTree = ""; }; + C2843765053488AC000AE0FC /* RSA_asymmetric.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = RSA_asymmetric.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2843766053488AC000AE0FC /* RSA_asymmetric.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_asymmetric.h; sourceTree = ""; }; C2843767053488AC000AE0FC /* RSA_DSA_csp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_csp.cpp; sourceTree = ""; }; C2843768053488AC000AE0FC /* RSA_DSA_csp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_csp.h; sourceTree = ""; }; - C2843769053488AC000AE0FC /* RSA_DSA_keys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_keys.cpp; sourceTree = ""; }; + C2843769053488AC000AE0FC /* RSA_DSA_keys.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = RSA_DSA_keys.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284376A053488AC000AE0FC /* RSA_DSA_keys.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_keys.h; sourceTree = ""; }; - C284376B053488AC000AE0FC /* RSA_DSA_signature.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_signature.cpp; sourceTree = ""; }; + C284376B053488AC000AE0FC /* RSA_DSA_signature.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = RSA_DSA_signature.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284376C053488AC000AE0FC /* RSA_DSA_signature.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_signature.h; sourceTree = ""; }; - C284376D053488AC000AE0FC /* RSA_DSA_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RSA_DSA_utils.cpp; sourceTree = ""; }; + C284376D053488AC000AE0FC /* RSA_DSA_utils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = RSA_DSA_utils.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284376E053488AC000AE0FC /* RSA_DSA_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RSA_DSA_utils.h; sourceTree = ""; }; C2843771053488AC000AE0FC /* SHA1_MD5_Object.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SHA1_MD5_Object.cpp; sourceTree = ""; }; C2843772053488AC000AE0FC /* SHA1_MD5_Object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SHA1_MD5_Object.h; sourceTree = ""; }; - C2843775053488AC000AE0FC /* SignatureContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SignatureContext.cpp; sourceTree = ""; }; + C2843775053488AC000AE0FC /* SignatureContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SignatureContext.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2843776053488AC000AE0FC /* SignatureContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SignatureContext.h; sourceTree = ""; }; C2843777053488AC000AE0FC /* vRijndael-alg-ref.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = "vRijndael-alg-ref.c"; sourceTree = ""; }; C2843778053488AC000AE0FC /* wrapKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = wrapKey.cpp; sourceTree = ""; }; @@ -1163,7 +1156,6 @@ buildRules = ( ); dependencies = ( - 182BB345146F10ED000BF1F3 /* PBXTargetDependency */, 053910800A37724600B9E848 /* PBXTargetDependency */, ); name = libsecurity_apple_csp; @@ -1178,7 +1170,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD2550987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_csp" */; compatibilityVersion = "Xcode 3.2"; @@ -1354,11 +1346,6 @@ target = 0539107D0A37721E00B9E848 /* Copy Open Source Docs */; targetProxy = 0539107F0A37724600B9E848 /* PBXContainerItemProxy */; }; - 182BB345146F10ED000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB344146F10ED000BF1F3 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -1428,12 +1415,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446067146DE98E00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -1441,12 +1437,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446067146DE98E00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_prime.c b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_prime.c index 83730079..0f65ff3b 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/bn/bn_prime.c +++ b/OSX/libsecurity_apple_csp/open_ssl/bn/bn_prime.c @@ -157,6 +157,8 @@ BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add, BN_CTX *ctx; int checks = BN_prime_checks_for_size(bits); + BN_init(&t); + ctx=BN_CTX_new(); if (ctx == NULL) goto err; if (ret == NULL) @@ -165,8 +167,7 @@ BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add, } else rnd=ret; - BN_init(&t); -loop: +loop: /* make a random number and set the top and bottom bits */ if (add == NULL) { diff --git a/OSX/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h b/OSX/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h index 3242b5ec..b02cf890 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h +++ b/OSX/libsecurity_apple_csp/open_ssl/openssl/opensslconf.h @@ -56,6 +56,7 @@ extern "C" { #define NO_DES 1 #define NO_IDEA 1 #define NO_MDC2 1 +#define NO_MD2 1 #ifdef NDEBUG #define NO_ERR 1 diff --git a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp index 5f3b68e6..fc88a8af 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp +++ b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslAsn1.cpp @@ -37,7 +37,7 @@ #include -#define sslAsn1Debug(args...) secdebug("sslAsn1", ##args) +#define sslAsn1Debug(args...) secinfo("sslAsn1", ##args) #ifndef NDEBUG /* set to 1 to see all ASN related errors */ diff --git a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp index ca332942..c20f8e0c 100644 --- a/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp +++ b/OSX/libsecurity_apple_csp/open_ssl/opensslUtils/opensslUtils.cpp @@ -35,7 +35,7 @@ #include #include -#define sslUtilsDebug(args...) secdebug("sslUtils", ## args) +#define sslUtilsDebug(args...) secinfo("sslUtils", ## args) openSslException::openSslException( int irtn, diff --git a/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp index cfc62236..25755028 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp @@ -81,8 +81,9 @@ SSCSPDLSession::makeReferenceKey(SSCSPSession &session, KeyHandle inKeyHandle, { SSKey* sskey = new SSKey(session, inKeyHandle, outKey, inSSDatabase, inKeyAttr, inKeyLabel); + (void) sskey; // Compiler thinks this variable isn't used, but we want the side effects of creation. Tell the compiler it's okay. - secdebug("SecAccessReference", "made a new reference sskey with handle %d [%d]", sskey->keyHandle(), sskey->keyReference()); + secinfo("SecAccessReference", "made a new reference sskey with handle %d [%ld]", sskey->keyHandle(), sskey->keyReference()); } SSKey & @@ -96,7 +97,7 @@ SSCSPDLSession::lookupKey(const CssmKey &inKey) /* fetch key (this is just mapping the value in inKey.KeyData to an SSKey) */ SSKey &theKey = find(inKey); - secdebug("SecAccessReference", "looked up a sskey with handle %d [%d]", theKey.keyHandle(), theKey.keyReference()); + secinfo("SecAccessReference", "looked up a sskey with handle %d [%ld]", theKey.keyHandle(), theKey.keyReference()); #ifdef someday /* @@ -147,7 +148,7 @@ SSCSPDLSession::didChangeKeyAcl(SecurityServer::ClientSession &clientSession, else { // @@@ Should we really throw here or just continue without updating the ACL? In reality this should never happen, so let's at least log it and throw. - secdebug("keyacl", "SSCSPDLSession::didChangeKeyAcl() keyHandle: %lu not found in map", (unsigned long)keyHandle); + secinfo("keyacl", "SSCSPDLSession::didChangeKeyAcl() keyHandle: %lu not found in map", (unsigned long)keyHandle); CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); } } @@ -177,7 +178,7 @@ void ClientSessionKey::getAcl(AutoAclEntryInfoList &aclInfos, const char *selectionTag) const { - secdebug("keyacl", "ClientSessionKey::getAcl() keyHandle: %u", mKeyHandle); + secinfo("keyacl", "ClientSessionKey::getAcl() keyHandle: %u", mKeyHandle); aclInfos.allocator(mClientSession.returnAllocator); mClientSession.getKeyAcl(mKeyHandle, selectionTag, *static_cast(aclInfos), @@ -188,14 +189,14 @@ void ClientSessionKey::changeAcl(const CSSM_ACL_EDIT &aclEdit, const CSSM_ACCESS_CREDENTIALS *cred) { - secdebug("keyacl", "ClientSessionKey::changeAcl() keyHandle: %u", mKeyHandle); + secinfo("keyacl", "ClientSessionKey::changeAcl() keyHandle: %u", mKeyHandle); mClientSession.changeKeyAcl(mKeyHandle, AccessCredentials::overlay(*cred), AclEdit::overlay(aclEdit)); } void ClientSessionKey::getOwner(AutoAclOwnerPrototype &owner) const { - secdebug("keyacl", "ClientSessionKey::getOwner() keyHandle: %u", mKeyHandle); + secinfo("keyacl", "ClientSessionKey::getOwner() keyHandle: %u", mKeyHandle); owner.allocator(mClientSession.returnAllocator); mClientSession.getKeyOwner(mKeyHandle, *reinterpret_cast(static_cast(owner))); @@ -205,7 +206,7 @@ void ClientSessionKey::changeOwner(const CSSM_ACL_OWNER_PROTOTYPE &newOwner, const CSSM_ACCESS_CREDENTIALS *cred) { - secdebug("keyacl", "ClientSessionKey::changeOwner() keyHandle: %u", mKeyHandle); + secinfo("keyacl", "ClientSessionKey::changeOwner() keyHandle: %u", mKeyHandle); mClientSession.changeKeyOwner(mKeyHandle, AccessCredentials::overlay(*cred), AclOwnerPrototype::overlay(newOwner)); } diff --git a/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp index d82bb4e3..e1f7b928 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSCSPSession.cpp @@ -357,7 +357,7 @@ SSCSPSession::FreeKey(const AccessCredentials *accessCred, // 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). - secdebug("freeKey", "CSPDL FreeKey"); + secinfo("freeKey", "CSPDL FreeKey"); auto_ptr ssKey(&mSSCSPDLSession.find(ioKey)); ssKey->free(accessCred, ioKey, deleteKey); } diff --git a/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp b/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp index 3d5de0ab..b0523932 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSContext.cpp @@ -25,7 +25,7 @@ #include "SSKey.h" #include -#define ssCryptDebug(args...) secdebug("ssCrypt", ## args) +#define ssCryptDebug(args...) secinfo("ssCrypt", ## args) using namespace SecurityServer; diff --git a/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp index 40bc29fa..5ead2930 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp @@ -73,6 +73,8 @@ try } catch (...) { + // Prevent re-throw of exception. + return; } // Utility functions @@ -117,7 +119,7 @@ SSDLSession::DbCreate(const char *inDbName, db->accessRequest(inAccessRequest); db->resourceControlContext(inCredAndAclEntry); db->openParameters(inOpenParameters); - db->create(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), + db->ssCreate(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), CSSM_SERVICE_DL | CSSM_SERVICE_CSP), inDbName, inDbLocation)); db->dbInfo(NULL); @@ -139,7 +141,7 @@ SSDLSession::CreateWithBlob(const char *DbName, db->accessRequest(AccessRequest); db->resourceControlContext(NULL); db->openParameters(OpenParameters); - db->createWithBlob(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), + db->ssCreateWithBlob(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), CSSM_SERVICE_DL | CSSM_SERVICE_CSP), DbName, DbLocation), blob); @@ -160,7 +162,7 @@ SSDLSession::DbOpen(const char *inDbName, db->accessRequest(inAccessRequest); db->accessCredentials(inAccessCred); db->openParameters(inOpenParameters); - db->open(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), + db->ssOpen(DLDbIdentifier(CssmSubserviceUid(plugin.myGuid(), &version(), subserviceId(), CSSM_SERVICE_DL | CSSM_SERVICE_CSP), inDbName, inDbLocation)); outDbHandle = makeDbHandle(db); @@ -267,7 +269,7 @@ SSDLSession::DataInsert(CSSM_DB_HANDLE inDbHandle, { SSDatabase db = findDbHandle(inDbHandle); // @@@ Fix client lib. - SSUniqueRecord uniqueId = db->insert(inRecordType, inAttributes, inData, true); // @@@ Fix me + SSUniqueRecord uniqueId = db->ssInsert(inRecordType, inAttributes, inData); outUniqueId = makeSSUniqueRecord(uniqueId); // @@@ If this is a key do the right thing. } @@ -1289,7 +1291,7 @@ SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, case CSSM_APPLECSPDL_DB_COPY_BLOB: { // make the output parameters - db->copyBlob(*reinterpret_cast(outOutputParams)); + db->ssCopyBlob(*reinterpret_cast(outOutputParams)); break; } case CSSM_APPLECSPDL_DB_INSERT_WITHOUT_ENCRYPTION: @@ -1322,6 +1324,11 @@ SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, *((uint32*) *outOutputParams) = db->recodeDbToVersion(*((uint32*) inInputParams)); break; } + case CSSM_APPLECSPDL_DB_RECODE_FINISHED: + { + db->recodeFinished(); + break; + } case CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK: { db->takeFileLock(); @@ -1336,6 +1343,22 @@ SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, { db->makeBackup(); break; + } + case CSSM_APPLECSPDL_DB_MAKE_COPY: + { + db->makeCopy((const char*) inInputParams); + break; + } + case CSSM_APPLECSPDL_DB_DELETE_FILE: + { + db->deleteFile(); + break; + } + case CSSM_APPLECSPDL_DB_CLONE: + { + SSDatabase ssdb = db->ssCloneTo(*((DLDbIdentifier*) inInputParams)); + *((CSSM_DB_HANDLE*) outOutputParams) = makeDbHandle(ssdb); + break; } default: { diff --git a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp index 755d232a..e4468f4d 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp @@ -49,9 +49,9 @@ catch (...) } SSUniqueRecord -SSDatabaseImpl::insert(CSSM_DB_RECORDTYPE recordType, +SSDatabaseImpl::ssInsert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, - const CSSM_DATA *data, bool) + const CSSM_DATA *data) { SSUniqueRecord uniqueId(SSDatabase(this)); check(CSSM_DL_DataInsert(handle(), recordType, @@ -238,7 +238,7 @@ SSDatabaseImpl::commonCreate(const DLDbIdentifier &dlDbIdentifier, bool &autoCom } void -SSDatabaseImpl::create(const DLDbIdentifier &dlDbIdentifier) +SSDatabaseImpl::ssCreate(const DLDbIdentifier &dlDbIdentifier) { try { @@ -260,7 +260,7 @@ SSDatabaseImpl::create(const DLDbIdentifier &dlDbIdentifier) mSSDbHandle = mClientSession.createDb(dlDbIdentifier, cred, owner, dbParameters); CssmDataContainer dbb(allocator()); mClientSession.encodeDb(mSSDbHandle, dbb, allocator()); - secdebugfunc("integrity", "opening %s", name()); + secnotice("integrity", "opening %s", name()); Db::Impl::insert(DBBlobRelationID, NULL, &dbb); if (autoCommit) { @@ -285,13 +285,13 @@ SSDatabaseImpl::create(const DLDbIdentifier &dlDbIdentifier) } void -SSDatabaseImpl::createWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob) +SSDatabaseImpl::ssCreateWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob) { try { bool autoCommit; commonCreate(dlDbIdentifier, autoCommit); - secdebugfunc("integrity", "opening %s", name()); + secnotice("integrity", "opening %s", name()); Db::Impl::insert(DBBlobRelationID, NULL, &blob); if (autoCommit) { @@ -308,22 +308,30 @@ SSDatabaseImpl::createWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_ } void -SSDatabaseImpl::open(const DLDbIdentifier &dlDbIdentifier) +SSDatabaseImpl::ssOpen(const DLDbIdentifier &dlDbIdentifier) { - mIdentifier = dlDbIdentifier; - Db::Impl::open(); - - CssmDataContainer dbb(allocator()); - getDbBlobId(&dbb); + load(dlDbIdentifier); - secdebugfunc("integrity", "opening %s", name()); + CssmDataContainer dbb(allocator()); + getDbBlobId(&dbb); // Pull our version out of the database blob mSSDbHandle = mClientSession.decodeDb(dlDbIdentifier, AccessCredentials::overlay(accessCredentials()), dbb); } void -SSDatabaseImpl::recode(const CssmData &dbHandleArray, const CssmData &agentData) +SSDatabaseImpl::load(const DLDbIdentifier &dlDbIdentifier) { + mIdentifier = dlDbIdentifier; + Db::Impl::open(); + + CssmDataContainer dbb(allocator()); + getDbBlobId(&dbb); + + secnotice("integrity", "loading %s", name()); +} + +void +SSDatabaseImpl::ssRecode(const CssmData &dbHandleArray, const CssmData &agentData) { // Start a transaction (Implies activate()). passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, 0); @@ -375,9 +383,9 @@ SSDatabaseImpl::recodeDbToVersion(uint32 newBlobVersion) { try { if(isLocked()) { - secdebugfunc("integrity", "is currently locked"); + secnotice("integrity", "is currently locked"); } else { - secdebugfunc("integrity", "is already unlocked"); + secnotice("integrity", "is already unlocked"); } CssmDataContainer dbb(allocator()); @@ -389,18 +397,18 @@ SSDatabaseImpl::recodeDbToVersion(uint32 newBlobVersion) { dbb.clear(); // Create a newDbHandle using the master secrets from the dbBlob we are recoding to. - secdebugfunc("integrity", "recoding db with handle %d", mSSDbHandle); + secnotice("integrity", "recoding db with handle %d", mSSDbHandle); SecurityServer::DbHandle clonedDbHandle = mClientSession.recodeDbToVersion(newBlobVersion, mSSDbHandle); - secdebugfunc("integrity", "received db with handle %d", clonedDbHandle); + secnotice("integrity", "received db with handle %d", clonedDbHandle); // @@@ If the dbb changed since we fetched it we should abort or // retry the operation here. uint32 newBlobVersion = recodeHelper(clonedDbHandle, dbBlobId); - secdebugfunc("integrity", "committing transaction %d", clonedDbHandle); + secnotice("integrity", "committing transaction %d", clonedDbHandle); // Commit the transaction to the db - transaction.success(); + transaction.commit(); return newBlobVersion; } catch (...) @@ -409,6 +417,11 @@ SSDatabaseImpl::recodeDbToVersion(uint32 newBlobVersion) { } } +void +SSDatabaseImpl::recodeFinished() { + mClientSession.recodeFinished(mSSDbHandle); +} + void SSDatabaseImpl::takeFileLock() { if(mTransaction) { // you're already in the middle of a file lock. @@ -422,9 +435,9 @@ void SSDatabaseImpl::releaseFileLock(bool success) { if(mTransaction) { try { if(success) { - mTransaction->success(); + mTransaction->commit(); } - // The destructor will commit the database and re-enable autocommit (if needed) + // If we didn't commit, the destructor will roll back and re-enable autocommit delete mTransaction; mTransaction = NULL; } catch(...) { @@ -438,6 +451,25 @@ void SSDatabaseImpl::makeBackup() { passThrough(CSSM_APPLEFILEDL_MAKE_BACKUP, NULL, NULL); } +void SSDatabaseImpl::makeCopy(const char* path) { + passThrough(CSSM_APPLEFILEDL_MAKE_COPY, path, NULL); +} + +void SSDatabaseImpl::deleteFile() { + passThrough(CSSM_APPLEFILEDL_DELETE_FILE, NULL, NULL); +} + +SSDatabase SSDatabaseImpl::ssCloneTo(const DLDbIdentifier& dldbidentifier) { + makeCopy(dldbidentifier.dbName()); + SSDatabase db(mClientSession, dl(), dldbidentifier.dbName(), dldbidentifier.dbLocation()); + + db->load(dldbidentifier); + db->mSSDbHandle = mClientSession.cloneDb(dldbidentifier, mSSDbHandle); + + return db; +} + + uint32 SSDatabaseImpl::recodeHelper(SecurityServer::DbHandle clonedDbHandle, CssmClient::DbUniqueRecord& dbBlobId) { // Recode all keys @@ -463,8 +495,8 @@ uint32 SSDatabaseImpl::recodeHelper(SecurityServer::DbHandle clonedDbHandle, Css CSSM_DB_MODIFY_ATTRIBUTE_NONE); } catch (CssmError cssme) { const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "corrupt item while recoding: %d %s", (int) cssme.error, errStr); - secdebugfunc("integrity", "deleting corrupt item"); + secnotice("integrity", "corrupt item while recoding: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "deleting corrupt item"); keyBlobId->deleteRecord(); @@ -472,12 +504,12 @@ uint32 SSDatabaseImpl::recodeHelper(SecurityServer::DbHandle clonedDbHandle, Css if(keyHandle != 0) { // tell securityd not to worry about this key again try { - secdebugfunc("integrity", "releasing corrupt key"); + secnotice("integrity", "releasing corrupt key"); mClientSession.releaseKey(keyHandle); } catch(CssmError cssme) { // swallow the error const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "couldn't release corrupt key: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "couldn't release corrupt key: %d %s", (int) cssme.error, errStr); } } } @@ -486,7 +518,7 @@ uint32 SSDatabaseImpl::recodeHelper(SecurityServer::DbHandle clonedDbHandle, Css // Commit the new blob to securityd, reencode the db blob, release the // cloned db handle and commit the new blob to the db. CssmDataContainer dbb(allocator()); - secdebugfunc("integrity", "committing %d", clonedDbHandle); + secnotice("integrity", "committing %d", clonedDbHandle); mClientSession.commitDbForSync(mSSDbHandle, clonedDbHandle, dbb, allocator()); dbBlobId->modify(DBBlobRelationID, NULL, &dbb, @@ -512,7 +544,7 @@ void SSDatabaseImpl::getRecordIdentifier(CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, dest[3] = 0; } -void SSDatabaseImpl::copyBlob(CSSM_DATA &data) +void SSDatabaseImpl::ssCopyBlob(CSSM_DATA& data) { // get the blob from the database CssmDataContainer dbb(allocator()); diff --git a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h index 04ed9c05..4fefdd5e 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h +++ b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h @@ -49,12 +49,12 @@ public: const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation); virtual ~SSDatabaseImpl(); - void create(const DLDbIdentifier &dlDbIdentifier); - void createWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob); - void open(const DLDbIdentifier &dlDbIdentifier); - SSUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + void ssCreate(const DLDbIdentifier &dlDbIdentifier); + void ssCreateWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_DATA &blob); + void ssOpen(const DLDbIdentifier &dlDbIdentifier); + SSUniqueRecord ssInsert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, - const CSSM_DATA *data, bool); + const CSSM_DATA *data); void authenticate(CSSM_DB_ACCESS_TYPE inAccessRequest, const CSSM_ACCESS_CREDENTIALS *inAccessCredentials); @@ -68,7 +68,7 @@ public: void setSettings(uint32 inIdleTimeout, bool inLockOnSleep); bool isLocked(); void changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred); - void recode(const CssmData &data, const CssmData &extraData); + void ssRecode(const CssmData &data, const CssmData &extraData); @@ -76,6 +76,9 @@ public: // Returns new version uint32 recodeDbToVersion(uint32 newBlobVersion); + // Tell securityd that we're done with the upgrade operation + void recodeFinished(); + // Try to take or release the file lock on the underlying database. // You _must_ call these as a pair. They start a transaction on the // underlying DL object, and that transaction is only finished when release @@ -92,7 +95,7 @@ public: SecurityServer::DbHandle dbHandle(); void getRecordIdentifier(const CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, CSSM_DATA &data); - void copyBlob(CSSM_DATA &blob); + void ssCopyBlob(CSSM_DATA& blob); // Get the version of this database's encoding uint32 dbBlobVersion(); @@ -100,10 +103,24 @@ public: // Try to make a backup copy of this database on the filesystem void makeBackup(); + // Try to make a backup copy of this database on the filesystem + void makeCopy(const char* path); + + // Try to delete the backing file of this database + // AFter you've done this, operations might fail in strange ways. + void deleteFile(); + + // Duplicate this database to this location, and return the clone. + // For best results, use on an unlocked SSDatabase, but it should work on a locked one as well. + SSDatabase ssCloneTo(const DLDbIdentifier& dldbidentifier); + protected: CssmClient::DbUniqueRecord getDbBlobId(CssmDataContainer *dbb = NULL); void commonCreate (const DLDbIdentifier &dlDbIdentifier, bool &autocommit); + // Load the database from disk, but don't talk with securityd about it + void load(const DLDbIdentifier &dlDbIdentifier); + static uint32 getDbVersionFromBlob(const CssmData& dbb); uint32 recodeHelper(SecurityServer::DbHandle clonedDbHandle, CssmClient::DbUniqueRecord& dbBlobId); diff --git a/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp b/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp index 69c57b51..fec984c5 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp @@ -124,9 +124,7 @@ mClientSession(session.clientSession()) attributes.add(KeySchema::Unwrap, header.useFor(CSSM_KEYUSE_ANY | CSSM_KEYUSE_UNWRAP)); - // @@@ Fixme - mUniqueId = inSSDatabase->insert(mRecordType, &attributes, &blob, - true); + mUniqueId = inSSDatabase->ssInsert(mRecordType, &attributes, &blob); } header.cspGuid(session.plugin.myGuid()); // Set the csp guid to me. @@ -290,7 +288,7 @@ SSKey::keyHandle() clientSession().decodeKey(mUniqueId->database().dbHandle(), blob, dummyHeader); - secdebugfunc("SecAccessReference", "decoded a new key into handle %d [reference %d]", mKeyHandle, keyReference()); + secinfo("SecAccessReference", "decoded a new key into handle %d [reference %ld]", mKeyHandle, keyReference()); // @@@ Check decoded header against returned header } @@ -336,7 +334,7 @@ SSKey::didChangeAcl() { if (mUniqueId == true) { - secdebug("keyacl", "SSKey::didChangeAcl() keyHandle: %lu updating DL entry", (unsigned long)mKeyHandle); + secinfo("keyacl", "SSKey::didChangeAcl() keyHandle: %lu updating DL entry", (unsigned long)mKeyHandle); // The key is persistent, make the change on disk. CssmDataContainer keyBlob(mAllocator); clientSession().encodeKey(keyHandle(), keyBlob); @@ -344,6 +342,6 @@ SSKey::didChangeAcl() } else { - secdebug("keyacl", "SSKey::didChangeAcl() keyHandle: %lu transient key no update done", (unsigned long)mKeyHandle); + secinfo("keyacl", "SSKey::didChangeAcl() keyHandle: %lu transient key no update done", (unsigned long)mKeyHandle); } } diff --git a/OSX/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj b/OSX/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj index c5a74d7c..0e8ed5a1 100644 --- a/OSX/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_apple_cspdl/libsecurity_apple_cspdl.xcodeproj/project.pbxproj @@ -29,13 +29,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 182BB348146F10F6000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; 184460DD146E7DF300B12992 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 184460D8146E7DF300B12992 /* libsecurity_cdsa_plugin.xcodeproj */; @@ -60,19 +53,19 @@ 4C6AA9D10535FDA6006E3284 /* CSPDLDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSPDLDatabase.h; sourceTree = ""; }; 4C6AA9D20535FDA6006E3284 /* CSPDLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSPDLPlugin.cpp; sourceTree = ""; }; 4C6AA9D30535FDA6006E3284 /* CSPDLPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSPDLPlugin.h; sourceTree = ""; }; - 4C6AA9D40535FDA6006E3284 /* SSContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSContext.cpp; sourceTree = ""; }; + 4C6AA9D40535FDA6006E3284 /* SSContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SSContext.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C6AA9D50535FDA6006E3284 /* SSContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSContext.h; sourceTree = ""; }; - 4C6AA9D60535FDA6006E3284 /* SSCSPDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSCSPDLSession.cpp; sourceTree = ""; }; + 4C6AA9D60535FDA6006E3284 /* SSCSPDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SSCSPDLSession.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C6AA9D70535FDA6006E3284 /* SSCSPDLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSCSPDLSession.h; sourceTree = ""; }; - 4C6AA9D80535FDA6006E3284 /* SSCSPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSCSPSession.cpp; sourceTree = ""; }; + 4C6AA9D80535FDA6006E3284 /* SSCSPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SSCSPSession.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C6AA9D90535FDA6006E3284 /* SSCSPSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSCSPSession.h; sourceTree = ""; }; - 4C6AA9DA0535FDA6006E3284 /* SSDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSDatabase.cpp; sourceTree = ""; }; + 4C6AA9DA0535FDA6006E3284 /* SSDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SSDatabase.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C6AA9DB0535FDA6006E3284 /* SSDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSDatabase.h; sourceTree = ""; }; 4C6AA9DC0535FDA6006E3284 /* SSDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSDLSession.cpp; sourceTree = ""; }; 4C6AA9DD0535FDA6006E3284 /* SSDLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSDLSession.h; sourceTree = ""; }; 4C6AA9DE0535FDA6006E3284 /* SSFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSFactory.cpp; sourceTree = ""; }; 4C6AA9DF0535FDA6006E3284 /* SSFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSFactory.h; sourceTree = ""; }; - 4C6AA9E00535FDA6006E3284 /* SSKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SSKey.cpp; sourceTree = ""; }; + 4C6AA9E00535FDA6006E3284 /* SSKey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SSKey.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C6AA9E10535FDA6006E3284 /* SSKey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SSKey.h; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_apple_cspdl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_apple_cspdl.a; sourceTree = BUILT_PRODUCTS_DIR; }; C2196B5C053B598C005808D4 /* AppleCSPDLBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AppleCSPDLBuiltin.cpp; path = lib/AppleCSPDLBuiltin.cpp; sourceTree = ""; }; @@ -199,7 +192,6 @@ buildRules = ( ); dependencies = ( - 182BB349146F10F6000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_apple_cspdl; productInstallPath = /usr/local/lib; @@ -213,7 +205,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD26A0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_cspdl" */; compatibilityVersion = "Xcode 3.2"; @@ -271,14 +263,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 182BB349146F10F6000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB348146F10F6000BF1F3 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ C27AD2640987FCDC001272E0 /* Debug */ = { isa = XCBuildConfiguration; @@ -308,6 +292,10 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184460CD146E7B7B00B12992 /* debug.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + ENABLE_TESTABILITY = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -315,6 +303,8 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184460CF146E7B7B00B12992 /* release.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; }; name = Release; }; diff --git a/OSX/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj b/OSX/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj index 7d0ef6a4..0d7ea931 100644 --- a/OSX/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_apple_file_dl/libsecurity_apple_file_dl.xcodeproj/project.pbxproj @@ -13,13 +13,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 182BB34C146F1102000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; 184460F9146E818D00B12992 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 184460F4146E818D00B12992 /* libsecurity_cdsa_plugin.xcodeproj */; @@ -139,7 +132,6 @@ buildRules = ( ); dependencies = ( - 182BB34D146F1102000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_apple_file_dl; productInstallPath = /usr/local/lib; @@ -153,7 +145,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD27B0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_file_dl" */; compatibilityVersion = "Xcode 3.2"; @@ -200,14 +192,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 182BB34D146F1102000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB34C146F1102000BF1F3 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ C27AD2780987FCDC001272E0 /* Debug */ = { isa = XCBuildConfiguration; @@ -229,12 +213,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184460E8146E808700B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -242,12 +235,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184460E8146E808700B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_apple_x509_cl/TODO b/OSX/libsecurity_apple_x509_cl/TODO deleted file mode 100644 index de81bb21..00000000 --- a/OSX/libsecurity_apple_x509_cl/TODO +++ /dev/null @@ -1 +0,0 @@ -Things TODO in AppleX509CL diff --git a/OSX/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp b/OSX/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp index 41002892..3c739ab3 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp +++ b/OSX/libsecurity_apple_x509_cl/lib/AppleX509CLSession.cpp @@ -41,13 +41,13 @@ AppleX509CLSession::~AppleX509CLSession() /* free leftover contents of cache and query maps */ CLCachedEntry *cachedCert = cacheMap.removeFirstEntry(); while(cachedCert != NULL) { - secdebug("clDetach", "CL detach: deleting a cached Cert\n"); + secinfo("clDetach", "CL detach: deleting a cached Cert\n"); delete cachedCert; cachedCert = cacheMap.removeFirstEntry(); } CLQuery *query = queryMap.removeFirstEntry(); while(query != NULL) { - secdebug("clDetach", "CL detach: deleting a cached query\n"); + secinfo("clDetach", "CL detach: deleting a cached query\n"); delete query; query = queryMap.removeFirstEntry(); } diff --git a/OSX/libsecurity_apple_x509_cl/lib/cldebugging.h b/OSX/libsecurity_apple_x509_cl/lib/cldebugging.h index 79709bb1..fca6af6f 100644 --- a/OSX/libsecurity_apple_x509_cl/lib/cldebugging.h +++ b/OSX/libsecurity_apple_x509_cl/lib/cldebugging.h @@ -29,10 +29,10 @@ #ifdef NDEBUG /* this actually compiles to nothing */ -#define clErrorLog(args...) secdebug("clError", ## args) +#define clErrorLog(args...) secinfo("clError", ## args) #else #define clErrorLog(args...) printf(args) #endif -#define clFieldLog(args...) secdebug("clField", ## args) +#define clFieldLog(args...) secinfo("clField", ## args) #endif /* _CLDEBUGGING_H_ */ diff --git a/OSX/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj b/OSX/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj index d16472c0..15608529 100644 --- a/OSX/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_apple_x509_cl/libsecurity_apple_x509_cl.xcodeproj/project.pbxproj @@ -49,13 +49,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 182BB350146F110B000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; 1844610C146E84E500B12992 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 18446107146E84E500B12992 /* libsecurity_cdsa_plugin.xcodeproj */; @@ -86,7 +79,7 @@ C284365A053485B1000AE0FC /* AppleX509CL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CL.cpp; sourceTree = ""; }; C284365B053485B1000AE0FC /* AppleX509CL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleX509CL.h; sourceTree = ""; }; C284365C053485B1000AE0FC /* AppleX509CLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CLPlugin.cpp; sourceTree = ""; }; - C284365D053485B1000AE0FC /* AppleX509CLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleX509CLSession.cpp; sourceTree = ""; }; + C284365D053485B1000AE0FC /* AppleX509CLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleX509CLSession.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C284365E053485B1000AE0FC /* AppleX509CLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleX509CLSession.h; sourceTree = ""; }; C284365F053485B1000AE0FC /* CertFields.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CertFields.cpp; sourceTree = ""; }; C2843660053485B1000AE0FC /* CLCachedEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLCachedEntry.cpp; sourceTree = ""; }; @@ -95,7 +88,7 @@ C2843663053485B1000AE0FC /* CLCertExtensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLCertExtensions.h; sourceTree = ""; }; C2843664053485B1000AE0FC /* CLCrlExtensions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLCrlExtensions.cpp; sourceTree = ""; }; C2843665053485B1000AE0FC /* CLCrlExtensions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLCrlExtensions.h; sourceTree = ""; }; - C2843666053485B1000AE0FC /* cldebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cldebugging.h; sourceTree = ""; }; + C2843666053485B1000AE0FC /* cldebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = cldebugging.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; C2843667053485B1000AE0FC /* CLFieldsCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLFieldsCommon.cpp; sourceTree = ""; }; C2843668053485B1000AE0FC /* CLFieldsCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLFieldsCommon.h; sourceTree = ""; }; C2843669053485B1000AE0FC /* clNameUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clNameUtils.cpp; sourceTree = ""; }; @@ -269,7 +262,6 @@ buildRules = ( ); dependencies = ( - 182BB351146F110B000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_apple_x509_cl; productInstallPath = /usr/local/lib; @@ -302,7 +294,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD28D0987FCDC001272E0 /* Build configuration list for PBXProject "libsecurity_apple_x509_cl" */; compatibilityVersion = "Xcode 3.2"; @@ -390,11 +382,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 182BB351146F110B000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB350146F110B000BF1F3 /* PBXContainerItemProxy */; - }; C2AAE44B053B54E2009142E3 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4CA1FEBD052A3C8100F22E42 /* libsecurity_apple_x509_cl */; @@ -445,12 +432,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446100146E82B800B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -458,12 +454,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446100146E82B800B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp b/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp index 165228a5..62b6f7b8 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp @@ -40,8 +40,8 @@ #include #include -#define tpTimeDbg(args...) secdebug("tpTime", ## args) -#define tpCertInfoDbg(args...) secdebug("tpCert", ## args) +#define tpTimeDbg(args...) secinfo("tpTime", ## args) +#define tpCertInfoDbg(args...) secinfo("tpCert", ## args) static const TPClItemCalls tpCertClCalls = { diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp index be25daea..3aee72f9 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpCredRequest.cpp @@ -34,7 +34,7 @@ #include #include -#define tpCredDebug(args...) secdebug("tpCred", ## args) +#define tpCredDebug(args...) secinfo("tpCred", ## args) /* * Build up a CSSM_X509_NAME from an arbitrary list of name/OID pairs. diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpdebugging.h b/OSX/libsecurity_apple_x509_tp/lib/tpdebugging.h index 91032aa6..eb9cc529 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpdebugging.h +++ b/OSX/libsecurity_apple_x509_tp/lib/tpdebugging.h @@ -27,9 +27,8 @@ #include /* If TP_USE_SYSLOG is defined and not 0, use syslog() for debug - * logging in addition to invoking the secdebug macro (which, as of - * Snow Leopard, emits a static dtrace probe instead of an actual - * log message.) + * logging in addition to invoking the secinfo macro (which, as of + * 10.11, emits a os_log message of a syslog message.) */ #ifndef TP_USE_SYSLOG #define TP_USE_SYSLOG 0 @@ -37,31 +36,31 @@ #if TP_USE_SYSLOG #include -#define tp_secdebug(scope, format...) \ +#define tp_secinfo(scope, format...) \ { \ syslog(LOG_NOTICE, format); \ - secdebug(scope, format); \ + secinfo(scope, format); \ } #else -#define tp_secdebug(scope, format...) \ - secdebug(scope, format) +#define tp_secinfo(scope, format...) \ + secinfo(scope, format) #endif #ifdef NDEBUG /* this actually compiles to nothing */ -#define tpErrorLog(args...) tp_secdebug("tpError", ## args) +#define tpErrorLog(args...) tp_secinfo("tpError", ## args) #else #define tpErrorLog(args...) printf(args) #endif -#define tpDebug(args...) tp_secdebug("tpDebug", ## args) -#define tpDbDebug(args...) tp_secdebug("tpDbDebug", ## args) -#define tpCrlDebug(args...) tp_secdebug("tpCrlDebug", ## args) -#define tpPolicyError(args...) tp_secdebug("tpPolicy", ## args) -#define tpVfyDebug(args...) tp_secdebug("tpVfyDebug", ## args) -#define tpAnchorDebug(args...) tp_secdebug("tpAnchorDebug", ## args) -#define tpOcspDebug(args...) tp_secdebug("tpOcsp", ## args) -#define tpOcspCacheDebug(args...) tp_secdebug("tpOcspCache", ## args) -#define tpTrustSettingsDbg(args...) tp_secdebug("tpTrustSettings", ## args) +#define tpDebug(args...) tp_secinfo("tpDebug", ## args) +#define tpDbDebug(args...) tp_secinfo("tpDbDebug", ## args) +#define tpCrlDebug(args...) tp_secinfo("tpCrlDebug", ## args) +#define tpPolicyError(args...) tp_secinfo("tpPolicy", ## args) +#define tpVfyDebug(args...) tp_secinfo("tpVfyDebug", ## args) +#define tpAnchorDebug(args...) tp_secinfo("tpAnchorDebug", ## args) +#define tpOcspDebug(args...) tp_secinfo("tpOcsp", ## args) +#define tpOcspCacheDebug(args...) tp_secinfo("tpOcspCache", ## args) +#define tpTrustSettingsDbg(args...) tp_secinfo("tpTrustSettings", ## args) #endif /* _TPDEBUGGING_H_ */ diff --git a/OSX/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj b/OSX/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj index f06f458e..649180fa 100644 --- a/OSX/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_apple_x509_tp/libsecurity_apple_x509_tp.xcodeproj/project.pbxproj @@ -46,13 +46,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 182BB354146F1117000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; 18446123146E86A900B12992 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 1844611E146E86A900B12992 /* libsecurity_cdsa_plugin.xcodeproj */; @@ -93,16 +86,16 @@ C2B5C4D90534C6AA00AF53F5 /* certGroupUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = certGroupUtils.cpp; sourceTree = ""; }; C2B5C4DA0534C6AA00AF53F5 /* certGroupUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = certGroupUtils.h; sourceTree = ""; }; C2B5C4DF0534C6AA00AF53F5 /* tpCertGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 8; lastKnownFileType = sourcecode.cpp.cpp; path = tpCertGroup.cpp; sourceTree = ""; tabWidth = 8; usesTabs = 1; }; - C2B5C4E00534C6AA00AF53F5 /* TPCertInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPCertInfo.cpp; sourceTree = ""; }; + C2B5C4E00534C6AA00AF53F5 /* TPCertInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TPCertInfo.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2B5C4E10534C6AA00AF53F5 /* TPCertInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPCertInfo.h; sourceTree = ""; }; - C2B5C4E20534C6AA00AF53F5 /* tpCredRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpCredRequest.cpp; sourceTree = ""; }; + C2B5C4E20534C6AA00AF53F5 /* tpCredRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = tpCredRequest.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2B5C4E30534C6AA00AF53F5 /* TPCrlInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPCrlInfo.cpp; sourceTree = ""; }; C2B5C4E40534C6AA00AF53F5 /* TPCrlInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPCrlInfo.h; sourceTree = ""; }; C2B5C4E50534C6AA00AF53F5 /* tpCrlVerify.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpCrlVerify.cpp; sourceTree = ""; }; C2B5C4E60534C6AA00AF53F5 /* tpCrlVerify.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpCrlVerify.h; sourceTree = ""; }; C2B5C4E70534C6AA00AF53F5 /* TPDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPDatabase.cpp; sourceTree = ""; }; C2B5C4E80534C6AA00AF53F5 /* TPDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPDatabase.h; sourceTree = ""; }; - C2B5C4E90534C6AA00AF53F5 /* tpdebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpdebugging.h; sourceTree = ""; }; + C2B5C4E90534C6AA00AF53F5 /* tpdebugging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = tpdebugging.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; C2B5C4EA0534C6AA00AF53F5 /* TPNetwork.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TPNetwork.cpp; sourceTree = ""; }; C2B5C4EB0534C6AA00AF53F5 /* TPNetwork.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TPNetwork.h; sourceTree = ""; }; C2B5C4EC0534C6AA00AF53F5 /* tpPolicies.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpPolicies.cpp; sourceTree = ""; }; @@ -256,7 +249,6 @@ buildRules = ( ); dependencies = ( - 182BB355146F1117000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_apple_x509_tp; productInstallPath = /usr/local/lib; @@ -270,7 +262,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD29B0987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_apple_x509_tp" */; compatibilityVersion = "Xcode 3.2"; @@ -337,14 +329,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 182BB355146F1117000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB354146F1117000BF1F3 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ C27AD2980987FCDD001272E0 /* Debug */ = { isa = XCBuildConfiguration; @@ -366,13 +350,22 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1844611C146E85EA00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -380,13 +373,20 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1844611C146E85EA00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_asn1/config/base.xcconfig b/OSX/libsecurity_asn1/config/base.xcconfig index ea15367d..300d8fb7 100644 --- a/OSX/libsecurity_asn1/config/base.xcconfig +++ b/OSX/libsecurity_asn1/config/base.xcconfig @@ -12,6 +12,7 @@ COPY_PHASE_STRIP = NO STRIP_STYLE = debugging STRIP_INSTALLED_PRODUCT = NO -ARCHS = $(ARCHS_STANDARD_32_64_BIT) +ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_asn1/config/lib.xcconfig b/OSX/libsecurity_asn1/config/lib.xcconfig index 2373abe7..644ba9df 100644 --- a/OSX/libsecurity_asn1/config/lib.xcconfig +++ b/OSX/libsecurity_asn1/config/lib.xcconfig @@ -5,22 +5,16 @@ EXECUTABLE_PREFIX = CODE_SIGN_IDENTITY = -HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) +HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../include $(PROJECT_DIR)/../utilities $(BUILT_PRODUCTS_DIR)/derived_src $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) -HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) +HEADER_SEARCH_PATHS[sdk=embedded*] = HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../sec $(PROJECT_DIR)/../utilities $(BUILT_PRODUCTS_DIR)/usr/local/include $(inherited) -#include "/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig" +INSTALL_PATH = /usr/local/lib -// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be -INSTALL_PATH_ACTUAL = /usr/local/lib +SKIP_INSTALL = YES -// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable -INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL) - -// Use $(INSTALL_PATH_PREFIX) instead of $(SDKROOT) as a prefix for other -// variables as appropriate -PUBLIC_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include/security_asn1 -PRIVATE_HEADERS_FOLDER_PATH = $(INSTALL_PATH_PREFIX)/usr/local/include/security_asn1 +PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_asn1 +PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/security_asn1 ALWAYS_SEARCH_USER_PATHS = NO @@ -36,4 +30,4 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES GCC_WARN_ABOUT_RETURN_TYPE = YES GCC_WARN_UNUSED_VARIABLE = YES -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator diff --git a/OSX/libsecurity_asn1/lib/SecAsn1Types.h b/OSX/libsecurity_asn1/lib/SecAsn1Types.h index d24d4821..9cb362b9 100644 --- a/OSX/libsecurity_asn1/lib/SecAsn1Types.h +++ b/OSX/libsecurity_asn1/lib/SecAsn1Types.h @@ -44,6 +44,10 @@ #include #include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR /* @@@ We need something that tells us which platform we are building for that let's us distinguish if we are doing an emulator build. */ @@ -244,4 +248,6 @@ typedef SecAsn1TemplateChooser * SecAsn1TemplateChooserPtr; CF_ASSUME_NONNULL_END +#pragma clang diagnostic pop + #endif /* _SEC_ASN1_TYPES_H_ */ diff --git a/OSX/libsecurity_asn1/lib/plarena.h b/OSX/libsecurity_asn1/lib/plarena.h index 359e3851..ef8a5d6a 100644 --- a/OSX/libsecurity_asn1/lib/plarena.h +++ b/OSX/libsecurity_asn1/lib/plarena.h @@ -123,7 +123,7 @@ struct PLArenaPool { PR_BEGIN_MACRO \ PLArena *_a = (pool)->current; \ PRUword _q = (PRUword)p + size + incr; /*__APPLE__ */ \ - if ((p < p + size) && (_q > p) && (_q > p + size) && /*__APPLE__ avoid overflow in _q*/ \ + if ((p < p + size) && (_q > (PRUword)p) && (_q > (PRUword)p + size) && /*__APPLE__ avoid overflow in _q*/ \ _a->avail == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \ _q <= PL_ARENA_ALIGN(pool,_q) && /*__APPLE__ avoid overflow from alignment*/ \ _a->limit >= PL_ARENA_ALIGN(pool,_q)) { /* __APPLE__ expanded buffer within arena*/ \ diff --git a/OSX/libsecurity_asn1/lib/secasn1d.c b/OSX/libsecurity_asn1/lib/secasn1d.c index 456309ab..4ff12eef 100644 --- a/OSX/libsecurity_asn1/lib/secasn1d.c +++ b/OSX/libsecurity_asn1/lib/secasn1d.c @@ -1069,7 +1069,9 @@ sec_asn1d_check_and_subtract_length (unsigned long *remaining, PORT_Assert(cx); if (!remaining || !cx) { PORT_SetError (SEC_ERROR_INVALID_ARGS); - cx->status = decodeError; + if(cx) { + cx->status = decodeError; + } return PR_FALSE; } if (*remaining < consumed) { diff --git a/OSX/libsecurity_asn1/lib/secasn1e.c b/OSX/libsecurity_asn1/lib/secasn1e.c index 5f383ade..e695972f 100644 --- a/OSX/libsecurity_asn1/lib/secasn1e.c +++ b/OSX/libsecurity_asn1/lib/secasn1e.c @@ -40,8 +40,6 @@ #include "secasn1.h" -#include - typedef enum { beforeHeader, duringContents, @@ -1343,16 +1341,13 @@ SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, SEC_ASN1EncoderContext *cx; our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); - if (our_pool == NULL) { - syslog(LOG_ERR,"SEC_ASN1EncoderStart: failed to create new arena"); - return NULL; - } + if (our_pool == NULL) + return NULL; cx = (SEC_ASN1EncoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); if (cx == NULL) { - syslog(LOG_ERR,"SEC_ASN1EncoderStart: failed to alloc"); - PORT_FreeArena (our_pool, PR_FALSE); - return NULL; + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; } cx->our_pool = our_pool; @@ -1367,9 +1362,8 @@ SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, * Trouble initializing (probably due to failed allocations) * requires that we just give up. */ - syslog(LOG_ERR, "SEC_ASN1EncoderStart: unable to initialize state"); - PORT_FreeArena (our_pool, PR_FALSE); - return NULL; + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; } return cx; @@ -1469,9 +1463,6 @@ SEC_ASN1Encode (const void *src, const SecAsn1Template *theTemplate, rv = SEC_ASN1EncoderUpdate (ecx, NULL, 0); - if (rv != SECSuccess) - syslog(LOG_ERR,"SEC_ASN1Encode: encode failure"); - SEC_ASN1EncoderFinish (ecx); return rv; } @@ -1573,23 +1564,17 @@ SEC_ASN1EncodeItem (PRArenaPool *poolp, SecAsn1Item *dest, const void *src, encoding_length = 0; rv = SEC_ASN1Encode (src, theTemplate, sec_asn1e_encode_item_count, &encoding_length); - if (rv != SECSuccess) { - syslog(LOG_ERR, "SEC_ASN1EncodeItem: Encode failed %d", rv); - return NULL; - } + if (rv != SECSuccess) + return NULL; dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); - if (dest == NULL) { - syslog(LOG_ERR, "SEC_ASN1EncodeItem: allocate failure"); - return NULL; - } + if (dest == NULL) + return NULL; /* XXX necessary? This really just checks for a bug in the allocate fn */ PORT_Assert (dest->Data != NULL); - if (dest->Data == NULL) { - syslog(LOG_ERR, "SEC_ASN1EncodeItem: data allocate failure"); - return NULL; - } + if (dest->Data == NULL) + return NULL; dest->Length = 0; (void) SEC_ASN1Encode (src, theTemplate, sec_asn1e_encode_item_store, dest); diff --git a/OSX/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj b/OSX/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj index 200a8ddb..ca22c61f 100644 --- a/OSX/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_asn1/libsecurity_asn1.xcodeproj/project.pbxproj @@ -6,66 +6,151 @@ objectVersion = 46; objects = { +/* Begin PBXAggregateTarget section */ + D46B08791C8FCA5000B5939A /* libASN1Install */ = { + isa = PBXAggregateTarget; + buildConfigurationList = D46B087C1C8FCA5100B5939A /* Build configuration list for PBXAggregateTarget "libASN1Install" */; + buildPhases = ( + D46B087D1C8FCA5800B5939A /* Copy Static Library File */, + D46B087E1C8FCA5B00B5939A /* Copy Headers */, + ); + dependencies = ( + D46B08A41C8FCBA000B5939A /* PBXTargetDependency */, + ); + name = libASN1Install; + productName = libASN1Install; + }; +/* End PBXAggregateTarget section */ + /* Begin PBXBuildFile section */ - 18312F9714E99A3F00F0BCAC /* SecNssCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434290534D3B800F287B2 /* SecNssCoder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1885B45314D9BB1A00519375 /* SecNssCoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434280534D3B800F287B2 /* SecNssCoder.cpp */; }; 18B6B2A714DB73A000EDDE5F /* secErrorStr.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434270534D3B800F287B2 /* secErrorStr.c */; }; 4C28246B0F1BC75800CAADEC /* oidsocsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C2824670F1BC75800CAADEC /* oidsocsp.c */; }; - 4C28246C0F1BC75800CAADEC /* oidsocsp.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2824680F1BC75800CAADEC /* oidsocsp.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA8220D38041D00BAE6A2 /* SecAsn1Coder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0545C7B806502D1100543007 /* SecAsn1Coder.c */; }; - 795CA8230D38041D00BAE6A2 /* SecAsn1Coder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0545C7B906502D1100543007 /* SecAsn1Coder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA8240D38041D00BAE6A2 /* SecAsn1Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433F80534D3B800F287B2 /* SecAsn1Templates.c */; }; - 795CA8250D38041D00BAE6A2 /* SecAsn1Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 795CA8260D38041D00BAE6A2 /* SecAsn1Types.h in Headers */ = {isa = PBXBuildFile; fileRef = 0554F5B609892C980085E7C5 /* SecAsn1Types.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA8270D38041D00BAE6A2 /* certExtensionTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FA0534D3B800F287B2 /* certExtensionTemplates.c */; }; - 795CA8280D38041D00BAE6A2 /* certExtensionTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA8290D38041D00BAE6A2 /* csrTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FC0534D3B800F287B2 /* csrTemplates.c */; }; - 795CA82A0D38041D00BAE6A2 /* csrTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FD0534D3B800F287B2 /* csrTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA82B0D38041D00BAE6A2 /* keyTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6433FE0534D3B800F287B2 /* keyTemplates.c */; }; - 795CA82C0D38041D00BAE6A2 /* keyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0502B640068A5920006168D5 /* keyTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA82D0D38041D00BAE6A2 /* nameTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434000534D3B800F287B2 /* nameTemplates.c */; }; - 795CA82E0D38041D00BAE6A2 /* nameTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434010534D3B800F287B2 /* nameTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA82F0D38041D00BAE6A2 /* nsprPortX.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434020534D3B800F287B2 /* nsprPortX.c */; }; 795CA8300D38041D00BAE6A2 /* nssUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434060534D3B800F287B2 /* nssUtils.c */; }; - 795CA8310D38041D00BAE6A2 /* nssUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434070534D3B800F287B2 /* nssUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA8320D38041D00BAE6A2 /* ocspTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 0502BF9A068B51E3006168D5 /* ocspTemplates.c */; }; - 795CA8330D38041D00BAE6A2 /* ocspTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA8350D38041D00BAE6A2 /* secasn1d.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434210534D3B800F287B2 /* secasn1d.c */; }; 795CA8360D38041D00BAE6A2 /* secasn1e.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434220534D3B800F287B2 /* secasn1e.c */; }; 795CA8380D38041D00BAE6A2 /* secasn1u.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C6434240534D3B800F287B2 /* secasn1u.c */; }; 795CA8390D38041D00BAE6A2 /* X509Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64342D0534D3B800F287B2 /* X509Templates.c */; }; - 795CA83A0D38041D00BAE6A2 /* X509Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64342E0534D3B800F287B2 /* X509Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CA83B0D38041D00BAE6A2 /* osKeyTemplates.c in Sources */ = {isa = PBXBuildFile; fileRef = 0504B16106517A730011D5F5 /* osKeyTemplates.c */; }; - 795CA83C0D38041D00BAE6A2 /* osKeyTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 0504B16206517A730011D5F5 /* osKeyTemplates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CAAD10D3BEDBB00BAE6A2 /* pkcs7Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 795CAACD0D3BEDBB00BAE6A2 /* pkcs7Templates.c */; }; - 795CAAD20D3BEDBB00BAE6A2 /* pkcs7Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; 795CAAD30D3BEDBB00BAE6A2 /* pkcs12Templates.c in Sources */ = {isa = PBXBuildFile; fileRef = 795CAACF0D3BEDBB00BAE6A2 /* pkcs12Templates.c */; }; - 795CAAD40D3BEDBB00BAE6A2 /* pkcs12Templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 798B80C10D3E8B6700AC1D04 /* secasn1.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434200534D3B800F287B2 /* secasn1.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 798B80E00D3E8BFC00AC1D04 /* secasn1t.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434230534D3B800F287B2 /* secasn1t.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79BDD2D10D60CE82000D84D3 /* plarenas.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340C0534D3B800F287B2 /* plarenas.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD2ED0D60CEF5000D84D3 /* prtypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64341E0534D3B800F287B2 /* prtypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD2F60D60CF24000D84D3 /* prcpucfg.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340F0534D3B800F287B2 /* prcpucfg.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD2FC0D60CF66000D84D3 /* secerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434260534D3B800F287B2 /* secerr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3020D60CFC9000D84D3 /* protypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64341B0534D3B800F287B2 /* protypes.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD30C0D60D0E5000D84D3 /* seccomon.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434250534D3B800F287B2 /* seccomon.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3100D60D116000D84D3 /* plstr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340D0534D3B800F287B2 /* plstr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3110D60D116000D84D3 /* prlog.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434170534D3B800F287B2 /* prlog.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD33F0D60D29A000D84D3 /* prerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434130534D3B800F287B2 /* prerror.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3420D60D2B2000D84D3 /* prerr.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434120534D3B800F287B2 /* prerr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD3490D60D4A4000D84D3 /* prbit.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340E0534D3B800F287B2 /* prbit.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 79BDD34A0D60D4A4000D84D3 /* prmem.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C6434190534D3B800F287B2 /* prmem.h */; settings = {ATTRIBUTES = (Private, ); }; }; 79EF5A780D3C1984009F5270 /* oidsalg.c in Sources */ = {isa = PBXBuildFile; fileRef = 79EF5A730D3C1984009F5270 /* oidsalg.c */; }; - 79EF5A790D3C1984009F5270 /* oidsalg.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A740D3C1984009F5270 /* oidsalg.h */; settings = {ATTRIBUTES = (Public, ); }; }; 79EF5A7A0D3C1984009F5270 /* oidsattr.c in Sources */ = {isa = PBXBuildFile; fileRef = 79EF5A750D3C1984009F5270 /* oidsattr.c */; }; - 79EF5A7B0D3C1984009F5270 /* oidsattr.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A760D3C1984009F5270 /* oidsattr.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79EF5A7C0D3C1984009F5270 /* oidsbase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A770D3C1984009F5270 /* oidsbase.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 79EF5BA30D3D6EF4009F5270 /* secport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64342B0534D3B800F287B2 /* secport.h */; settings = {ATTRIBUTES = (Private, ); }; }; 79EF5BA50D3D6EF8009F5270 /* secport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64342A0534D3B800F287B2 /* secport.c */; }; 79EF5BC90D3D6F44009F5270 /* plarena.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C64340A0534D3B800F287B2 /* plarena.c */; }; - 79EF5BCA0D3D6F44009F5270 /* plarena.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C64340B0534D3B800F287B2 /* plarena.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D46B08801C8FCABF00B5939A /* SecAsn1Coder.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 0545C7B906502D1100543007 /* SecAsn1Coder.h */; }; + D46B08811C8FCABF00B5939A /* SecAsn1Templates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6433F90534D3B800F287B2 /* SecAsn1Templates.h */; }; + D46B08821C8FCABF00B5939A /* SecAsn1Types.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 0554F5B609892C980085E7C5 /* SecAsn1Types.h */; }; + D46B08831C8FCABF00B5939A /* secasn1t.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434230534D3B800F287B2 /* secasn1t.h */; }; + D46B08841C8FCAE400B5939A /* certExtensionTemplates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FB0534D3B800F287B2 /* certExtensionTemplates.h */; }; + D46B08851C8FCAE400B5939A /* csrTemplates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FD0534D3B800F287B2 /* csrTemplates.h */; }; + D46B08861C8FCAE400B5939A /* keyTemplates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 0502B640068A5920006168D5 /* keyTemplates.h */; }; + D46B08871C8FCAE400B5939A /* nameTemplates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434010534D3B800F287B2 /* nameTemplates.h */; }; + D46B08881C8FCAE400B5939A /* pkcs7Templates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 795CAACE0D3BEDBB00BAE6A2 /* pkcs7Templates.h */; }; + D46B08891C8FCAE400B5939A /* pkcs12Templates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 795CAAD00D3BEDBB00BAE6A2 /* pkcs12Templates.h */; }; + D46B088A1C8FCAE400B5939A /* ocspTemplates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6433FF0534D3B800F287B2 /* ocspTemplates.h */; }; + D46B088B1C8FCAE400B5939A /* X509Templates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64342E0534D3B800F287B2 /* X509Templates.h */; }; + D46B088C1C8FCAE400B5939A /* osKeyTemplates.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 0504B16206517A730011D5F5 /* osKeyTemplates.h */; }; + D46B088D1C8FCAF100B5939A /* nssUtils.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434070534D3B800F287B2 /* nssUtils.h */; }; + D46B088E1C8FCAFD00B5939A /* oidsalg.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A740D3C1984009F5270 /* oidsalg.h */; }; + D46B088F1C8FCAFD00B5939A /* oidsattr.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A760D3C1984009F5270 /* oidsattr.h */; }; + D46B08901C8FCAFD00B5939A /* oidsbase.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 79EF5A770D3C1984009F5270 /* oidsbase.h */; }; + D46B08911C8FCAFD00B5939A /* oidsocsp.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C2824680F1BC75800CAADEC /* oidsocsp.h */; }; + D46B08921C8FCB2900B5939A /* prbit.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64340E0534D3B800F287B2 /* prbit.h */; }; + D46B08931C8FCB2900B5939A /* prcpucfg.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64340F0534D3B800F287B2 /* prcpucfg.h */; }; + D46B08941C8FCB2900B5939A /* prerr.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434120534D3B800F287B2 /* prerr.h */; }; + D46B08951C8FCB2900B5939A /* prerror.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434130534D3B800F287B2 /* prerror.h */; }; + D46B08961C8FCB2900B5939A /* prlog.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434170534D3B800F287B2 /* prlog.h */; }; + D46B08971C8FCB2900B5939A /* prmem.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434190534D3B800F287B2 /* prmem.h */; }; + D46B08981C8FCB2900B5939A /* protypes.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64341B0534D3B800F287B2 /* protypes.h */; }; + D46B08991C8FCB2900B5939A /* prtypes.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64341E0534D3B800F287B2 /* prtypes.h */; }; + D46B089A1C8FCB5E00B5939A /* secasn1.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434200534D3B800F287B2 /* secasn1.h */; }; + D46B089B1C8FCB5E00B5939A /* seccomon.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434250534D3B800F287B2 /* seccomon.h */; }; + D46B089C1C8FCB5E00B5939A /* secerr.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434260534D3B800F287B2 /* secerr.h */; }; + D46B089D1C8FCB5E00B5939A /* SecNssCoder.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C6434290534D3B800F287B2 /* SecNssCoder.h */; }; + D46B089E1C8FCB5E00B5939A /* secport.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64342B0534D3B800F287B2 /* secport.h */; }; + D46B089F1C8FCB8D00B5939A /* plarena.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64340B0534D3B800F287B2 /* plarena.h */; }; + D46B08A01C8FCB8D00B5939A /* plarenas.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64340C0534D3B800F287B2 /* plarenas.h */; }; + D46B08A11C8FCB8D00B5939A /* plstr.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 4C64340D0534D3B800F287B2 /* plstr.h */; }; + D46B08A21C8FCB9A00B5939A /* libASN1.a in Copy Static Library File */ = {isa = PBXBuildFile; fileRef = 795CA7FF0D38013D00BAE6A2 /* libASN1.a */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + D46B08A31C8FCBA000B5939A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D56980C03E74D6100003D05 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 795CA7FE0D38013D00BAE6A2; + remoteInfo = libASN1; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + D46B087D1C8FCA5800B5939A /* Copy Static Library File */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/lib; + dstSubfolderSpec = 0; + files = ( + D46B08A21C8FCB9A00B5939A /* libASN1.a in Copy Static Library File */, + ); + name = "Copy Static Library File"; + runOnlyForDeploymentPostprocessing = 1; + }; + D46B087E1C8FCA5B00B5939A /* Copy Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/include/security_asn1; + dstSubfolderSpec = 0; + files = ( + D46B089F1C8FCB8D00B5939A /* plarena.h in Copy Headers */, + D46B08A01C8FCB8D00B5939A /* plarenas.h in Copy Headers */, + D46B08A11C8FCB8D00B5939A /* plstr.h in Copy Headers */, + D46B089A1C8FCB5E00B5939A /* secasn1.h in Copy Headers */, + D46B089B1C8FCB5E00B5939A /* seccomon.h in Copy Headers */, + D46B089C1C8FCB5E00B5939A /* secerr.h in Copy Headers */, + D46B089D1C8FCB5E00B5939A /* SecNssCoder.h in Copy Headers */, + D46B089E1C8FCB5E00B5939A /* secport.h in Copy Headers */, + D46B08921C8FCB2900B5939A /* prbit.h in Copy Headers */, + D46B08931C8FCB2900B5939A /* prcpucfg.h in Copy Headers */, + D46B08941C8FCB2900B5939A /* prerr.h in Copy Headers */, + D46B08951C8FCB2900B5939A /* prerror.h in Copy Headers */, + D46B08961C8FCB2900B5939A /* prlog.h in Copy Headers */, + D46B08971C8FCB2900B5939A /* prmem.h in Copy Headers */, + D46B08981C8FCB2900B5939A /* protypes.h in Copy Headers */, + D46B08991C8FCB2900B5939A /* prtypes.h in Copy Headers */, + D46B088E1C8FCAFD00B5939A /* oidsalg.h in Copy Headers */, + D46B088F1C8FCAFD00B5939A /* oidsattr.h in Copy Headers */, + D46B08901C8FCAFD00B5939A /* oidsbase.h in Copy Headers */, + D46B08911C8FCAFD00B5939A /* oidsocsp.h in Copy Headers */, + D46B088D1C8FCAF100B5939A /* nssUtils.h in Copy Headers */, + D46B08841C8FCAE400B5939A /* certExtensionTemplates.h in Copy Headers */, + D46B08851C8FCAE400B5939A /* csrTemplates.h in Copy Headers */, + D46B08861C8FCAE400B5939A /* keyTemplates.h in Copy Headers */, + D46B08871C8FCAE400B5939A /* nameTemplates.h in Copy Headers */, + D46B08881C8FCAE400B5939A /* pkcs7Templates.h in Copy Headers */, + D46B08891C8FCAE400B5939A /* pkcs12Templates.h in Copy Headers */, + D46B088A1C8FCAE400B5939A /* ocspTemplates.h in Copy Headers */, + D46B088B1C8FCAE400B5939A /* X509Templates.h in Copy Headers */, + D46B088C1C8FCAE400B5939A /* osKeyTemplates.h in Copy Headers */, + D46B08801C8FCABF00B5939A /* SecAsn1Coder.h in Copy Headers */, + D46B08811C8FCABF00B5939A /* SecAsn1Templates.h in Copy Headers */, + D46B08821C8FCABF00B5939A /* SecAsn1Types.h in Copy Headers */, + D46B08831C8FCABF00B5939A /* secasn1t.h in Copy Headers */, + ); + name = "Copy Headers"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 0502B640068A5920006168D5 /* keyTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = keyTemplates.h; sourceTree = ""; }; 0502BF9A068B51E3006168D5 /* ocspTemplates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ocspTemplates.c; sourceTree = ""; }; @@ -283,40 +368,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 79BDD3490D60D4A4000D84D3 /* prbit.h in Headers */, - 79BDD34A0D60D4A4000D84D3 /* prmem.h in Headers */, - 79BDD3100D60D116000D84D3 /* plstr.h in Headers */, - 79BDD3110D60D116000D84D3 /* prlog.h in Headers */, - 79BDD30C0D60D0E5000D84D3 /* seccomon.h in Headers */, - 79BDD3420D60D2B2000D84D3 /* prerr.h in Headers */, - 79BDD33F0D60D29A000D84D3 /* prerror.h in Headers */, - 79BDD2FC0D60CF66000D84D3 /* secerr.h in Headers */, - 79EF5BA30D3D6EF4009F5270 /* secport.h in Headers */, - 798B80C10D3E8B6700AC1D04 /* secasn1.h in Headers */, - 798B80E00D3E8BFC00AC1D04 /* secasn1t.h in Headers */, - 79BDD2F60D60CF24000D84D3 /* prcpucfg.h in Headers */, - 79BDD2ED0D60CEF5000D84D3 /* prtypes.h in Headers */, - 79EF5BCA0D3D6F44009F5270 /* plarena.h in Headers */, - 79BDD3020D60CFC9000D84D3 /* protypes.h in Headers */, - 79BDD2D10D60CE82000D84D3 /* plarenas.h in Headers */, - 795CA8230D38041D00BAE6A2 /* SecAsn1Coder.h in Headers */, - 795CA8250D38041D00BAE6A2 /* SecAsn1Templates.h in Headers */, - 795CA8260D38041D00BAE6A2 /* SecAsn1Types.h in Headers */, - 795CA8280D38041D00BAE6A2 /* certExtensionTemplates.h in Headers */, - 795CA82A0D38041D00BAE6A2 /* csrTemplates.h in Headers */, - 795CA82C0D38041D00BAE6A2 /* keyTemplates.h in Headers */, - 795CA82E0D38041D00BAE6A2 /* nameTemplates.h in Headers */, - 795CA8310D38041D00BAE6A2 /* nssUtils.h in Headers */, - 795CA8330D38041D00BAE6A2 /* ocspTemplates.h in Headers */, - 795CA83A0D38041D00BAE6A2 /* X509Templates.h in Headers */, - 795CA83C0D38041D00BAE6A2 /* osKeyTemplates.h in Headers */, - 795CAAD20D3BEDBB00BAE6A2 /* pkcs7Templates.h in Headers */, - 795CAAD40D3BEDBB00BAE6A2 /* pkcs12Templates.h in Headers */, - 79EF5A790D3C1984009F5270 /* oidsalg.h in Headers */, - 79EF5A7B0D3C1984009F5270 /* oidsattr.h in Headers */, - 79EF5A7C0D3C1984009F5270 /* oidsbase.h in Headers */, - 4C28246C0F1BC75800CAADEC /* oidsocsp.h in Headers */, - 18312F9714E99A3F00F0BCAC /* SecNssCoder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -346,7 +397,12 @@ 9D56980C03E74D6100003D05 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; + TargetAttributes = { + D46B08791C8FCA5000B5939A = { + CreatedOnToolsVersion = 7.3; + }; + }; }; buildConfigurationList = C23B0CEC09A298C500B7FCED /* Build configuration list for PBXProject "libsecurity_asn1" */; compatibilityVersion = "Xcode 3.2"; @@ -364,6 +420,7 @@ projectRoot = ""; targets = ( 795CA7FE0D38013D00BAE6A2 /* libASN1 */, + D46B08791C8FCA5000B5939A /* libASN1Install */, ); }; /* End PBXProject section */ @@ -401,18 +458,30 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + D46B08A41C8FCBA000B5939A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 795CA7FE0D38013D00BAE6A2 /* libASN1 */; + targetProxy = D46B08A31C8FCBA000B5939A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 795CA8090D3801A700BAE6A2 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 18B647F614D9FD4500F538BF /* debug.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_TESTABILITY = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; }; name = Debug; @@ -430,12 +499,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18B647F814D9FD4500F538BF /* release.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; RUN_CLANG_STATIC_ANALYZER = YES; }; @@ -450,6 +521,20 @@ }; name = Release; }; + D46B087A1C8FCA5100B5939A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D46B087B1C8FCA5100B5939A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -471,6 +556,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D46B087C1C8FCA5100B5939A /* Build configuration list for PBXAggregateTarget "libASN1Install" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D46B087A1C8FCA5100B5939A /* Debug */, + D46B087B1C8FCA5100B5939A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 9D56980C03E74D6100003D05 /* Project object */; diff --git a/OSX/libsecurity_authorization/lib/Authorization.c b/OSX/libsecurity_authorization/lib/Authorization.c index f864a5c3..533fb326 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.c +++ b/OSX/libsecurity_authorization/lib/Authorization.c @@ -106,8 +106,8 @@ OSStatus AuthorizationCreate(const AuthorizationRights *rights, // 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); + require_action_quiet(reply != NULL, done, status = errAuthorizationInternal); + require_action_quiet(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); // Status status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); diff --git a/OSX/libsecurity_authorization/lib/Authorization.h b/OSX/libsecurity_authorization/lib/Authorization.h index e70ca25a..068a5e22 100644 --- a/OSX/libsecurity_authorization/lib/Authorization.h +++ b/OSX/libsecurity_authorization/lib/Authorization.h @@ -158,7 +158,7 @@ typedef const char *AuthorizationString; typedef struct { AuthorizationString name; size_t valueLength; - void *value; + void * __nullable value; UInt32 flags; } AuthorizationItem; @@ -172,7 +172,7 @@ typedef struct { */ typedef struct { UInt32 count; - AuthorizationItem *items; + AuthorizationItem * __nullable items; } AuthorizationItemSet; @@ -188,9 +188,7 @@ typedef struct { SECURITY NOTE: Applications should take care to not disclose the AuthorizationExternalForm to potential attackers since it would authorize rights to them. */ -enum { - kAuthorizationExternalFormLength = 32 -}; +static const size_t kAuthorizationExternalFormLength = 32; typedef struct { char bytes[kAuthorizationExternalFormLength]; @@ -342,7 +340,6 @@ void AuthorizationCopyRightsAsync(AuthorizationRef authorization, @param authorization (input) The authorization object on which this operation is performed. @param tag (input/optional) An optional string tag specifing which sideband information should be returned. When NULL is specified all available information is returned. - @param flags (input) options specified by the AuthorizationFlags enum. set all unused bits to zero to allow for future expansion. @param info (output) A pointer to a newly allocated AuthorizationInfoSet in which the requested sideband infomation is returned (info should be deallocated by calling AuthorizationFreeItemSet() when it is no longer needed). @result errAuthorizationSuccess 0 No error. diff --git a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h index f57c34a2..66c919df 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationPlugin.h @@ -214,8 +214,8 @@ typedef struct AuthorizationCallbacks { /* Read value from context. AuthorizationValue does not own data. */ OSStatus (*GetContextValue)(AuthorizationEngineRef inEngine, AuthorizationString inKey, - AuthorizationContextFlags *outContextFlags, - const AuthorizationValue * __nullable * __nonnull outValue); + AuthorizationContextFlags * __nullable outContextFlags, + const AuthorizationValue * __nullable * __nullable outValue); /* Write value to context. AuthorizationValue and data are copied. */ OSStatus (*SetContextValue)(AuthorizationEngineRef inEngine, @@ -226,7 +226,7 @@ typedef struct AuthorizationCallbacks { /* Read value from hints. AuthorizationValue does not own data. */ OSStatus (*GetHintValue)(AuthorizationEngineRef inEngine, AuthorizationString inKey, - const AuthorizationValue * __nullable * __nonnull outValue); + const AuthorizationValue * __nullable * __nullable outValue); /* Write value to hints. AuthorizationValue and data are copied. */ OSStatus (*SetHintValue)(AuthorizationEngineRef inEngine, @@ -239,12 +239,12 @@ typedef struct AuthorizationCallbacks { /* Read SessionId. */ OSStatus (*GetSessionId)(AuthorizationEngineRef inEngine, - AuthorizationSessionId __nullable * __nonnull outSessionId); + AuthorizationSessionId __nullable * __nullable outSessionId); /* Read value from hints. AuthorizationValue does not own data. */ OSStatus (*GetImmutableHintValue)(AuthorizationEngineRef inEngine, AuthorizationString inKey, - const AuthorizationValue * __nullable * __nonnull outValue); + const AuthorizationValue * __nullable * __nullable outValue); } AuthorizationCallbacks; diff --git a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h index 0e11f023..6001609e 100644 --- a/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h +++ b/OSX/libsecurity_authorization/lib/AuthorizationTagsPriv.h @@ -229,6 +229,12 @@ */ #define kAuthorizationRuleParameterRequireAppleSigned "require-apple-signed" +/*! @defined kAuthorizationRuleParameterPasswordOnly + boolean, default false - if true, all alternative authentication methods + like smart cards are disabled for this rule, only password is allowed + */ +#define kAuthorizationRuleParameterPasswordOnly "password-only" + /* * Hints for internal Authorization use */ @@ -240,6 +246,7 @@ #define AGENT_HINT_CUSTOM_PROMPT "prompt" #define AGENT_HINT_AUTHORIZE_RIGHT "authorize-right" #define AGENT_HINT_CLIENT_PID "client-pid" +#define AGENT_HINT_CUSTOM_PID "custom-pid" #define AGENT_HINT_CLIENT_UID "client-uid" #define AGENT_HINT_CLIENT_VALIDITY "client-signature-validity" #define AGENT_HINT_CREATOR_PID "creator-pid" @@ -253,6 +260,10 @@ #define AGENT_HINT_TOKEN_NAME "token-name" #define AGENT_HINT_PROCESS_SIGNED "process-apple-signed" #define AGENT_HINT_SHOW_RESET "show-reset" +#define AGENT_HINT_PASSWORD_ONLY "password-only" + +// Public Key Hash from certificate used for login +#define AGENT_HINT_TOKEN_HASH "token-hash" /* passed by loginwindow to securityd and agent */ #define AGENT_HINT_IMMEDIATE_LAUNCH "immediate-agent" @@ -268,6 +279,7 @@ #define AGENT_HINT_ACL_MISMATCH "acl-mismatch" #define AGENT_HINT_KEYCHAIN_ITEM_NAME "keychain-item-name" #define AGENT_HINT_KEYCHAIN_PATH "keychain-path" +#define AGENT_HINT_KEYCHAIN_CHECK "keychain-check-pwd" #define AGENT_HINT_WINDOW_LEVEL "window-level" /* Login Keychain Creation hint keys */ @@ -325,4 +337,16 @@ #define AGENT_CONTEXT_REMEMBER_ACTION "remember-action" #define AGENT_CONTEXT_ALLOW "allow" +/* Authorization Hints Providers */ +#define AGENT_CONTEXT_AP_USER_NAME "ap-user-name" +#define AGENT_CONTEXT_AP_TOKEN "ap-token" +#define AGENT_CONTEXT_AP_PAM_SERVICE_NAME "ap-pam-service-name" +#define AGENT_CONTEXT_AP_PAM_ERROR_MESSAGE "ap-pam-error-message" + +/* ID of smartcard which was used for authentication */ +#define AGENT_CONTEXT_AUTH_TOKEN_ID "authenticated-token-id" + +/* LocalAuthentication specific */ +#define AGENT_CONTEXT_LACONTEXT "la-context" + #endif /* !_SECURITY_AUTHORIZATIONTAGSPRIV_H_ */ diff --git a/OSX/libsecurity_authorization/lib/trampolineClient.cpp b/OSX/libsecurity_authorization/lib/trampolineClient.cpp index a640f0a0..00fed805 100644 --- a/OSX/libsecurity_authorization/lib/trampolineClient.cpp +++ b/OSX/libsecurity_authorization/lib/trampolineClient.cpp @@ -152,12 +152,12 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter if (errno == EAGAIN) { // potentially recoverable resource shortage if (n > 0) { - secdebug("authexec", "resource shortage (EAGAIN), delaying %d seconds", delay); + secinfo("authexec", "resource shortage (EAGAIN), delaying %d seconds", delay); sleep(delay); continue; } } - secdebug("authexec", "fork failed (errno=%d)", errno); + secinfo("authexec", "fork failed (errno=%d)", errno); close(notify[READ]); close(notify[WRITE]); return errAuthorizationToolExecuteFailure; @@ -171,16 +171,16 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter fclose(mbox); // get status notification from child - secdebug("authexec", "parent waiting for status"); + secinfo("authexec", "parent waiting for status"); ssize_t rc = read(notify[READ], &status, sizeof(status)); status = n2h(status); switch (rc) { default: // weird result of read: post error - secdebug("authexec", "unexpected read return value %ld", long(rc)); + secinfo("authexec", "unexpected read return value %ld", long(rc)); status = errAuthorizationToolEnvironmentError; // fall through case sizeof(status): // read succeeded: child reported an error - secdebug("authexec", "parent received status=%d", (int)status); + secinfo("authexec", "parent received status=%d", (int)status); close(notify[READ]); if (communicationsPipe) { close(comm[READ]); close(comm[WRITE]); } goto exit_point; @@ -188,7 +188,7 @@ OSStatus AuthorizationExecuteWithPrivilegesExternalForm(const AuthorizationExter close(notify[READ]); if (communicationsPipe) *communicationsPipe = fdopen(comm[READ], "r+"); - secdebug("authexec", "parent resumes (no error)"); + secinfo("authexec", "parent resumes (no error)"); status = errSecSuccess; goto exit_point; } diff --git a/OSX/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj b/OSX/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj index 995cc736..6522557b 100644 --- a/OSX/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_authorization/libsecurity_authorization.xcodeproj/project.pbxproj @@ -53,7 +53,7 @@ 40BC5D9605322F76009E6ADA /* AuthorizationTags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationTags.h; path = lib/AuthorizationTags.h; sourceTree = ""; }; 40BC5D9805322F76009E6ADA /* AuthSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthSession.h; path = lib/AuthSession.h; sourceTree = ""; }; 40C767090534CCDB008AC043 /* AuthorizationTagsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AuthorizationTagsPriv.h; path = lib/AuthorizationTagsPriv.h; sourceTree = ""; }; - 4C481F03058161C400846F0C /* trampolineClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = trampolineClient.cpp; path = lib/trampolineClient.cpp; sourceTree = ""; }; + 4C481F03058161C400846F0C /* trampolineClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = trampolineClient.cpp; path = lib/trampolineClient.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C481F04058161C400846F0C /* trampolineServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = trampolineServer.cpp; path = lib/trampolineServer.cpp; sourceTree = ""; }; 4C6848A005815EE4003AC7B2 /* privPort.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = privPort.h; path = lib/privPort.h; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_authorization.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_authorization.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -162,7 +162,6 @@ buildRules = ( ); dependencies = ( - 182BB337146F100D000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_authorization; productInstallPath = /usr/local/lib; @@ -176,7 +175,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD2B70987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_authorization" */; compatibilityVersion = "Xcode 3.2"; @@ -266,12 +265,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446156146E928E00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -279,12 +287,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446156146E928E00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_cdsa_client/lib/aclclient.cpp b/OSX/libsecurity_cdsa_client/lib/aclclient.cpp index 988943fd..caca8685 100644 --- a/OSX/libsecurity_cdsa_client/lib/aclclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/aclclient.cpp @@ -21,10 +21,12 @@ // #include #include -#include +#include +#include #include #include - +#include +#include namespace Security { namespace CssmClient { @@ -243,7 +245,41 @@ AclFactory::PasswordChangeCredentials::PasswordChangeCredentials (const CssmData new (allocator) ListElement (CssmAutoData(allocator, password).release())); } - + +// +// Manage the (pseudo) credentials used to explicitly provide a master key to a keychain. +// +AclFactory::MasterKeyUnlockCredentials::MasterKeyUnlockCredentials (const CssmClient::Key& key, + Allocator& allocator) : KeychainCredentials(allocator) +{ + // Flatten out this key into: + // { h2ni(CSSM_KEY) : raw data for CSSM_KEY } + // which is also (on x86_64): + // { h2ni(CSSM_KEYHEADER) : 4 byte align : CSSM_DATA{0:0} : raw data for CSSM_KEY } + // (placement of alignment bytes uncertain) + // + // Data format is for consumption by kcdatabase.cpp:unflattenKey() + + size_t dataLen = sizeof(CSSM_KEY) + key->keyData().length(); + CssmAutoData flattenedKey(allocator); + flattenedKey.malloc(dataLen); + memset(flattenedKey, 0, dataLen); + + // The key header must be in network-byte order for some reason + CSSM_KEYHEADER header = key->header(); + Security::h2ni(header); + memcpy(flattenedKey, &header, sizeof(CSSM_KEYHEADER)); + memcpy(((uint8_t*) flattenedKey.data()) + sizeof(CSSM_KEY), key->keyData().data(), key->keyData().length()); + + mCredentials->sample(0) = TypedList(allocator, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new (allocator) ListElement(CSSM_SAMPLE_TYPE_SYMMETRIC_KEY), + new (allocator) ListElement(CssmAutoData(allocator, CssmData::wrap((SecurityServer::KeyHandle) 0)).release()), + new (allocator) ListElement(CssmAutoData(allocator, CssmData::wrap(*((const CssmKey*) key))).release()), + new (allocator) ListElement(flattenedKey.release())); +} + + + // // Wide open ("ANY") CSSM forms for owner and ACL entry // diff --git a/OSX/libsecurity_cdsa_client/lib/aclclient.h b/OSX/libsecurity_cdsa_client/lib/aclclient.h index 2daa1cfd..8789eb25 100644 --- a/OSX/libsecurity_cdsa_client/lib/aclclient.h +++ b/OSX/libsecurity_cdsa_client/lib/aclclient.h @@ -32,7 +32,7 @@ namespace Security { namespace CssmClient { class CSP; - +class Key; // // Any client-side object that has CSSM-layer ACLs shall be @@ -139,6 +139,12 @@ public: PasswordChangeCredentials (const CssmData& password, Allocator& allocator); }; + // create an AccessCredentials to explicitly provide a keychain master key + class MasterKeyUnlockCredentials : public KeychainCredentials { + public: + MasterKeyUnlockCredentials (const Key& key, Allocator& allocator); + }; + public: class AnyResourceContext : public ResourceControlContext { public: diff --git a/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp b/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp index 05a59c49..ce83b5e2 100644 --- a/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/cssmclient.cpp @@ -30,7 +30,7 @@ // and thus don't need to be interlocked explicitly. // #include -#include +#include using namespace CssmClient; @@ -80,7 +80,7 @@ try if (!isIdle()) { int i = mChildCount; - syslog(LOG_ALERT, "Object %p still has %d children at delete.\n", this, i); + secerror("Object %p still has %d children at delete.\n", this, i); } // release parent from her obligations (if we still have one) @@ -269,13 +269,13 @@ void CssmImpl::StandardCssm::unsetCssm(CssmImpl *cssm) mCssm = NULL; } -CssmImpl *CssmImpl::StandardCssm::get() +Cssm CssmImpl::StandardCssm::get() { StLock _(*this); if (mCssm == NULL) { // make the default instance mCssm = new CssmImpl(true); } - return mCssm; + return Cssm(mCssm); } CssmImpl::StandardCssm::~StandardCssm() @@ -383,7 +383,7 @@ void ModuleEvents::fault(uint32 subService, CSSM_SERVICE_TYPE type) { } void ModuleImpl::appNotifyCallback(CSSM_API_ModuleEventHandler appNotifyCallback, void *appNotifyCallbackCtx) { - secdebug("callback","In ModuleImpl::appNotifyCallback, appNotifyCallback=%p, appNotifyCallbackCtx=%p", + secinfo("callback","In ModuleImpl::appNotifyCallback, appNotifyCallback=%p, appNotifyCallbackCtx=%p", appNotifyCallback, appNotifyCallbackCtx); if (mActive) Error::throwMe(Error::objectBusy); @@ -407,7 +407,7 @@ ModuleImpl::activate() { session()->init(); // @@@ install handler here (use central dispatch with override) - secdebug("callback","In ModuleImpl::activate, mAppNotifyCallback=%p, mAppNotifyCallbackCtx=%p", + secinfo("callback","In ModuleImpl::activate, mAppNotifyCallback=%p, mAppNotifyCallbackCtx=%p", mAppNotifyCallback, mAppNotifyCallbackCtx); check(CSSM_ModuleLoad(&guid(), CSSM_KEY_HIERARCHY_NONE, mAppNotifyCallback, mAppNotifyCallbackCtx)); mActive = true; diff --git a/OSX/libsecurity_cdsa_client/lib/cssmclient.h b/OSX/libsecurity_cdsa_client/lib/cssmclient.h index 53719b82..9b003382 100644 --- a/OSX/libsecurity_cdsa_client/lib/cssmclient.h +++ b/OSX/libsecurity_cdsa_client/lib/cssmclient.h @@ -350,10 +350,12 @@ private: ~StandardCssm(); void setCssm(CssmImpl *cssm); void unsetCssm(CssmImpl *cssm); - CssmImpl *get(); + Cssm get(); private: - CssmImpl *mCssm; + RefPointer mCssm; // 'Leaks' this object (in that it won't ever be deleted after creation), but + // there's no safe way to vend and re-create this object in a multi-threaded environment + // without an implementation of WeakRefPointer<>. }; static ModuleNexus mStandard; }; diff --git a/OSX/libsecurity_cdsa_client/lib/dlclient.cpp b/OSX/libsecurity_cdsa_client/lib/dlclient.cpp index 127f9b13..2846d3cf 100644 --- a/OSX/libsecurity_cdsa_client/lib/dlclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/dlclient.cpp @@ -481,7 +481,7 @@ uint32 DbImpl::dbBlobVersion() { if(dl()->guid() == gGuidAppleCSPDL) { check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_BLOB_VERSION, NULL, (void**) &dbBlobVersionPtr)); } else { - secdebugfunc("integrity", "Non-Apple CSPDL keychains don't have keychain versions"); + secnotice("integrity", "Non-Apple CSPDL keychains don't have keychain versions"); } return dbBlobVersion; } @@ -493,6 +493,10 @@ uint32 DbImpl::recodeDbToVersion(uint32 version) { return newDbVersion; } +void DbImpl::recodeFinished() { + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_RECODE_FINISHED, NULL, NULL)); +} + void DbImpl::takeFileLock() { passThrough(CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK, NULL, NULL); } @@ -505,6 +509,52 @@ void DbImpl::makeBackup() { passThrough(CSSM_APPLECSPDL_DB_MAKE_BACKUP, NULL, NULL); } +void DbImpl::makeCopy(const char* path) { + passThrough(CSSM_APPLECSPDL_DB_MAKE_COPY, path, NULL); +} + +void DbImpl::deleteFile() { + passThrough(CSSM_APPLECSPDL_DB_DELETE_FILE, NULL, NULL); +} + +void DbImpl::transferTo(const DLDbIdentifier& dldbidentifier) { + if (dldbidentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) { + // if we're an Apple CSPDL, do the fancy transfer: + // clone the file, clone the db, remove the original file + string oldPath = name(); + + CSSM_DB_HANDLE dbhandle; + passThrough(CSSM_APPLECSPDL_DB_CLONE, &dldbidentifier, &dbhandle); + + mDbName = dldbidentifier.dbName(); + mHandle.DBHandle = dbhandle; + + unlink(oldPath.c_str()); + + // Don't cache this name + if (mNameFromHandle) { + allocator().free(mNameFromHandle); + mNameFromHandle = NULL; + } + } else { + // if we're not an Apple CSPDL, just call rename + this->rename(dldbidentifier.dbName()); + } +} + + +// cloneTo only makes sense if you're on an Apple CSPDL +Db DbImpl::cloneTo(const DLDbIdentifier& dldbidentifier) { + CSSM_DB_HANDLE dbhandle; + passThrough(CSSM_APPLECSPDL_DB_CLONE, &dldbidentifier, &dbhandle); + + // This is the only reasonable way to make a SSDbImpl at this layer. + CssmClient::Db db(dl(), dldbidentifier.dbName(), dldbidentifier.dbLocation()); + db->mHandle.DBHandle = dbhandle; + + return db; +} + // // DbCursorMaker // diff --git a/OSX/libsecurity_cdsa_client/lib/dlclient.h b/OSX/libsecurity_cdsa_client/lib/dlclient.h index 6617a392..fbd05c98 100644 --- a/OSX/libsecurity_cdsa_client/lib/dlclient.h +++ b/OSX/libsecurity_cdsa_client/lib/dlclient.h @@ -328,6 +328,9 @@ public: // Attempt to recode this database to the new version virtual uint32 recodeDbToVersion(uint32 version); + // Declare that the recode operation is complete + virtual void recodeFinished(); + // Try to take or release the file lock on the underlying database. // You _must_ call these as a pair. They start a transaction on the // underlying DL object, and that transaction is only finished when release @@ -339,6 +342,22 @@ public: // Make a backup of this database on the filesystem virtual void makeBackup(); + // Make a copy of this database on the filesystem + // Throws a UnixError if anything goes wrong + virtual void makeCopy(const char* path); + + // Make a clone of this database in a new location. + // This method handles telling securityd about the clone, and copying the + // file over. + virtual Db cloneTo(const DLDbIdentifier& dldbidentifier); + + // Transfer this database to a new location. If the database is open in + // securityd, transfer the lock status as well. + virtual void transferTo(const DLDbIdentifier& dldbidentifier); + + // This will attempt to delete the file underlying this database. + // Don't call this unless you really, really mean to. + virtual void deleteFile(); // Utility methods diff --git a/OSX/libsecurity_cdsa_client/lib/securestorage.cpp b/OSX/libsecurity_cdsa_client/lib/securestorage.cpp index 40b1c0ed..7d2d0ab1 100644 --- a/OSX/libsecurity_cdsa_client/lib/securestorage.cpp +++ b/OSX/libsecurity_cdsa_client/lib/securestorage.cpp @@ -129,8 +129,16 @@ SSDbImpl::open() DbImpl::open(); } -SSDbUniqueRecord +DbUniqueRecord SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data) +{ + return DbImpl::insert(recordType, attributes, data); +} + +SSDbUniqueRecord +SSDbImpl::ssInsert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, const CSSM_DATA *data, const CSSM_RESOURCE_CONTROL_CONTEXT *rc) @@ -148,7 +156,7 @@ SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, const CSSM_ACCESS_CREDENTIALS *cred = rc ? rc->AccessCred : NULL; try { - return insert(recordType, attributes, data, group, cred); + SSDbUniqueRecord ssdbur = ssInsert(recordType, attributes, data, group, cred); if (autoCommit) { // autoCommit was on so commit now that we are done and turn @@ -157,6 +165,7 @@ SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, reinterpret_cast(autoCommit), NULL); } + return ssdbur; } catch(...) { @@ -171,13 +180,10 @@ SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, } throw; } - - // keep the compiler happy -- this path is NEVER taken - CssmError::throwMe(0); } SSDbUniqueRecord -SSDbImpl::insert(CSSM_DB_RECORDTYPE recordType, +SSDbImpl::ssInsert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, const CSSM_DATA *data, const SSGroup &group, const CSSM_ACCESS_CREDENTIALS *cred) diff --git a/OSX/libsecurity_cdsa_client/lib/securestorage.h b/OSX/libsecurity_cdsa_client/lib/securestorage.h index 7474fbfd..6f8c1b75 100644 --- a/OSX/libsecurity_cdsa_client/lib/securestorage.h +++ b/OSX/libsecurity_cdsa_client/lib/securestorage.h @@ -154,12 +154,17 @@ public: void create(); void open(); - SSDbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + // This insert is here to explicitly catch calls to DbImpl's insert. You probably want the ssInsert calls below. + DbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, + const CSSM_DATA *data); + + SSDbUniqueRecord ssInsert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, const CSSM_DATA *data, const CSSM_RESOURCE_CONTROL_CONTEXT *rc = NULL); - SSDbUniqueRecord insert(CSSM_DB_RECORDTYPE recordType, + SSDbUniqueRecord ssInsert(CSSM_DB_RECORDTYPE recordType, const CSSM_DB_RECORD_ATTRIBUTE_DATA *attributes, const CSSM_DATA *data, const SSGroup &group, const CSSM_ACCESS_CREDENTIALS *cred); diff --git a/OSX/libsecurity_cdsa_client/lib/tpclient.cpp b/OSX/libsecurity_cdsa_client/lib/tpclient.cpp index f64fef31..95ee733b 100644 --- a/OSX/libsecurity_cdsa_client/lib/tpclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/tpclient.cpp @@ -69,7 +69,7 @@ void TPImpl::certGroupVerify(const CertGroup &certGroup, void TPImpl::setupCL() { if (mUseCL == NULL) { - secdebug("tpclient", "TP is auto-attaching supporting CL"); + secinfo("tpclient", "TP is auto-attaching supporting CL"); mUseCL = new CL(gGuidAppleX509CL); mOwnCL = true; } @@ -78,7 +78,7 @@ void TPImpl::setupCL() void TPImpl::setupCSP() { if (mUseCSP == NULL) { - secdebug("tpclient", "TP is auto-attaching supporting CSP"); + secinfo("tpclient", "TP is auto-attaching supporting CSP"); mUseCSP = new CSP(gGuidAppleCSP); mOwnCSP = true; } diff --git a/OSX/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj b/OSX/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj index 261a2e3a..4f2a5af3 100644 --- a/OSX/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cdsa_client/libsecurity_cdsa_client.xcodeproj/project.pbxproj @@ -66,9 +66,9 @@ C25F9888052C9E3100EDA739 /* cryptoclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cryptoclient.h; sourceTree = ""; }; C25F9889052C9E3100EDA739 /* cspclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cspclient.cpp; sourceTree = ""; }; C25F988A052C9E3100EDA739 /* cspclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cspclient.h; sourceTree = ""; }; - C25F988B052C9E3100EDA739 /* cssmclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmclient.cpp; sourceTree = ""; }; + C25F988B052C9E3100EDA739 /* cssmclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cssmclient.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C25F988C052C9E3100EDA739 /* cssmclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmclient.h; sourceTree = ""; }; - C25F988D052C9E3100EDA739 /* dlclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = dlclient.cpp; sourceTree = ""; }; + C25F988D052C9E3100EDA739 /* dlclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = dlclient.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C25F988E052C9E3100EDA739 /* dlclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dlclient.h; sourceTree = ""; }; C25F988F052C9E3100EDA739 /* DLDBList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DLDBList.cpp; sourceTree = ""; }; C25F9890052C9E3100EDA739 /* DLDBList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DLDBList.h; sourceTree = ""; }; @@ -86,7 +86,7 @@ C25F98A0052C9E3200EDA739 /* securestorage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = securestorage.h; sourceTree = ""; }; C25F98A1052C9E3200EDA739 /* signclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = signclient.cpp; sourceTree = ""; }; C25F98A2052C9E3200EDA739 /* signclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = signclient.h; sourceTree = ""; }; - C25F98A3052C9E3200EDA739 /* tpclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tpclient.cpp; sourceTree = ""; }; + C25F98A3052C9E3200EDA739 /* tpclient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = tpclient.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C25F98A4052C9E3200EDA739 /* tpclient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tpclient.h; sourceTree = ""; }; C25F98A5052C9E3200EDA739 /* wrapkey.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = wrapkey.cpp; sourceTree = ""; }; C25F98A6052C9E3200EDA739 /* wrapkey.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = wrapkey.h; sourceTree = ""; }; @@ -252,7 +252,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD2D60987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_client" */; compatibilityVersion = "Xcode 3.2"; @@ -281,12 +281,15 @@ files = ( ); inputPaths = ( + "$(SRCROOT)/", + "$(SRCROOT)/lib/", ); outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "nmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + shellScript = "# with our source directories as input files, Xcode will only re-run this phase if there's been a source change\nnmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; }; /* End PBXShellScriptBuildPhase section */ @@ -355,12 +358,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446165146E94DE00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -368,12 +380,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446165146E94DE00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp new file mode 100644 index 00000000..6caef051 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.cpp @@ -0,0 +1,69 @@ +// +// AC plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#include +#include +#include +#include + + +ACAbstractPluginSession::~ACAbstractPluginSession() +{ /* virtual */ } + +static CSSM_RETURN CSSMACI cssm_AuthCompute(CSSM_AC_HANDLE ACHandle, + const CSSM_TUPLEGROUP *BaseAuthorizations, + const CSSM_TUPLEGROUP *Credentials, + uint32 NumberOfRequestors, + const CSSM_LIST *Requestors, + const CSSM_LIST *RequestedAuthorizationPeriod, + const CSSM_LIST *RequestedAuthorization, + CSSM_TUPLEGROUP_PTR AuthorizationResult) +{ + BEGIN_API + findSession(ACHandle).AuthCompute(Required(BaseAuthorizations), + Credentials, + NumberOfRequestors, + Required(Requestors), + RequestedAuthorizationPeriod, + Required(RequestedAuthorization), + Required(AuthorizationResult)); + END_API(AC) +} + +static CSSM_RETURN CSSMACI cssm_PassThrough(CSSM_AC_HANDLE ACHandle, + CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) +{ + BEGIN_API + findSession(ACHandle).PassThrough(TPHandle, + CLHandle, + CCHandle, + Required(DBList), + PassThroughId, + InputParams, + OutputParams); + END_API(AC) +} + + +static const CSSM_SPI_AC_FUNCS ACFunctionStruct = { + cssm_AuthCompute, + cssm_PassThrough, +}; + +static CSSM_MODULE_FUNCS ACFunctionTable = { + CSSM_SERVICE_AC, // service type + 2, // number of functions + (const CSSM_PROC_ADDR *)&ACFunctionStruct +}; + +CSSM_MODULE_FUNCS_PTR ACPluginSession::construct() +{ + return &ACFunctionTable; +} diff --git a/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.h b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.h new file mode 100644 index 00000000..e7fccead --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/ACabstractsession.h @@ -0,0 +1,39 @@ +// +// AC plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#ifndef _H_ACABSTRACTSESSION +#define _H_ACABSTRACTSESSION + +#include +#include + + +namespace Security { + + +// +// A pure abstract class to define the AC module interface +// +class ACAbstractPluginSession { +public: + virtual ~ACAbstractPluginSession(); + virtual void AuthCompute(const CSSM_TUPLEGROUP &BaseAuthorizations, + const CSSM_TUPLEGROUP *Credentials, + uint32 NumberOfRequestors, + const CSSM_LIST &Requestors, + const CSSM_LIST *RequestedAuthorizationPeriod, + const CSSM_LIST &RequestedAuthorization, + CSSM_TUPLEGROUP &AuthorizationResult) = 0; + virtual void PassThrough(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST &DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) = 0; +}; + +} // end namespace Security + +#endif //_H_ACABSTRACTSESSION diff --git a/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp new file mode 100644 index 00000000..bfb5e7fe --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.cpp @@ -0,0 +1,548 @@ +// +// CL plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#include +#include +#include +#include + + +CLAbstractPluginSession::~CLAbstractPluginSession() +{ /* virtual */ } + +static CSSM_RETURN CSSMCLI cssm_CertGetFirstFieldValue(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_OID *CertField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if ((Required(ResultsHandle) = findSession(CLHandle).CertGetFirstFieldValue(CssmData::required(Cert), + CssmData::required(CertField), + Required(NumberOfMatchedFields), + Required(Value))) == CSSM_INVALID_HANDLE) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_PassThrough(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) +{ + BEGIN_API + findSession(CLHandle).PassThrough(CCHandle, + PassThroughId, + InputParams, + OutputParams); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGetNextCachedFieldValue(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if (!findSession(CLHandle).CertGetNextCachedFieldValue(ResultsHandle, + Required(Value))) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + CSSM_DATA_PTR NewCrl) +{ + BEGIN_API + findSession(CLHandle).CrlCreateTemplate(NumberOfFields, + CrlTemplate, + CssmData::required(NewCrl)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertTemplate, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CSSM_DATA_PTR SignedCert) +{ + BEGIN_API + findSession(CLHandle).CertSign(CCHandle, + CssmData::required(CertTemplate), + SignScope, + ScopeSize, + CssmData::required(SignedCert)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlGetFirstFieldValue(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if ((Required(ResultsHandle) = findSession(CLHandle).CrlGetFirstFieldValue(CssmData::required(Crl), + CssmData::required(CrlField), + Required(NumberOfMatchedFields), + Required(Value))) == CSSM_INVALID_HANDLE) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlGetNextFieldValue(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if (!findSession(CLHandle).CrlGetNextFieldValue(ResultsHandle, + Required(Value))) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_FreeFields(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + CSSM_FIELD_PTR *FieldArray) +{ + BEGIN_API + findSession(CLHandle).FreeFields(NumberOfFields, + Required(FieldArray)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlGetAllFields(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + uint32 *NumberOfCrlFields, + CSSM_FIELD_PTR *CrlFields) +{ + BEGIN_API + findSession(CLHandle).CrlGetAllFields(CssmData::required(Crl), + Required(NumberOfCrlFields), + Required(CrlFields)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlAbortCache(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle) +{ + BEGIN_API + findSession(CLHandle).CrlAbortCache(CrlHandle); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGetAllTemplateFields(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *CertTemplate, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields) +{ + BEGIN_API + findSession(CLHandle).CertGetAllTemplateFields(CssmData::required(CertTemplate), + Required(NumberOfFields), + Required(CertFields)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlSetFields(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlTemplate, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR ModifiedCrl) +{ + BEGIN_API + findSession(CLHandle).CrlSetFields(NumberOfFields, + CrlTemplate, + CssmData::required(OldCrl), + CssmData::required(ModifiedCrl)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGetAllFields(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields) +{ + BEGIN_API + findSession(CLHandle).CertGetAllFields(CssmData::required(Cert), + Required(NumberOfFields), + Required(CertFields)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlAddCert(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Cert, + uint32 NumberOfFields, + const CSSM_FIELD *CrlEntryFields, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR NewCrl) +{ + BEGIN_API + findSession(CLHandle).CrlAddCert(CCHandle, + CssmData::required(Cert), + NumberOfFields, + CrlEntryFields, + CssmData::required(OldCrl), + CssmData::required(NewCrl)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_IsCertInCachedCrl(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_HANDLE CrlHandle, + CSSM_BOOL *CertFound, + CSSM_DATA_PTR CrlRecordIndex) +{ + BEGIN_API + findSession(CLHandle).IsCertInCachedCrl(CssmData::required(Cert), + CrlHandle, + Required(CertFound), + CssmData::required(CrlRecordIndex)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *UnsignedCrl, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CSSM_DATA_PTR SignedCrl) +{ + BEGIN_API + findSession(CLHandle).CrlSign(CCHandle, + CssmData::required(UnsignedCrl), + SignScope, + ScopeSize, + CssmData::required(SignedCrl)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertAbortQuery(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle) +{ + BEGIN_API + findSession(CLHandle).CertAbortQuery(ResultsHandle); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGetNextFieldValue(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if (!findSession(CLHandle).CertGetNextFieldValue(ResultsHandle, + Required(Value))) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CertFields, + CSSM_DATA_PTR CertTemplate) +{ + BEGIN_API + findSession(CLHandle).CertCreateTemplate(NumberOfFields, + CertFields, + CssmData::required(CertTemplate)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertCache(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_HANDLE_PTR CertHandle) +{ + BEGIN_API + findSession(CLHandle).CertCache(CssmData::required(Cert), + Required(CertHandle)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlVerifyWithKey(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlToBeVerified) +{ + BEGIN_API + findSession(CLHandle).CrlVerifyWithKey(CCHandle, + CssmData::required(CrlToBeVerified)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlGetAllCachedRecordFields(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_DATA *CrlRecordIndex, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CrlFields) +{ + BEGIN_API + findSession(CLHandle).CrlGetAllCachedRecordFields(CrlHandle, + CssmData::required(CrlRecordIndex), + Required(NumberOfFields), + Required(CrlFields)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlRemoveCert(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_DATA *OldCrl, + CSSM_DATA_PTR NewCrl) +{ + BEGIN_API + findSession(CLHandle).CrlRemoveCert(CssmData::required(Cert), + CssmData::required(OldCrl), + CssmData::required(NewCrl)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertVerifyWithKey(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertToBeVerified) +{ + BEGIN_API + findSession(CLHandle).CertVerifyWithKey(CCHandle, + CssmData::required(CertToBeVerified)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlGetFirstCachedFieldValue(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CrlHandle, + const CSSM_DATA *CrlRecordIndex, + const CSSM_OID *CrlField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if ((Required(ResultsHandle) = findSession(CLHandle).CrlGetFirstCachedFieldValue(CrlHandle, + CssmData::optional(CrlRecordIndex), + CssmData::required(CrlField), + Required(NumberOfMatchedFields), + Required(Value))) == CSSM_INVALID_HANDLE) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGetFirstCachedFieldValue(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CertHandle, + const CSSM_OID *CertField, + CSSM_HANDLE_PTR ResultsHandle, + uint32 *NumberOfMatchedFields, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if ((Required(ResultsHandle) = findSession(CLHandle).CertGetFirstCachedFieldValue(CertHandle, + CssmData::required(CertField), + Required(NumberOfMatchedFields), + Required(Value))) == CSSM_INVALID_HANDLE) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) +{ + BEGIN_API + findSession(CLHandle).CertVerify(CCHandle, + CssmData::required(CertToBeVerified), + CssmData::optional(SignerCert), + VerifyScope, + ScopeSize); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGetKeyInfo(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + CSSM_KEY_PTR *Key) +{ + BEGIN_API + findSession(CLHandle).CertGetKeyInfo(CssmData::required(Cert), + Required(Key)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CrlToBeVerified, + const CSSM_DATA *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) +{ + BEGIN_API + findSession(CLHandle).CrlVerify(CCHandle, + CssmData::required(CrlToBeVerified), + CssmData::optional(SignerCert), + VerifyScope, + ScopeSize); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlDescribeFormat(CSSM_CL_HANDLE CLHandle, + uint32 *NumberOfFields, + CSSM_OID_PTR *OidList) +{ + BEGIN_API + findSession(CLHandle).CrlDescribeFormat(Required(NumberOfFields), + Required(OidList)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlAbortQuery(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle) +{ + BEGIN_API + findSession(CLHandle).CrlAbortQuery(ResultsHandle); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertDescribeFormat(CSSM_CL_HANDLE CLHandle, + uint32 *NumberOfFields, + CSSM_OID_PTR *OidList) +{ + BEGIN_API + findSession(CLHandle).CertDescribeFormat(Required(NumberOfFields), + Required(OidList)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_FreeFieldValue(CSSM_CL_HANDLE CLHandle, + const CSSM_OID *CertOrCrlOid, + CSSM_DATA_PTR Value) +{ + BEGIN_API + findSession(CLHandle).FreeFieldValue(CssmData::required(CertOrCrlOid), + CssmData::required(Value)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGroupToSignedBundle(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CERTGROUP *CertGroupToBundle, + const CSSM_CERT_BUNDLE_HEADER *BundleInfo, + CSSM_DATA_PTR SignedBundle) +{ + BEGIN_API + findSession(CLHandle).CertGroupToSignedBundle(CCHandle, + Required(CertGroupToBundle), + BundleInfo, + CssmData::required(SignedBundle)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertAbortCache(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE CertHandle) +{ + BEGIN_API + findSession(CLHandle).CertAbortCache(CertHandle); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlCache(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Crl, + CSSM_HANDLE_PTR CrlHandle) +{ + BEGIN_API + findSession(CLHandle).CrlCache(CssmData::required(Crl), + Required(CrlHandle)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_IsCertInCrl(CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *Cert, + const CSSM_DATA *Crl, + CSSM_BOOL *CertFound) +{ + BEGIN_API + findSession(CLHandle).IsCertInCrl(CssmData::required(Cert), + CssmData::required(Crl), + Required(CertFound)); + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CrlGetNextCachedFieldValue(CSSM_CL_HANDLE CLHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR *Value) +{ + BEGIN_API + if (!findSession(CLHandle).CrlGetNextCachedFieldValue(ResultsHandle, + Required(Value))) + return CSSMERR_CL_NO_FIELD_VALUES; + END_API(CL) +} + +static CSSM_RETURN CSSMCLI cssm_CertGroupFromVerifiedBundle(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CERT_BUNDLE *CertBundle, + const CSSM_DATA *SignerCert, + CSSM_CERTGROUP_PTR *CertGroup) +{ + BEGIN_API + findSession(CLHandle).CertGroupFromVerifiedBundle(CCHandle, + Required(CertBundle), + CssmData::optional(SignerCert), + Required(CertGroup)); + END_API(CL) +} + + +static const CSSM_SPI_CL_FUNCS CLFunctionStruct = { + cssm_CertCreateTemplate, + cssm_CertGetAllTemplateFields, + cssm_CertSign, + cssm_CertVerify, + cssm_CertVerifyWithKey, + cssm_CertGetFirstFieldValue, + cssm_CertGetNextFieldValue, + cssm_CertAbortQuery, + cssm_CertGetKeyInfo, + cssm_CertGetAllFields, + cssm_FreeFields, + cssm_FreeFieldValue, + cssm_CertCache, + cssm_CertGetFirstCachedFieldValue, + cssm_CertGetNextCachedFieldValue, + cssm_CertAbortCache, + cssm_CertGroupToSignedBundle, + cssm_CertGroupFromVerifiedBundle, + cssm_CertDescribeFormat, + cssm_CrlCreateTemplate, + cssm_CrlSetFields, + cssm_CrlAddCert, + cssm_CrlRemoveCert, + cssm_CrlSign, + cssm_CrlVerify, + cssm_CrlVerifyWithKey, + cssm_IsCertInCrl, + cssm_CrlGetFirstFieldValue, + cssm_CrlGetNextFieldValue, + cssm_CrlAbortQuery, + cssm_CrlGetAllFields, + cssm_CrlCache, + cssm_IsCertInCachedCrl, + cssm_CrlGetFirstCachedFieldValue, + cssm_CrlGetNextCachedFieldValue, + cssm_CrlGetAllCachedRecordFields, + cssm_CrlAbortCache, + cssm_CrlDescribeFormat, + cssm_PassThrough, +}; + +static CSSM_MODULE_FUNCS CLFunctionTable = { + CSSM_SERVICE_CL, // service type + 39, // number of functions + (const CSSM_PROC_ADDR *)&CLFunctionStruct +}; + +CSSM_MODULE_FUNCS_PTR CLPluginSession::construct() +{ + return &CLFunctionTable; +} diff --git a/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.h b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.h new file mode 100644 index 00000000..6c3e1cd7 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/CLabstractsession.h @@ -0,0 +1,143 @@ +// +// CL plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#ifndef _H_CLABSTRACTSESSION +#define _H_CLABSTRACTSESSION + +#include +#include + + +namespace Security { + + +// +// A pure abstract class to define the CL module interface +// +class CLAbstractPluginSession { +public: + virtual ~CLAbstractPluginSession(); + virtual void CertGetAllFields(const CssmData &Cert, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields) = 0; + virtual void CertGetAllTemplateFields(const CssmData &CertTemplate, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields) = 0; + virtual void CrlSetFields(uint32 NumberOfFields, + const CSSM_FIELD CrlTemplate[], + const CssmData &OldCrl, + CssmData &ModifiedCrl) = 0; + virtual void CrlAbortCache(CSSM_HANDLE CrlHandle) = 0; + virtual void CrlGetAllFields(const CssmData &Crl, + uint32 &NumberOfCrlFields, + CSSM_FIELD_PTR &CrlFields) = 0; + virtual void FreeFields(uint32 NumberOfFields, + CSSM_FIELD_PTR &FieldArray) = 0; + virtual bool CrlGetNextFieldValue(CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) = 0; + virtual CSSM_HANDLE CrlGetFirstFieldValue(const CssmData &Crl, + const CssmData &CrlField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) = 0; + virtual void CertSign(CSSM_CC_HANDLE CCHandle, + const CssmData &CertTemplate, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CssmData &SignedCert) = 0; + virtual void CrlCreateTemplate(uint32 NumberOfFields, + const CSSM_FIELD CrlTemplate[], + CssmData &NewCrl) = 0; + virtual bool CertGetNextCachedFieldValue(CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) = 0; + virtual void PassThrough(CSSM_CC_HANDLE CCHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) = 0; + virtual CSSM_HANDLE CertGetFirstFieldValue(const CssmData &Cert, + const CssmData &CertField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) = 0; + virtual void CrlVerifyWithKey(CSSM_CC_HANDLE CCHandle, + const CssmData &CrlToBeVerified) = 0; + virtual void CertCreateTemplate(uint32 NumberOfFields, + const CSSM_FIELD CertFields[], + CssmData &CertTemplate) = 0; + virtual void CertCache(const CssmData &Cert, + CSSM_HANDLE &CertHandle) = 0; + virtual bool CertGetNextFieldValue(CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) = 0; + virtual void CertAbortQuery(CSSM_HANDLE ResultsHandle) = 0; + virtual void IsCertInCachedCrl(const CssmData &Cert, + CSSM_HANDLE CrlHandle, + CSSM_BOOL &CertFound, + CssmData &CrlRecordIndex) = 0; + virtual void CrlSign(CSSM_CC_HANDLE CCHandle, + const CssmData &UnsignedCrl, + const CSSM_FIELD *SignScope, + uint32 ScopeSize, + CssmData &SignedCrl) = 0; + virtual void CrlAddCert(CSSM_CC_HANDLE CCHandle, + const CssmData &Cert, + uint32 NumberOfFields, + const CSSM_FIELD CrlEntryFields[], + const CssmData &OldCrl, + CssmData &NewCrl) = 0; + virtual void CertGroupToSignedBundle(CSSM_CC_HANDLE CCHandle, + const CSSM_CERTGROUP &CertGroupToBundle, + const CSSM_CERT_BUNDLE_HEADER *BundleInfo, + CssmData &SignedBundle) = 0; + virtual void FreeFieldValue(const CssmData &CertOrCrlOid, + CssmData &Value) = 0; + virtual void CertDescribeFormat(uint32 &NumberOfFields, + CSSM_OID_PTR &OidList) = 0; + virtual void CrlAbortQuery(CSSM_HANDLE ResultsHandle) = 0; + virtual void CrlDescribeFormat(uint32 &NumberOfFields, + CSSM_OID_PTR &OidList) = 0; + virtual void CrlVerify(CSSM_CC_HANDLE CCHandle, + const CssmData &CrlToBeVerified, + const CssmData *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) = 0; + virtual void CertGetKeyInfo(const CssmData &Cert, + CSSM_KEY_PTR &Key) = 0; + virtual void CertVerify(CSSM_CC_HANDLE CCHandle, + const CssmData &CertToBeVerified, + const CssmData *SignerCert, + const CSSM_FIELD *VerifyScope, + uint32 ScopeSize) = 0; + virtual CSSM_HANDLE CertGetFirstCachedFieldValue(CSSM_HANDLE CertHandle, + const CssmData &CertField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) = 0; + virtual CSSM_HANDLE CrlGetFirstCachedFieldValue(CSSM_HANDLE CrlHandle, + const CssmData *CrlRecordIndex, + const CssmData &CrlField, + uint32 &NumberOfMatchedFields, + CSSM_DATA_PTR &Value) = 0; + virtual void CertVerifyWithKey(CSSM_CC_HANDLE CCHandle, + const CssmData &CertToBeVerified) = 0; + virtual void CrlRemoveCert(const CssmData &Cert, + const CssmData &OldCrl, + CssmData &NewCrl) = 0; + virtual void CrlGetAllCachedRecordFields(CSSM_HANDLE CrlHandle, + const CssmData &CrlRecordIndex, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CrlFields) = 0; + virtual void CertGroupFromVerifiedBundle(CSSM_CC_HANDLE CCHandle, + const CSSM_CERT_BUNDLE &CertBundle, + const CssmData *SignerCert, + CSSM_CERTGROUP_PTR &CertGroup) = 0; + virtual bool CrlGetNextCachedFieldValue(CSSM_HANDLE ResultsHandle, + CSSM_DATA_PTR &Value) = 0; + virtual void IsCertInCrl(const CssmData &Cert, + const CssmData &Crl, + CSSM_BOOL &CertFound) = 0; + virtual void CrlCache(const CssmData &Crl, + CSSM_HANDLE &CrlHandle) = 0; + virtual void CertAbortCache(CSSM_HANDLE CertHandle) = 0; +}; + +} // end namespace Security + +#endif //_H_CLABSTRACTSESSION diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp new file mode 100644 index 00000000..a138ed2e --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.cpp @@ -0,0 +1,847 @@ +// +// CSP plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#include +#include +#include +#include + + +CSPAbstractPluginSession::~CSPAbstractPluginSession() +{ /* virtual */ } + +static CSSM_RETURN CSSMCSPI cssm_ObtainPrivateKeyFromPublicKey(CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *PublicKey, + CSSM_KEY_PTR PrivateKey) +{ + BEGIN_API + findSession(CSPHandle).ObtainPrivateKeyFromPublicKey(CssmKey::required(PublicKey), + CssmKey::required(PrivateKey)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GetOperationalStatistics(CSSM_CSP_HANDLE CSPHandle, + CSSM_CSP_OPERATIONAL_STATISTICS *Statistics) +{ + BEGIN_API + findSession(CSPHandle).GetOperationalStatistics(CSPOperationalStatistics::required(Statistics)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_ChangeLoginOwner(CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) +{ + BEGIN_API + findSession(CSPHandle).ChangeLoginOwner(AccessCredentials::required(AccessCred), + Required(NewOwner)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_EventNotify(CSSM_CSP_HANDLE CSPHandle, + CSSM_CONTEXT_EVENT Event, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) +{ + BEGIN_API + findSession(CSPHandle).EventNotify(Event, + CCHandle, + Context::required(Context)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DecryptDataInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).DecryptDataInit(CCHandle, + Context::required(Context), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_SignDataInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) +{ + BEGIN_API + findSession(CSPHandle).SignDataInit(CCHandle, + Context::required(Context)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DigestData(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_DATA_PTR Digest) +{ + BEGIN_API + findSession(CSPHandle).DigestData(CCHandle, + Context::required(Context), + &CssmData::required(DataBufs), + DataBufCount, + CssmData::required(Digest)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GetKeyOwner(CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) +{ + BEGIN_API + findSession(CSPHandle).GetKeyOwner(CssmKey::required(Key), + Required(Owner)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GetLoginAcl(CSSM_CSP_HANDLE CSPHandle, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos) +{ + BEGIN_API + findSession(CSPHandle).GetLoginAcl(SelectionTag, + Required(NumberOfAclInfos), + Required(AclInfos)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyMac(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + const CSSM_DATA *Mac) +{ + BEGIN_API + findSession(CSPHandle).VerifyMac(CCHandle, + Context::required(Context), + &CssmData::required(DataBufs), + DataBufCount, + CssmData::required(Mac)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_SignDataFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Signature) +{ + BEGIN_API + findSession(CSPHandle).SignDataFinal(CCHandle, + CssmData::required(Signature)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyDataUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) +{ + BEGIN_API + findSession(CSPHandle).VerifyDataUpdate(CCHandle, + &CssmData::required(DataBufs), + DataBufCount); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateMac(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_DATA_PTR Mac) +{ + BEGIN_API + findSession(CSPHandle).GenerateMac(CCHandle, + Context::required(Context), + &CssmData::required(DataBufs), + DataBufCount, + CssmData::required(Mac)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyMacFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Mac) +{ + BEGIN_API + findSession(CSPHandle).VerifyMacFinal(CCHandle, + CssmData::required(Mac)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateRandom(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_DATA_PTR RandomNumber) +{ + BEGIN_API + findSession(CSPHandle).GenerateRandom(CCHandle, + Context::required(Context), + CssmData::required(RandomNumber)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_RetrieveUniqueId(CSSM_CSP_HANDLE CSPHandle, + CSSM_DATA_PTR UniqueID) +{ + BEGIN_API + findSession(CSPHandle).RetrieveUniqueId(CssmData::required(UniqueID)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_UnwrapKey(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_KEY *PublicKey, + const CSSM_WRAP_KEY *WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR UnwrappedKey, + CSSM_DATA_PTR DescriptiveData, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).UnwrapKey(CCHandle, + Context::required(Context), + CssmKey::optional(PublicKey), + CssmKey::required(WrappedKey), + KeyUsage, + KeyAttr, + CssmData::optional(KeyLabel), + CredAndAclEntry, + CssmKey::required(UnwrappedKey), + CssmData::required(DescriptiveData), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateMacFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Mac) +{ + BEGIN_API + findSession(CSPHandle).GenerateMacFinal(CCHandle, + CssmData::required(Mac)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_WrapKey(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_DATA *DescriptiveData, + CSSM_WRAP_KEY_PTR WrappedKey, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).WrapKey(CCHandle, + Context::required(Context), + AccessCredentials::required(AccessCred), + CssmKey::required(Key), + CssmData::optional(DescriptiveData), + CssmKey::required(WrappedKey), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DecryptDataFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RemData) +{ + BEGIN_API + findSession(CSPHandle).DecryptDataFinal(CCHandle, + CssmData::required(RemData)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_SignData(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + CSSM_DATA_PTR Signature) +{ + BEGIN_API + findSession(CSPHandle).SignData(CCHandle, + Context::required(Context), + &CssmData::required(DataBufs), + DataBufCount, + DigestAlgorithm, + CssmData::required(Signature)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_EncryptDataInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).EncryptDataInit(CCHandle, + Context::required(Context), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyData(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *DataBufs, + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + const CSSM_DATA *Signature) +{ + BEGIN_API + findSession(CSPHandle).VerifyData(CCHandle, + Context::required(Context), + &CssmData::required(DataBufs), + DataBufCount, + DigestAlgorithm, + CssmData::required(Signature)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateMacUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) +{ + BEGIN_API + findSession(CSPHandle).GenerateMacUpdate(CCHandle, + &CssmData::required(DataBufs), + DataBufCount); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_EncryptDataFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR RemData) +{ + BEGIN_API + findSession(CSPHandle).EncryptDataFinal(CCHandle, + CssmData::required(RemData)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_ChangeKeyOwner(CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_KEY *Key, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) +{ + BEGIN_API + findSession(CSPHandle).ChangeKeyOwner(AccessCredentials::required(AccessCred), + CssmKey::required(Key), + Required(NewOwner)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyMacInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) +{ + BEGIN_API + findSession(CSPHandle).VerifyMacInit(CCHandle, + Context::required(Context)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DigestDataClone(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_CC_HANDLE ClonedCCHandle) +{ + BEGIN_API + findSession(CSPHandle).DigestDataClone(CCHandle, + ClonedCCHandle); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyDataInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) +{ + BEGIN_API + findSession(CSPHandle).VerifyDataInit(CCHandle, + Context::required(Context)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DecryptDataUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted) +{ + BEGIN_API + findSession(CSPHandle).DecryptDataUpdate(CCHandle, + &CssmData::required(CipherBufs), + CipherBufCount, + &CssmData::required(ClearBufs), + ClearBufCount, + Required(bytesDecrypted)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateAlgorithmParams(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 ParamBits, + CSSM_DATA_PTR Param, + uint32 *NumberOfUpdatedAttibutes, + CSSM_CONTEXT_ATTRIBUTE_PTR *UpdatedAttributes) +{ + BEGIN_API + findSession(CSPHandle).GenerateAlgorithmParams(CCHandle, + Context::required(Context), + ParamBits, + CssmData::required(Param), + Required(NumberOfUpdatedAttibutes), + Required(UpdatedAttributes)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GetLoginOwner(CSSM_CSP_HANDLE CSPHandle, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) +{ + BEGIN_API + findSession(CSPHandle).GetLoginOwner(Required(Owner)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GetKeyAcl(CSSM_CSP_HANDLE CSPHandle, + const CSSM_KEY *Key, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos) +{ + BEGIN_API + findSession(CSPHandle).GetKeyAcl(CssmKey::required(Key), + SelectionTag, + Required(NumberOfAclInfos), + Required(AclInfos)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyDevice(CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *DeviceCert) +{ + BEGIN_API + findSession(CSPHandle).VerifyDevice(CssmData::required(DeviceCert)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_EncryptDataUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted) +{ + BEGIN_API + findSession(CSPHandle).EncryptDataUpdate(CCHandle, + &CssmData::required(ClearBufs), + ClearBufCount, + &CssmData::required(CipherBufs), + CipherBufCount, + Required(bytesEncrypted)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DigestDataFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + CSSM_DATA_PTR Digest) +{ + BEGIN_API + findSession(CSPHandle).DigestDataFinal(CCHandle, + CssmData::required(Digest)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_Login(CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_DATA *LoginName, + const void *Reserved) +{ + BEGIN_API + findSession(CSPHandle).Login(AccessCredentials::required(AccessCred), + CssmData::optional(LoginName), + Reserved); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_ChangeKeyAcl(CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit, + const CSSM_KEY *Key) +{ + BEGIN_API + findSession(CSPHandle).ChangeKeyAcl(AccessCredentials::required(AccessCred), + Required(AclEdit), + CssmKey::required(Key)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_SignDataUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) +{ + BEGIN_API + findSession(CSPHandle).SignDataUpdate(CCHandle, + &CssmData::required(DataBufs), + DataBufCount); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_QueryKeySizeInBits(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_KEY *Key, + CSSM_KEY_SIZE_PTR KeySize) +{ + BEGIN_API + findSession(CSPHandle).QueryKeySizeInBits(CCHandle, + Context::optional(Context), + CssmKey::optional(Key), + Required(KeySize)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_Logout(CSSM_CSP_HANDLE CSPHandle) +{ + BEGIN_API + findSession(CSPHandle).Logout(); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DecryptData(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *CipherBufs, + uint32 CipherBufCount, + CSSM_DATA_PTR ClearBufs, + uint32 ClearBufCount, + CSSM_SIZE *bytesDecrypted, + CSSM_DATA_PTR RemData, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).DecryptData(CCHandle, + Context::required(Context), + &CssmData::required(CipherBufs), + CipherBufCount, + &CssmData::required(ClearBufs), + ClearBufCount, + Required(bytesDecrypted), + CssmData::required(RemData), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DigestDataInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) +{ + BEGIN_API + findSession(CSPHandle).DigestDataInit(CCHandle, + Context::required(Context)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyDataFinal(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *Signature) +{ + BEGIN_API + findSession(CSPHandle).VerifyDataFinal(CCHandle, + CssmData::required(Signature)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateKeyPair(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CSSM_DATA *PublicKeyLabel, + CSSM_KEY_PTR PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CSSM_DATA *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR PrivateKey, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).GenerateKeyPair(CCHandle, + Context::required(Context), + PublicKeyUsage, + PublicKeyAttr, + CssmData::optional(PublicKeyLabel), + CssmKey::required(PublicKey), + PrivateKeyUsage, + PrivateKeyAttr, + CssmData::optional(PrivateKeyLabel), + CredAndAclEntry, + CssmKey::required(PrivateKey), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_EncryptData(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + const CSSM_DATA *ClearBufs, + uint32 ClearBufCount, + CSSM_DATA_PTR CipherBufs, + uint32 CipherBufCount, + CSSM_SIZE *bytesEncrypted, + CSSM_DATA_PTR RemData, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).EncryptData(CCHandle, + Context::required(Context), + &CssmData::required(ClearBufs), + ClearBufCount, + &CssmData::required(CipherBufs), + CipherBufCount, + Required(bytesEncrypted), + CssmData::required(RemData), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GetTimeValue(CSSM_CSP_HANDLE CSPHandle, + CSSM_ALGORITHMS TimeAlgorithm, + CSSM_DATA *TimeData) +{ + BEGIN_API + findSession(CSPHandle).GetTimeValue(TimeAlgorithm, + CssmData::required(TimeData)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DeriveKey(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_DATA_PTR Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR DerivedKey) +{ + BEGIN_API + findSession(CSPHandle).DeriveKey(CCHandle, + Context::required(Context), + CssmData::required(Param), + KeyUsage, + KeyAttr, + CssmData::optional(KeyLabel), + CredAndAclEntry, + CssmKey::required(DerivedKey)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateKey(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 KeyUsage, + uint32 KeyAttr, + const CSSM_DATA *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CSSM_KEY_PTR Key, + CSSM_PRIVILEGE Privilege) +{ + BEGIN_API + findSession(CSPHandle).GenerateKey(CCHandle, + Context::required(Context), + KeyUsage, + KeyAttr, + CssmData::optional(KeyLabel), + CredAndAclEntry, + CssmKey::required(Key), + Privilege); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_PassThrough(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + uint32 PassThroughId, + const void *InData, + void **OutData) +{ + BEGIN_API + findSession(CSPHandle).PassThrough(CCHandle, + Context::required(Context), + PassThroughId, + InData, + OutData); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_VerifyMacUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) +{ + BEGIN_API + findSession(CSPHandle).VerifyMacUpdate(CCHandle, + &CssmData::required(DataBufs), + DataBufCount); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_FreeKey(CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + CSSM_KEY_PTR KeyPtr, + CSSM_BOOL Delete) +{ + BEGIN_API + findSession(CSPHandle).FreeKey(AccessCredentials::optional(AccessCred), + CssmKey::required(KeyPtr), + Delete); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_GenerateMacInit(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context) +{ + BEGIN_API + findSession(CSPHandle).GenerateMacInit(CCHandle, + Context::required(Context)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_RetrieveCounter(CSSM_CSP_HANDLE CSPHandle, + CSSM_DATA_PTR Counter) +{ + BEGIN_API + findSession(CSPHandle).RetrieveCounter(CssmData::required(Counter)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_QuerySize(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_CONTEXT *Context, + CSSM_BOOL Encrypt, + uint32 QuerySizeCount, + CSSM_QUERY_SIZE_DATA_PTR DataBlock) +{ + BEGIN_API + findSession(CSPHandle).QuerySize(CCHandle, + Context::required(Context), + Encrypt, + QuerySizeCount, + QuerySizeData::optional(DataBlock)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_ChangeLoginAcl(CSSM_CSP_HANDLE CSPHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit) +{ + BEGIN_API + findSession(CSPHandle).ChangeLoginAcl(AccessCredentials::required(AccessCred), + Required(AclEdit)); + END_API(CSP) +} + +static CSSM_RETURN CSSMCSPI cssm_DigestDataUpdate(CSSM_CSP_HANDLE CSPHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *DataBufs, + uint32 DataBufCount) +{ + BEGIN_API + findSession(CSPHandle).DigestDataUpdate(CCHandle, + &CssmData::required(DataBufs), + DataBufCount); + END_API(CSP) +} + + +static const CSSM_SPI_CSP_FUNCS CSPFunctionStruct = { + cssm_EventNotify, + cssm_QuerySize, + cssm_SignData, + cssm_SignDataInit, + cssm_SignDataUpdate, + cssm_SignDataFinal, + cssm_VerifyData, + cssm_VerifyDataInit, + cssm_VerifyDataUpdate, + cssm_VerifyDataFinal, + cssm_DigestData, + cssm_DigestDataInit, + cssm_DigestDataUpdate, + cssm_DigestDataClone, + cssm_DigestDataFinal, + cssm_GenerateMac, + cssm_GenerateMacInit, + cssm_GenerateMacUpdate, + cssm_GenerateMacFinal, + cssm_VerifyMac, + cssm_VerifyMacInit, + cssm_VerifyMacUpdate, + cssm_VerifyMacFinal, + cssm_EncryptData, + cssm_EncryptDataInit, + cssm_EncryptDataUpdate, + cssm_EncryptDataFinal, + cssm_DecryptData, + cssm_DecryptDataInit, + cssm_DecryptDataUpdate, + cssm_DecryptDataFinal, + cssm_QueryKeySizeInBits, + cssm_GenerateKey, + cssm_GenerateKeyPair, + cssm_GenerateRandom, + cssm_GenerateAlgorithmParams, + cssm_WrapKey, + cssm_UnwrapKey, + cssm_DeriveKey, + cssm_FreeKey, + cssm_PassThrough, + cssm_Login, + cssm_Logout, + cssm_ChangeLoginAcl, + cssm_ObtainPrivateKeyFromPublicKey, + cssm_RetrieveUniqueId, + cssm_RetrieveCounter, + cssm_VerifyDevice, + cssm_GetTimeValue, + cssm_GetOperationalStatistics, + cssm_GetLoginAcl, + cssm_GetKeyAcl, + cssm_ChangeKeyAcl, + cssm_GetKeyOwner, + cssm_ChangeKeyOwner, + cssm_GetLoginOwner, + cssm_ChangeLoginOwner, +}; + +static CSSM_MODULE_FUNCS CSPFunctionTable = { + CSSM_SERVICE_CSP, // service type + 57, // number of functions + (const CSSM_PROC_ADDR *)&CSPFunctionStruct +}; + +CSSM_MODULE_FUNCS_PTR CSPPluginSession::construct() +{ + return &CSPFunctionTable; +} diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.h b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.h new file mode 100644 index 00000000..2f7f92e2 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPabstractsession.h @@ -0,0 +1,239 @@ +// +// CSP plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#ifndef _H_CSPABSTRACTSESSION +#define _H_CSPABSTRACTSESSION + +#include +#include +#include +#include +#include + + +namespace Security { + + +// +// A pure abstract class to define the CSP module interface +// +class CSPAbstractPluginSession { +public: + virtual ~CSPAbstractPluginSession(); + virtual void VerifyMacFinal(CSSM_CC_HANDLE CCHandle, + const CssmData &Mac) = 0; + virtual void GenerateRandom(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &RandomNumber) = 0; + virtual void RetrieveUniqueId(CssmData &UniqueID) = 0; + virtual void SignDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Signature) = 0; + virtual void VerifyDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount) = 0; + virtual void GenerateMac(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CssmData &Mac) = 0; + virtual void VerifyMac(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + const CssmData &Mac) = 0; + virtual void ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, + CssmKey &PrivateKey) = 0; + virtual void ChangeLoginOwner(const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) = 0; + virtual void SignDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context) = 0; + virtual void DecryptDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_PRIVILEGE Privilege) = 0; + virtual void EventNotify(CSSM_CONTEXT_EVENT Event, + CSSM_CC_HANDLE CCHandle, + const Context &Context) = 0; + virtual void GetOperationalStatistics(CSPOperationalStatistics &Statistics) = 0; + virtual void DigestData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CssmData &Digest) = 0; + virtual void GetLoginAcl(const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) = 0; + virtual void GetKeyOwner(const CssmKey &Key, + CSSM_ACL_OWNER_PROTOTYPE &Owner) = 0; + virtual void ChangeKeyOwner(const AccessCredentials &AccessCred, + const CssmKey &Key, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) = 0; + virtual void VerifyMacInit(CSSM_CC_HANDLE CCHandle, + const Context &Context) = 0; + virtual void DigestDataClone(CSSM_CC_HANDLE CCHandle, + CSSM_CC_HANDLE ClonedCCHandle) = 0; + virtual void GenerateMacUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount) = 0; + virtual void EncryptDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &RemData) = 0; + virtual void EncryptDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_PRIVILEGE Privilege) = 0; + virtual void VerifyData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + const CssmData &Signature) = 0; + virtual void UnwrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmKey *PublicKey, + const CssmKey &WrappedKey, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &UnwrappedKey, + CssmData &DescriptiveData, + CSSM_PRIVILEGE Privilege) = 0; + virtual void GenerateMacFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Mac) = 0; + virtual void WrapKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const AccessCredentials &AccessCred, + const CssmKey &Key, + const CssmData *DescriptiveData, + CssmKey &WrappedKey, + CSSM_PRIVILEGE Privilege) = 0; + virtual void DecryptDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &RemData) = 0; + virtual void SignData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData DataBufs[], + uint32 DataBufCount, + CSSM_ALGORITHMS DigestAlgorithm, + CssmData &Signature) = 0; + virtual void SignDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount) = 0; + virtual void Logout() = 0; + virtual void DecryptData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData CipherBufs[], + uint32 CipherBufCount, + CssmData ClearBufs[], + uint32 ClearBufCount, + CSSM_SIZE &bytesDecrypted, + CssmData &RemData, + CSSM_PRIVILEGE Privilege) = 0; + virtual void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, + const Context *Context, + const CssmKey *Key, + CSSM_KEY_SIZE &KeySize) = 0; + virtual void DigestDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context) = 0; + virtual void DigestDataFinal(CSSM_CC_HANDLE CCHandle, + CssmData &Digest) = 0; + virtual void Login(const AccessCredentials &AccessCred, + const CssmData *LoginName, + const void *Reserved) = 0; + virtual void ChangeKeyAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit, + const CssmKey &Key) = 0; + virtual void GetKeyAcl(const CssmKey &Key, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) = 0; + virtual void GenerateAlgorithmParams(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 ParamBits, + CssmData &Param, + uint32 &NumberOfUpdatedAttibutes, + CSSM_CONTEXT_ATTRIBUTE_PTR &UpdatedAttributes) = 0; + virtual void GetLoginOwner(CSSM_ACL_OWNER_PROTOTYPE &Owner) = 0; + virtual void VerifyDevice(const CssmData &DeviceCert) = 0; + virtual void EncryptDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData ClearBufs[], + uint32 ClearBufCount, + CssmData CipherBufs[], + uint32 CipherBufCount, + CSSM_SIZE &bytesEncrypted) = 0; + virtual void VerifyDataInit(CSSM_CC_HANDLE CCHandle, + const Context &Context) = 0; + virtual void DecryptDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData CipherBufs[], + uint32 CipherBufCount, + CssmData ClearBufs[], + uint32 ClearBufCount, + CSSM_SIZE &bytesDecrypted) = 0; + virtual void ChangeLoginAcl(const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit) = 0; + virtual void DigestDataUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount) = 0; + virtual void GenerateMacInit(CSSM_CC_HANDLE CCHandle, + const Context &Context) = 0; + virtual void QuerySize(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CSSM_BOOL Encrypt, + uint32 QuerySizeCount, + QuerySizeData *DataBlock) = 0; + virtual void RetrieveCounter(CssmData &Counter) = 0; + virtual void DeriveKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + CssmData &Param, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &DerivedKey) = 0; + virtual void GenerateKey(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 KeyUsage, + uint32 KeyAttr, + const CssmData *KeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &Key, + CSSM_PRIVILEGE Privilege) = 0; + virtual void FreeKey(const AccessCredentials *AccessCred, + CssmKey &KeyPtr, + CSSM_BOOL Delete) = 0; + virtual void PassThrough(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PassThroughId, + const void *InData, + void **OutData) = 0; + virtual void VerifyMacUpdate(CSSM_CC_HANDLE CCHandle, + const CssmData DataBufs[], + uint32 DataBufCount) = 0; + virtual void VerifyDataFinal(CSSM_CC_HANDLE CCHandle, + const CssmData &Signature) = 0; + virtual void GenerateKeyPair(CSSM_CC_HANDLE CCHandle, + const Context &Context, + uint32 PublicKeyUsage, + uint32 PublicKeyAttr, + const CssmData *PublicKeyLabel, + CssmKey &PublicKey, + uint32 PrivateKeyUsage, + uint32 PrivateKeyAttr, + const CssmData *PrivateKeyLabel, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + CssmKey &PrivateKey, + CSSM_PRIVILEGE Privilege) = 0; + virtual void GetTimeValue(CSSM_ALGORITHMS TimeAlgorithm, + CssmData &TimeData) = 0; + virtual void EncryptData(CSSM_CC_HANDLE CCHandle, + const Context &Context, + const CssmData ClearBufs[], + uint32 ClearBufCount, + CssmData CipherBufs[], + uint32 CipherBufCount, + CSSM_SIZE &bytesEncrypted, + CssmData &RemData, + CSSM_PRIVILEGE Privilege) = 0; +}; + +} // end namespace Security + +#endif //_H_CSPABSTRACTSESSION diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp index f2b674ff..a66e068d 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp @@ -1045,7 +1045,7 @@ KeyPool::add(ReferencedKey &referencedKey) // never add a key that is already in mKeyMap assert(inserted); - secdebug("SecAccessReference", "added a referenced key %p for key reference %d", &referencedKey, referencedKey.keyReference()); + secinfo("SecAccessReference", "added a referenced key %p for key reference %ld", &referencedKey, referencedKey.keyReference()); } ReferencedKey & @@ -1062,7 +1062,7 @@ KeyPool::findKeyReference(ReferencedKey::KeyReference keyReference) const if (it == mKeyMap.end()) CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_REFERENCE); - secdebug("SecAccessReference", "found a referenced key %p for key reference %d [%d]", it->second, keyReference, it->second->keyReference()); + secinfo("SecAccessReference", "found a referenced key %p for key reference %ld [%ld]", it->second, keyReference, it->second->keyReference()); return *it->second; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp new file mode 100644 index 00000000..d29da3d4 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.cpp @@ -0,0 +1,333 @@ +// +// DL plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#include +#include +#include +#include + + +DLAbstractPluginSession::~DLAbstractPluginSession() +{ /* virtual */ } + +static CSSM_RETURN CSSMDLI cssm_DataGetFirst(CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_QUERY *Query, + CSSM_HANDLE_PTR ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) +{ + BEGIN_API + if ((Required(ResultsHandle) = findSession(DLDBHandle.DLHandle).DataGetFirst(DLDBHandle.DBHandle, + CssmQuery::optional(Query), + Attributes, + CssmData::optional(Data), + Required(UniqueId))) == CSSM_INVALID_HANDLE) + return CSSMERR_DL_ENDOFDATA; + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_GetDbNames(CSSM_DL_HANDLE DLHandle, + CSSM_NAME_LIST_PTR *NameList) +{ + BEGIN_API + findSession(DLHandle).GetDbNames(Required(NameList)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DbClose(CSSM_DL_DB_HANDLE DLDBHandle) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DbClose(DLDBHandle.DBHandle); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DataInsert(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + const CSSM_DATA *Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DataInsert(DLDBHandle.DBHandle, + RecordType, + Attributes, + CssmData::optional(Data), + Required(UniqueId)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_GetDbNameFromHandle(CSSM_DL_DB_HANDLE DLDBHandle, + char **DbName) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).GetDbNameFromHandle(DLDBHandle.DBHandle, + DbName); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_ChangeDbAcl(CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_EDIT *AclEdit) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).ChangeDbAcl(DLDBHandle.DBHandle, + AccessCredentials::required(AccessCred), + Required(AclEdit)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_FreeNameList(CSSM_DL_HANDLE DLHandle, + CSSM_NAME_LIST_PTR NameList) +{ + BEGIN_API + findSession(DLHandle).FreeNameList(Required(NameList)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_CreateRelation(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RelationID, + const char *RelationName, + uint32 NumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 NumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO *pIndexInfo) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).CreateRelation(DLDBHandle.DBHandle, + RelationID, + RelationName, + NumberOfAttributes, + pAttributeInfo, + NumberOfIndexes, + Required(pIndexInfo)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DataAbortQuery(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_HANDLE ResultsHandle) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DataAbortQuery(DLDBHandle.DBHandle, + ResultsHandle); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DataModify(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, + const CSSM_DATA *DataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DataModify(DLDBHandle.DBHandle, + RecordType, + Required(UniqueRecordIdentifier), + AttributesToBeModified, + CssmData::optional(DataToBeModified), + ModifyMode); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DestroyRelation(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_RECORDTYPE RelationID) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DestroyRelation(DLDBHandle.DBHandle, + RelationID); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DbCreate(CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO *DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + const void *OpenParameters, + CSSM_DB_HANDLE *DbHandle) +{ + BEGIN_API + findSession(DLHandle).DbCreate(DbName, + DbLocation, + Required(DBInfo), + AccessRequest, + CredAndAclEntry, + OpenParameters, + Required(DbHandle)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DbOpen(CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const void *OpenParameters, + CSSM_DB_HANDLE *DbHandle) +{ + BEGIN_API + findSession(DLHandle).DbOpen(DbName, + DbLocation, + AccessRequest, + AccessCredentials::optional(AccessCred), + OpenParameters, + Required(DbHandle)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DataGetNext(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data, + CSSM_DB_UNIQUE_RECORD_PTR *UniqueId) +{ + BEGIN_API + if (!findSession(DLDBHandle.DLHandle).DataGetNext(DLDBHandle.DBHandle, + ResultsHandle, + Attributes, + CssmData::optional(Data), + Required(UniqueId))) + return CSSMERR_DL_ENDOFDATA; + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_FreeUniqueRecord(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_UNIQUE_RECORD_PTR UniqueRecord) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).FreeUniqueRecord(DLDBHandle.DBHandle, + Required(UniqueRecord)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_ChangeDbOwner(CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_ACCESS_CREDENTIALS *AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE *NewOwner) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).ChangeDbOwner(DLDBHandle.DBHandle, + AccessCredentials::required(AccessCred), + Required(NewOwner)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DbDelete(CSSM_DL_HANDLE DLHandle, + const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_ACCESS_CREDENTIALS *AccessCred) +{ + BEGIN_API + findSession(DLHandle).DbDelete(DbName, + DbLocation, + AccessCredentials::optional(AccessCred)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_Authenticate(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_ACCESS_CREDENTIALS *AccessCred) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).Authenticate(DLDBHandle.DBHandle, + AccessRequest, + AccessCredentials::required(AccessCred)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DataDelete(CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_DB_UNIQUE_RECORD *UniqueRecordIdentifier) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DataDelete(DLDBHandle.DBHandle, + Required(UniqueRecordIdentifier)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_GetDbOwner(CSSM_DL_DB_HANDLE DLDBHandle, + CSSM_ACL_OWNER_PROTOTYPE_PTR Owner) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).GetDbOwner(DLDBHandle.DBHandle, + Required(Owner)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_PassThrough(CSSM_DL_DB_HANDLE DLDBHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).PassThrough(DLDBHandle.DBHandle, + PassThroughId, + InputParams, + OutputParams); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_GetDbAcl(CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_STRING *SelectionTag, + uint32 *NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR *AclInfos) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).GetDbAcl(DLDBHandle.DBHandle, + SelectionTag, + Required(NumberOfAclInfos), + Required(AclInfos)); + END_API(DL) +} + +static CSSM_RETURN CSSMDLI cssm_DataGetFromUniqueRecordId(CSSM_DL_DB_HANDLE DLDBHandle, + const CSSM_DB_UNIQUE_RECORD *UniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR Attributes, + CSSM_DATA_PTR Data) +{ + BEGIN_API + findSession(DLDBHandle.DLHandle).DataGetFromUniqueRecordId(DLDBHandle.DBHandle, + Required(UniqueRecord), + Attributes, + CssmData::optional(Data)); + END_API(DL) +} + + +static const CSSM_SPI_DL_FUNCS DLFunctionStruct = { + cssm_DbOpen, + cssm_DbClose, + cssm_DbCreate, + cssm_DbDelete, + cssm_CreateRelation, + cssm_DestroyRelation, + cssm_Authenticate, + cssm_GetDbAcl, + cssm_ChangeDbAcl, + cssm_GetDbOwner, + cssm_ChangeDbOwner, + cssm_GetDbNames, + cssm_GetDbNameFromHandle, + cssm_FreeNameList, + cssm_DataInsert, + cssm_DataDelete, + cssm_DataModify, + cssm_DataGetFirst, + cssm_DataGetNext, + cssm_DataAbortQuery, + cssm_DataGetFromUniqueRecordId, + cssm_FreeUniqueRecord, + cssm_PassThrough, +}; + +static CSSM_MODULE_FUNCS DLFunctionTable = { + CSSM_SERVICE_DL, // service type + 23, // number of functions + (const CSSM_PROC_ADDR *)&DLFunctionStruct +}; + +CSSM_MODULE_FUNCS_PTR DLPluginSession::construct() +{ + return &DLFunctionTable; +} diff --git a/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.h b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.h new file mode 100644 index 00000000..5457e6f8 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/DLabstractsession.h @@ -0,0 +1,107 @@ +// +// DL plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#ifndef _H_DLABSTRACTSESSION +#define _H_DLABSTRACTSESSION + +#include +#include +#include +#include + + +namespace Security { + + +// +// A pure abstract class to define the DL module interface +// +class DLAbstractPluginSession { +public: + virtual ~DLAbstractPluginSession(); + virtual void FreeNameList(CSSM_NAME_LIST &NameList) = 0; + virtual void CreateRelation(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RelationID, + const char *RelationName, + uint32 NumberOfAttributes, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *pAttributeInfo, + uint32 NumberOfIndexes, + const CSSM_DB_SCHEMA_INDEX_INFO &pIndexInfo) = 0; + virtual void DataModify(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RecordType, + CSSM_DB_UNIQUE_RECORD &UniqueRecordIdentifier, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *AttributesToBeModified, + const CssmData *DataToBeModified, + CSSM_DB_MODIFY_MODE ModifyMode) = 0; + virtual void DataAbortQuery(CSSM_DB_HANDLE DBHandle, + CSSM_HANDLE ResultsHandle) = 0; + virtual void DestroyRelation(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RelationID) = 0; + virtual void DbCreate(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const CSSM_DBINFO &DBInfo, + CSSM_DB_ACCESS_TYPE AccessRequest, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry, + const void *OpenParameters, + CSSM_DB_HANDLE &DbHandle) = 0; + virtual CSSM_HANDLE DataGetFirst(CSSM_DB_HANDLE DBHandle, + const CssmQuery *Query, + CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId) = 0; + virtual void GetDbNames(CSSM_NAME_LIST_PTR &NameList) = 0; + virtual void DbClose(CSSM_DB_HANDLE DBHandle) = 0; + virtual void GetDbNameFromHandle(CSSM_DB_HANDLE DBHandle, + char **DbName) = 0; + virtual void DataInsert(CSSM_DB_HANDLE DBHandle, + CSSM_DB_RECORDTYPE RecordType, + const CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + const CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId) = 0; + virtual void ChangeDbAcl(CSSM_DB_HANDLE DBHandle, + const AccessCredentials &AccessCred, + const CSSM_ACL_EDIT &AclEdit) = 0; + virtual void PassThrough(CSSM_DB_HANDLE DBHandle, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) = 0; + virtual void GetDbAcl(CSSM_DB_HANDLE DBHandle, + const CSSM_STRING *SelectionTag, + uint32 &NumberOfAclInfos, + CSSM_ACL_ENTRY_INFO_PTR &AclInfos) = 0; + virtual void DataGetFromUniqueRecordId(CSSM_DB_HANDLE DBHandle, + const CSSM_DB_UNIQUE_RECORD &UniqueRecord, + CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + CssmData *Data) = 0; + virtual void DbOpen(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + CSSM_DB_ACCESS_TYPE AccessRequest, + const AccessCredentials *AccessCred, + const void *OpenParameters, + CSSM_DB_HANDLE &DbHandle) = 0; + virtual bool DataGetNext(CSSM_DB_HANDLE DBHandle, + CSSM_HANDLE ResultsHandle, + CSSM_DB_RECORD_ATTRIBUTE_DATA *Attributes, + CssmData *Data, + CSSM_DB_UNIQUE_RECORD_PTR &UniqueId) = 0; + virtual void FreeUniqueRecord(CSSM_DB_HANDLE DBHandle, + CSSM_DB_UNIQUE_RECORD &UniqueRecord) = 0; + virtual void ChangeDbOwner(CSSM_DB_HANDLE DBHandle, + const AccessCredentials &AccessCred, + const CSSM_ACL_OWNER_PROTOTYPE &NewOwner) = 0; + virtual void Authenticate(CSSM_DB_HANDLE DBHandle, + CSSM_DB_ACCESS_TYPE AccessRequest, + const AccessCredentials &AccessCred) = 0; + virtual void DbDelete(const char *DbName, + const CSSM_NET_ADDRESS *DbLocation, + const AccessCredentials *AccessCred) = 0; + virtual void DataDelete(CSSM_DB_HANDLE DBHandle, + const CSSM_DB_UNIQUE_RECORD &UniqueRecordIdentifier) = 0; + virtual void GetDbOwner(CSSM_DB_HANDLE DBHandle, + CSSM_ACL_OWNER_PROTOTYPE &Owner) = 0; +}; + +} // end namespace Security + +#endif //_H_DLABSTRACTSESSION diff --git a/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp b/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp index 637806ba..1930ad9c 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/DatabaseSession.cpp @@ -28,7 +28,7 @@ #include /* log open/close events */ -#define DOCDebug(args...) secdebug("DBOpen", ## args) +#define DOCDebug(args...) secinfo("DBOpen", ## args) using namespace std; @@ -52,29 +52,26 @@ DatabaseSession::~DatabaseSession() void DatabaseSession::GetDbNames(CSSM_NAME_LIST_PTR &outNameList) { - secdebug("dbsession", "GetDbNames"); + secinfo("dbsession", "GetDbNames"); outNameList = mDatabaseManager.getDbNames (*this); #ifndef NDEBUG // dump the returned names uint32 n; - secdebug("dbsession", "GetDbNames returned %d names", outNameList->NumStrings); + secinfo("dbsession", "GetDbNames returned %d names", outNameList->NumStrings); for (n = 0; n < outNameList->NumStrings; ++n) { - secdebug("dbsession", "%d: %s", n, outNameList->String[n]); + secinfo("dbsession", "%d: %s", n, outNameList->String[n]); } #endif - - secdebug("dbsession", "********************"); } void DatabaseSession::FreeNameList(CSSM_NAME_LIST &inNameList) { - secdebug("dbsession", "FreeNameList"); + secinfo("dbsession", "FreeNameList"); mDatabaseManager.freeNameList (*this, inNameList); - secdebug("dbsession", "********************"); } @@ -85,9 +82,8 @@ DatabaseSession::DbDelete(const char *inDbName, { // The databaseManager will notify all its DbContext instances // that the database is question is being deleted. - secdebug("dbsession", "DbDelete of %s", inDbName); + secnotice("dbsession", "DbDelete of %s", inDbName); mDatabaseManager.dbDelete(*this, DbName(inDbName, CssmNetAddress::optional(inDbLocation)), inAccessCred); - secdebug("dbsession", "********************"); } // DbContext creation and destruction. @@ -101,7 +97,7 @@ DatabaseSession::DbCreate(const char *inDbName, CSSM_DB_HANDLE &outDbHandle) { outDbHandle = CSSM_INVALID_HANDLE; // CDSA 2.0 says to set this if we fail - secdebug("dbsession", "DbCreate of %s", inDbName); + secnotice("dbsession", "DbCreate of %s", inDbName); outDbHandle = insertDbContext(mDatabaseManager.dbCreate(*this, DbName(inDbName, CssmNetAddress::optional(inDbLocation)), @@ -109,9 +105,7 @@ DatabaseSession::DbCreate(const char *inDbName, inAccessRequest, inCredAndAclEntry, inOpenParameters)); - secdebug("dbsession", "DbCreate returned handle %#lx", outDbHandle); - - secdebug("dbsession", "********************"); + secinfo("dbsession", "DbCreate returned handle %#lx", outDbHandle); } void @@ -123,15 +117,14 @@ DatabaseSession::DbOpen(const char *inDbName, CSSM_DB_HANDLE &outDbHandle) { DOCDebug("DatabaseSession::DbOpen: dbName %s", inDbName); - secdebug("dbsession", "DbOpen of %s", inDbName); + secnotice("dbsession", "DbOpen of %s", inDbName); outDbHandle = CSSM_INVALID_HANDLE; // CDSA 2.0 says to set this if we fail outDbHandle = insertDbContext(mDatabaseManager.dbOpen(*this, DbName(inDbName, CssmNetAddress::optional(inDbLocation)), inAccessRequest, inAccessCred, inOpenParameters)); - secdebug("dbsession", "DbOpen returned handle %#lx", outDbHandle); - secdebug("dbsession", "********************"); + secinfo("dbsession", "DbOpen returned handle %#lx", outDbHandle); } CSSM_DB_HANDLE @@ -187,7 +180,6 @@ DatabaseSession::closeAll() } mDbContextMap.clear(); - secdebug("dbsession", "********************"); } // Operations using DbContext instances. @@ -196,14 +188,13 @@ DatabaseSession::DbClose(CSSM_DB_HANDLE inDbHandle) { StLock _(mDbContextMapLock); DOCDebug("DatabaseSession::Close"); - secdebug("dbsession", "DbClose of handle %ld", inDbHandle); + secinfo("dbsession", "DbClose of handle %ld", inDbHandle); DbContextMap::iterator it = mDbContextMap.find(inDbHandle); if (it == mDbContextMap.end()) CssmError::throwMe(CSSM_ERRCODE_INVALID_DB_HANDLE); auto_ptr aDbContext(it->second); mDbContextMap.erase(it); mDatabaseManager.dbClose(*aDbContext); - secdebug("dbsession", "********************"); } void @@ -215,23 +206,23 @@ DatabaseSession::CreateRelation(CSSM_DB_HANDLE inDbHandle, uint32 inNumberOfIndexes, const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) { - secdebug("dbsession", "CreateRelation from handle %ld of record type %X with relation name %s", inDbHandle, inRelationID, inRelationName); - secdebug("dbsession", "number of attributes = %d", inNumberOfAttributes); + secinfo("dbsession", "CreateRelation from handle %ld of record type %X with relation name %s", inDbHandle, inRelationID, inRelationName); + secinfo("dbsession", "number of attributes = %d", inNumberOfAttributes); #ifndef NDEBUG unsigned n; for (n = 0; n < inNumberOfAttributes; ++n) { - secdebug("dbsession", "%d: id %d name %s, data type %d", n, inAttributeInfo[n].AttributeId, + secinfo("dbsession", "%d: id %d name %s, data type %d", n, inAttributeInfo[n].AttributeId, inAttributeInfo[n].AttributeName, inAttributeInfo[n].DataType); } #endif - secdebug("dbsession", "number of indexes: %d", inNumberOfIndexes); + secinfo("dbsession", "number of indexes: %d", inNumberOfIndexes); #ifndef NDEBUG for (n = 0; n < inNumberOfIndexes; ++n) { - secdebug("dbsession", "%d: id %d indexid %d indextype %d location %d", n, inIndexInfo.AttributeId, + secinfo("dbsession", "%d: id %d indexid %d indextype %d location %d", n, inIndexInfo.AttributeId, inIndexInfo.IndexedDataLocation, inIndexInfo.IndexId, inIndexInfo.IndexType); @@ -242,17 +233,15 @@ DatabaseSession::CreateRelation(CSSM_DB_HANDLE inDbHandle, return aDbContext.mDatabase.createRelation(aDbContext, inRelationID, inRelationName, inNumberOfAttributes, inAttributeInfo, inNumberOfIndexes, inIndexInfo); - secdebug("dbsession", "********************"); } void DatabaseSession::DestroyRelation(CSSM_DB_HANDLE inDbHandle, CSSM_DB_RECORDTYPE inRelationID) { - secdebug("dbsession", "DestroyRelation (handle %ld) %d", inDbHandle, inRelationID); + secinfo("dbsession", "DestroyRelation (handle %ld) %d", inDbHandle, inRelationID); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.destroyRelation(aDbContext, inRelationID); - secdebug("dbsession", "********************"); } void @@ -260,10 +249,9 @@ DatabaseSession::Authenticate(CSSM_DB_HANDLE inDbHandle, CSSM_DB_ACCESS_TYPE inAccessRequest, const AccessCredentials &inAccessCred) { - secdebug("dbsession", "Authenticate (handle %ld) inAccessRequest %d", inDbHandle, inAccessRequest); + secinfo("dbsession", "Authenticate (handle %ld) inAccessRequest %d", inDbHandle, inAccessRequest); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.authenticate(aDbContext, inAccessRequest, inAccessCred); - secdebug("dbsession", "********************"); } @@ -273,10 +261,9 @@ DatabaseSession::GetDbAcl(CSSM_DB_HANDLE inDbHandle, uint32 &outNumberOfAclInfos, CSSM_ACL_ENTRY_INFO_PTR &outAclInfos) { - secdebug("dbsession", "GetDbAcl (handle %ld)", inDbHandle); + secinfo("dbsession", "GetDbAcl (handle %ld)", inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.getDbAcl(aDbContext, inSelectionTag, outNumberOfAclInfos, outAclInfos); - secdebug("dbsession", "********************"); } void @@ -284,20 +271,18 @@ DatabaseSession::ChangeDbAcl(CSSM_DB_HANDLE inDbHandle, const AccessCredentials &inAccessCred, const CSSM_ACL_EDIT &inAclEdit) { - secdebug("dbsession", "ChangeDbAcl (handle %ld)", inDbHandle); + secinfo("dbsession", "ChangeDbAcl (handle %ld)", inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.changeDbAcl(aDbContext, inAccessCred, inAclEdit); - secdebug("dbsession", "********************"); } void DatabaseSession::GetDbOwner(CSSM_DB_HANDLE inDbHandle, CSSM_ACL_OWNER_PROTOTYPE &outOwner) { - secdebug("dbsession", "GetDbOwner (handle %ld)", inDbHandle); + secinfo("dbsession", "GetDbOwner (handle %ld)", inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.getDbOwner(aDbContext, outOwner); - secdebug("dbsession", "********************"); } void @@ -305,21 +290,19 @@ DatabaseSession::ChangeDbOwner(CSSM_DB_HANDLE inDbHandle, const AccessCredentials &inAccessCred, const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) { - secdebug("dbsession", "ChangeDbOwner (handle %ld)", inDbHandle); + secinfo("dbsession", "ChangeDbOwner (handle %ld)", inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.changeDbOwner(aDbContext, inAccessCred, inNewOwner); - secdebug("dbsession", "********************"); } void DatabaseSession::GetDbNameFromHandle(CSSM_DB_HANDLE inDbHandle, char **outDbName) { - secdebug("dbsession", "GetDbNameFromHandle (handle %ld)", inDbHandle); + secinfo("dbsession", "GetDbNameFromHandle (handle %ld)", inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); Required(outDbName) = aDbContext.mDatabase.getDbNameFromHandle(aDbContext); - secdebug("dbsession", "name: %s", *outDbName); - secdebug("dbsession", "********************"); + secinfo("dbsession", "name: %s", *outDbName); } @@ -346,19 +329,19 @@ void DumpAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &info) break; } - secdebug("dbsession", " Attribute name type: %s", attrNameType); + secinfo("dbsession", " Attribute name type: %s", attrNameType); switch (info.AttributeFormat) { case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: - secdebug("dbsession", " name: %s", info.Label.AttributeName); + secinfo("dbsession", " name: %s", info.Label.AttributeName); break; case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: - secdebug("dbsession", " name: %d", info.Label.AttributeID); + secinfo("dbsession", " name: %d", info.Label.AttributeID); break; case CSSM_DB_ATTRIBUTE_NAME_AS_OID: - secdebug("dbsession", " name is oid"); + secinfo("dbsession", " name is oid"); break; } @@ -394,7 +377,7 @@ void DumpAttributeInfo(const CSSM_DB_ATTRIBUTE_INFO &info) break; } - secdebug("dbsession", " attribute format: %s", s); + secinfo("dbsession", " attribute format: %s", s); } @@ -403,20 +386,20 @@ void DumpAttributes(const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes) { if (!inAttributes) { - secdebug("dbsession", "No attributes defined."); + secinfo("dbsession", "No attributes defined."); return; } - secdebug("dbsession", "insert into %d", inAttributes->DataRecordType); - secdebug("dbsession", "Semantic information %d", inAttributes->SemanticInformation); - secdebug("dbsession", "Number of attributes: %d", inAttributes->NumberOfAttributes); + secinfo("dbsession", "insert into %d", inAttributes->DataRecordType); + secinfo("dbsession", "Semantic information %d", inAttributes->SemanticInformation); + secinfo("dbsession", "Number of attributes: %d", inAttributes->NumberOfAttributes); unsigned n; for (n = 0; n < inAttributes->NumberOfAttributes; ++n) { DumpAttributeInfo(inAttributes->AttributeData[n].Info); - secdebug("dbsession", "Attribute %d\n", n); - secdebug("dbsession", " number of values: %d", inAttributes->AttributeData[n].NumberOfValues); + secinfo("dbsession", "Attribute %d\n", n); + secinfo("dbsession", " number of values: %d", inAttributes->AttributeData[n].NumberOfValues); unsigned i; for (i = 0; i < inAttributes->AttributeData[n].NumberOfValues; ++i) { @@ -425,26 +408,26 @@ void DumpAttributes(const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes) case CSSM_DB_ATTRIBUTE_FORMAT_STRING: { std::string ss((char*) inAttributes->AttributeData[n].Value[i].Data, inAttributes->AttributeData[n].Value[i].Length); - secdebug("dbsession", " Value %d: %s", i, ss.c_str()); + secinfo("dbsession", " Value %d: %s", i, ss.c_str()); break; } case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: - secdebug("dbsession", " Value %d: %d", i, *(sint32*)inAttributes->AttributeData[n].Value[i].Data); + secinfo("dbsession", " Value %d: %d", i, *(sint32*)inAttributes->AttributeData[n].Value[i].Data); break; case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: - secdebug("dbsession", " Value %d: %u", i, *(uint32*)inAttributes->AttributeData[n].Value[i].Data); + secinfo("dbsession", " Value %d: %u", i, *(uint32*)inAttributes->AttributeData[n].Value[i].Data); break; case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM: - secdebug("dbsession", " Value %d: (bignum)", i); + secinfo("dbsession", " Value %d: (bignum)", i); break; case CSSM_DB_ATTRIBUTE_FORMAT_REAL: - secdebug("dbsession", " Value %d: %f", i, *(double*)inAttributes->AttributeData[n].Value[i].Data); + secinfo("dbsession", " Value %d: %f", i, *(double*)inAttributes->AttributeData[n].Value[i].Data); break; case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: - secdebug("dbsession", " Value %d: %s", i, (char*)inAttributes->AttributeData[n].Value[i].Data); + secinfo("dbsession", " Value %d: %s", i, (char*)inAttributes->AttributeData[n].Value[i].Data); break; case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: - secdebug("dbsession", " Value %d: (blob)", i); + secinfo("dbsession", " Value %d: (blob)", i); break; case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32: { @@ -453,14 +436,14 @@ void DumpAttributes(const CSSM_DB_RECORD_ATTRIBUTE_DATA *inAttributes) for (j = 0; j < numInts; ++j) { uint32* nums = (uint32*) inAttributes->AttributeData[n].Value[i].Data; - secdebug("dbsession", " %d", nums[j]); + secinfo("dbsession", " %d", nums[j]); } break; } case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX: - secdebug("dbsession", " Value %d: (complex)", i); + secinfo("dbsession", " Value %d: (complex)", i); break; } } @@ -490,7 +473,7 @@ DumpUniqueRecord(const CSSM_DB_UNIQUE_RECORD &record) } } - secdebug("dbsession", "RecordLocator.IndexType: %s", s); + secinfo("dbsession", "RecordLocator.IndexType: %s", s); switch (record.RecordLocator.IndexedDataLocation) { @@ -513,9 +496,9 @@ DumpUniqueRecord(const CSSM_DB_UNIQUE_RECORD &record) } } - secdebug("dbsession", "RecordLocator.IndexedDataLocation: %s", s); + secinfo("dbsession", "RecordLocator.IndexedDataLocation: %s", s); - secdebug("dbsession", "Attribute info:"); + secinfo("dbsession", "Attribute info:"); DumpAttributeInfo(record.RecordLocator.Info); */ @@ -530,7 +513,7 @@ DumpUniqueRecord(const CSSM_DB_UNIQUE_RECORD &record) output += hexBuffer; } - secdebug("dbsession", " RecordIdentifier.Data: %s", output.c_str()); + secinfo("dbsession", " RecordIdentifier.Data: %s", output.c_str()); } #endif /* NDEBUG */ @@ -541,16 +524,14 @@ DatabaseSession::DataInsert(CSSM_DB_HANDLE inDbHandle, const CssmData *inData, CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId) { - secdebug("dbsession", "%p DataInsert(%lx,%x)", this, inDbHandle, inRecordType); + secinfo("dbsession", "%p DataInsert(%lx,%x)", this, inDbHandle, inRecordType); DbContext &aDbContext = findDbContext(inDbHandle); outUniqueId = aDbContext.mDatabase.dataInsert(aDbContext, inRecordType, inAttributes, inData); #ifndef NDEBUG - secdebug("dbsession", "Returned unique id:"); + secinfo("dbsession", "Returned unique id:"); DumpUniqueRecord(*outUniqueId); #endif - - secdebug("dbsession", "********************"); } @@ -558,15 +539,14 @@ void DatabaseSession::DataDelete(CSSM_DB_HANDLE inDbHandle, const CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) { - secdebug("dbsession", "%p DataDelete(%lx)", this, inDbHandle); + secinfo("dbsession", "%p DataDelete(%lx)", this, inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.dataDelete(aDbContext, inUniqueRecordIdentifier); #ifndef NDEBUG - secdebug("dbsession", "Record identifier:"); + secinfo("dbsession", "Record identifier:"); DumpUniqueRecord(inUniqueRecordIdentifier); #endif - secdebug("dbsession", "********************"); } @@ -578,15 +558,14 @@ DatabaseSession::DataModify(CSSM_DB_HANDLE inDbHandle, const CssmData *inDataToBeModified, CSSM_DB_MODIFY_MODE inModifyMode) { - secdebug("dbsession", "%p DataModify(%lx,%x)", this, inDbHandle, inRecordType); + secinfo("dbsession", "%p DataModify(%lx,%x)", this, inDbHandle, inRecordType); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.dataModify(aDbContext, inRecordType, inoutUniqueRecordIdentifier, inAttributesToBeModified, inDataToBeModified, inModifyMode); #ifndef NDEBUG - secdebug("dbsession", "Out record identifier:"); + secinfo("dbsession", "Out record identifier:"); DumpUniqueRecord(inoutUniqueRecordIdentifier); #endif - secdebug("dbsession", "********************"); } CSSM_HANDLE @@ -596,21 +575,20 @@ DatabaseSession::DataGetFirst(CSSM_DB_HANDLE inDbHandle, CssmData *inoutData, CSSM_DB_UNIQUE_RECORD_PTR &outUniqueId) { - secdebug("dbsession", "%p DataGetFirst(%lx)", this, inDbHandle); + secinfo("dbsession", "%p DataGetFirst(%lx)", this, inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); CSSM_HANDLE result = aDbContext.mDatabase.dataGetFirst(aDbContext, inQuery, inoutAttributes, inoutData, outUniqueId); #ifndef NDEBUG - secdebug("dbsession", "result handle: %lx", result); + secinfo("dbsession", "result handle: %lx", result); if (result != 0) { - secdebug("dbsession", "Returned ID:"); + secinfo("dbsession", "Returned ID:"); DumpUniqueRecord(*outUniqueId); } #endif - secdebug("dbsession", "********************"); return result; } @@ -621,7 +599,7 @@ DatabaseSession::DataGetNext(CSSM_DB_HANDLE inDbHandle, CssmData *inoutData, CSSM_DB_UNIQUE_RECORD_PTR &outUniqueRecord) { - secdebug("dbsession", "DataGetNext(%lx)", inDbHandle); + secinfo("dbsession", "DataGetNext(%lx)", inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); bool result = aDbContext.mDatabase.dataGetNext(aDbContext, inResultsHandle, inoutAttributes, @@ -630,12 +608,11 @@ DatabaseSession::DataGetNext(CSSM_DB_HANDLE inDbHandle, #ifndef NDEBUG if (result) { - secdebug("dbsession", "Returned ID:"); + secinfo("dbsession", "Returned ID:"); DumpUniqueRecord(*outUniqueRecord); } #endif - secdebug("dbsession", "********************"); return result; } @@ -643,10 +620,9 @@ void DatabaseSession::DataAbortQuery(CSSM_DB_HANDLE inDbHandle, CSSM_HANDLE inResultsHandle) { - secdebug("dbsession", "%p DataAbortQuery(%lx)", this, inDbHandle); + secinfo("dbsession", "%p DataAbortQuery(%lx)", this, inDbHandle); DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.dataAbortQuery(aDbContext, inResultsHandle); - secdebug("dbsession", "********************"); } void @@ -655,30 +631,28 @@ DatabaseSession::DataGetFromUniqueRecordId(CSSM_DB_HANDLE inDbHandle, CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR inoutAttributes, CssmData *inoutData) { - secdebug("dbsession", "%p DataGetFromUniqueId(%lx)", this, inDbHandle); + secinfo("dbsession", "%p DataGetFromUniqueId(%lx)", this, inDbHandle); #ifndef NDEBUG - secdebug("dbsession", "inUniqueRecord:"); + secinfo("dbsession", "inUniqueRecord:"); DumpUniqueRecord(inUniqueRecord); #endif DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.dataGetFromUniqueRecordId(aDbContext, inUniqueRecord, inoutAttributes, inoutData); - secdebug("dbsession", "********************"); } void DatabaseSession::FreeUniqueRecord(CSSM_DB_HANDLE inDbHandle, CSSM_DB_UNIQUE_RECORD &inUniqueRecordIdentifier) { - secdebug("dbsession", "FreeUniqueRecord: %lx", inDbHandle); + secinfo("dbsession", "FreeUniqueRecord: %lx", inDbHandle); #ifndef NDEBUG - secdebug("dbsession", "inUniqueRecordIdentifier follows:"); + secinfo("dbsession", "inUniqueRecordIdentifier follows:"); DumpUniqueRecord(inUniqueRecordIdentifier); #endif DbContext &aDbContext = findDbContext(inDbHandle); aDbContext.mDatabase.freeUniqueRecord(aDbContext, inUniqueRecordIdentifier); - secdebug("dbsession", "********************"); } void diff --git a/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp new file mode 100644 index 00000000..acfb0493 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.cpp @@ -0,0 +1,416 @@ +// +// TP plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#include +#include +#include +#include + + +TPAbstractPluginSession::~TPAbstractPluginSession() +{ /* virtual */ } + +static CSSM_RETURN CSSMTPI cssm_CertReclaimKey(CSSM_TP_HANDLE TPHandle, + const CSSM_CERTGROUP *CertGroup, + uint32 CertIndex, + CSSM_LONG_HANDLE KeyCacheHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry) +{ + BEGIN_API + findSession(TPHandle).CertReclaimKey(Required(CertGroup), + CertIndex, + KeyCacheHandle, + CSPHandle, + CredAndAclEntry); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertGroupToTupleGroup(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_CERTGROUP *CertGroup, + CSSM_TUPLEGROUP_PTR *TupleGroup) +{ + BEGIN_API + findSession(TPHandle).CertGroupToTupleGroup(CLHandle, + Required(CertGroup), + Required(TupleGroup)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertCreateTemplate(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CertFields, + CSSM_DATA_PTR CertTemplate) +{ + BEGIN_API + findSession(TPHandle).CertCreateTemplate(CLHandle, + NumberOfFields, + CertFields, + CssmData::required(CertTemplate)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_FormRequest(CSSM_TP_HANDLE TPHandle, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_FORM_TYPE FormType, + CSSM_DATA_PTR BlankForm) +{ + BEGIN_API + findSession(TPHandle).FormRequest(PreferredAuthority, + FormType, + CssmData::required(BlankForm)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CrlSign(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_ENCODED_CRL *CrlToBeSigned, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, + CSSM_DATA_PTR SignedCrl) +{ + BEGIN_API + findSession(TPHandle).CrlSign(CLHandle, + CCHandle, + Required(CrlToBeSigned), + Required(SignerCertGroup), + SignerVerifyContext, + SignerVerifyResult, + CssmData::required(SignedCrl)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_TupleGroupToCertGroup(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_TUPLEGROUP *TupleGroup, + CSSM_CERTGROUP_PTR *CertTemplates) +{ + BEGIN_API + findSession(TPHandle).TupleGroupToCertGroup(CLHandle, + Required(TupleGroup), + Required(CertTemplates)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertGetAllTemplateFields(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_DATA *CertTemplate, + uint32 *NumberOfFields, + CSSM_FIELD_PTR *CertFields) +{ + BEGIN_API + findSession(TPHandle).CertGetAllTemplateFields(CLHandle, + CssmData::required(CertTemplate), + Required(NumberOfFields), + Required(CertFields)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertReclaimAbort(CSSM_TP_HANDLE TPHandle, + CSSM_LONG_HANDLE KeyCacheHandle) +{ + BEGIN_API + findSession(TPHandle).CertReclaimAbort(KeyCacheHandle); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CrlCreateTemplate(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD *CrlFields, + CSSM_DATA_PTR NewCrlTemplate) +{ + BEGIN_API + findSession(TPHandle).CrlCreateTemplate(CLHandle, + NumberOfFields, + CrlFields, + CssmData::required(NewCrlTemplate)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertGroupConstruct(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DL_DB_LIST *DBList, + const void *ConstructParams, + const CSSM_CERTGROUP *CertGroupFrag, + CSSM_CERTGROUP_PTR *CertGroup) +{ + BEGIN_API + findSession(TPHandle).CertGroupConstruct(CLHandle, + CSPHandle, + Required(DBList), + ConstructParams, + Required(CertGroupFrag), + Required(CertGroup)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_PassThrough(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) +{ + BEGIN_API + findSession(TPHandle).PassThrough(CLHandle, + CCHandle, + DBList, + PassThroughId, + InputParams, + OutputParams); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_RetrieveCredResult(CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + sint32 *EstimatedTime, + CSSM_BOOL *ConfirmationRequired, + CSSM_TP_RESULT_SET_PTR *RetrieveOutput) +{ + BEGIN_API + findSession(TPHandle).RetrieveCredResult(CssmData::required(ReferenceIdentifier), + CallerAuthCredentials, + Required(EstimatedTime), + Required(ConfirmationRequired), + Required(RetrieveOutput)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertSign(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DATA *CertTemplateToBeSigned, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR SignerVerifyResult, + CSSM_DATA_PTR SignedCert) +{ + BEGIN_API + findSession(TPHandle).CertSign(CLHandle, + CCHandle, + CssmData::required(CertTemplateToBeSigned), + Required(SignerCertGroup), + SignerVerifyContext, + SignerVerifyResult, + CssmData::required(SignedCert)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_FormSubmit(CSSM_TP_HANDLE TPHandle, + CSSM_TP_FORM_TYPE FormType, + const CSSM_DATA *Form, + const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, + const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, + CSSM_ACCESS_CREDENTIALS_PTR Credentials) +{ + BEGIN_API + findSession(TPHandle).FormSubmit(FormType, + CssmData::required(Form), + ClearanceAuthority, + RepresentedAuthority, + AccessCredentials::optional(Credentials)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertGroupVerify(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_CERTGROUP *CertGroupToBeVerified, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult) +{ + BEGIN_API + findSession(TPHandle).CertGroupVerify(CLHandle, + CSPHandle, + Required(CertGroupToBeVerified), + VerifyContext, + VerifyContextResult); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_SubmitCredRequest(CSSM_TP_HANDLE TPHandle, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, + const CSSM_TP_REQUEST_SET *RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 *EstimatedTime, + CSSM_DATA_PTR ReferenceIdentifier) +{ + BEGIN_API + findSession(TPHandle).SubmitCredRequest(PreferredAuthority, + RequestType, + Required(RequestInput), + CallerAuthContext, + Required(EstimatedTime), + CssmData::required(ReferenceIdentifier)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_ReceiveConfirmation(CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + CSSM_TP_CONFIRM_RESPONSE_PTR *Responses, + sint32 *ElapsedTime) +{ + BEGIN_API + findSession(TPHandle).ReceiveConfirmation(CssmData::required(ReferenceIdentifier), + Required(Responses), + Required(ElapsedTime)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_ConfirmCredResult(CSSM_TP_HANDLE TPHandle, + const CSSM_DATA *ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + const CSSM_TP_CONFIRM_RESPONSE *Responses, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority) +{ + BEGIN_API + findSession(TPHandle).ConfirmCredResult(CssmData::required(ReferenceIdentifier), + CallerAuthCredentials, + Required(Responses), + PreferredAuthority); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CrlVerify(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL *CrlToBeVerified, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult) +{ + BEGIN_API + findSession(TPHandle).CrlVerify(CLHandle, + CSPHandle, + Required(CrlToBeVerified), + Required(SignerCertGroup), + VerifyContext, + RevokerVerifyResult); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_ApplyCrlToDb(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL *CrlToBeApplied, + const CSSM_CERTGROUP *SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR ApplyCrlVerifyResult) +{ + BEGIN_API + findSession(TPHandle).ApplyCrlToDb(CLHandle, + CSPHandle, + Required(CrlToBeApplied), + Required(SignerCertGroup), + ApplyCrlVerifyContext, + Required(ApplyCrlVerifyResult)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertGroupPrune(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + const CSSM_DL_DB_LIST *DBList, + const CSSM_CERTGROUP *OrderedCertGroup, + CSSM_CERTGROUP_PTR *PrunedCertGroup) +{ + BEGIN_API + findSession(TPHandle).CertGroupPrune(CLHandle, + Required(DBList), + Required(OrderedCertGroup), + Required(PrunedCertGroup)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertRevoke(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *OldCrlTemplate, + const CSSM_CERTGROUP *CertGroupToBeRevoked, + const CSSM_CERTGROUP *RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, + CSSM_TP_CERTCHANGE_REASON Reason, + CSSM_DATA_PTR NewCrlTemplate) +{ + BEGIN_API + findSession(TPHandle).CertRevoke(CLHandle, + CSPHandle, + CssmData::optional(OldCrlTemplate), + Required(CertGroupToBeRevoked), + Required(RevokerCertGroup), + Required(RevokerVerifyContext), + Required(RevokerVerifyResult), + Reason, + CssmData::required(NewCrlTemplate)); + END_API(TP) +} + +static CSSM_RETURN CSSMTPI cssm_CertRemoveFromCrlTemplate(CSSM_TP_HANDLE TPHandle, + CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DATA *OldCrlTemplate, + const CSSM_CERTGROUP *CertGroupToBeRemoved, + const CSSM_CERTGROUP *RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT_PTR RevokerVerifyResult, + CSSM_DATA_PTR NewCrlTemplate) +{ + BEGIN_API + findSession(TPHandle).CertRemoveFromCrlTemplate(CLHandle, + CSPHandle, + CssmData::optional(OldCrlTemplate), + Required(CertGroupToBeRemoved), + Required(RevokerCertGroup), + Required(RevokerVerifyContext), + Required(RevokerVerifyResult), + CssmData::required(NewCrlTemplate)); + END_API(TP) +} + + +static const CSSM_SPI_TP_FUNCS TPFunctionStruct = { + cssm_SubmitCredRequest, + cssm_RetrieveCredResult, + cssm_ConfirmCredResult, + cssm_ReceiveConfirmation, + cssm_CertReclaimKey, + cssm_CertReclaimAbort, + cssm_FormRequest, + cssm_FormSubmit, + cssm_CertGroupVerify, + cssm_CertCreateTemplate, + cssm_CertGetAllTemplateFields, + cssm_CertSign, + cssm_CrlVerify, + cssm_CrlCreateTemplate, + cssm_CertRevoke, + cssm_CertRemoveFromCrlTemplate, + cssm_CrlSign, + cssm_ApplyCrlToDb, + cssm_CertGroupConstruct, + cssm_CertGroupPrune, + cssm_CertGroupToTupleGroup, + cssm_TupleGroupToCertGroup, + cssm_PassThrough, +}; + +static CSSM_MODULE_FUNCS TPFunctionTable = { + CSSM_SERVICE_TP, // service type + 23, // number of functions + (const CSSM_PROC_ADDR *)&TPFunctionStruct +}; + +CSSM_MODULE_FUNCS_PTR TPPluginSession::construct() +{ + return &TPFunctionTable; +} diff --git a/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.h b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.h new file mode 100644 index 00000000..d8104d62 --- /dev/null +++ b/OSX/libsecurity_cdsa_plugin/lib/TPabstractsession.h @@ -0,0 +1,140 @@ +// +// TP plugin transition layer. +// This file was automatically generated. Do not edit on penalty of futility! +// +#ifndef _H_TPABSTRACTSESSION +#define _H_TPABSTRACTSESSION + +#include +#include +#include + + +namespace Security { + + +// +// A pure abstract class to define the TP module interface +// +class TPAbstractPluginSession { +public: + virtual ~TPAbstractPluginSession(); + virtual void FormRequest(const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_FORM_TYPE FormType, + CssmData &BlankForm) = 0; + virtual void CrlSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_ENCODED_CRL &CrlToBeSigned, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *SignerVerifyResult, + CssmData &SignedCrl) = 0; + virtual void CertCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD CertFields[], + CssmData &CertTemplate) = 0; + virtual void CertReclaimKey(const CSSM_CERTGROUP &CertGroup, + uint32 CertIndex, + CSSM_LONG_HANDLE KeyCacheHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_RESOURCE_CONTROL_CONTEXT *CredAndAclEntry) = 0; + virtual void CertGroupToTupleGroup(CSSM_CL_HANDLE CLHandle, + const CSSM_CERTGROUP &CertGroup, + CSSM_TUPLEGROUP_PTR &TupleGroup) = 0; + virtual void RetrieveCredResult(const CssmData &ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + sint32 &EstimatedTime, + CSSM_BOOL &ConfirmationRequired, + CSSM_TP_RESULT_SET_PTR &RetrieveOutput) = 0; + virtual void FormSubmit(CSSM_TP_FORM_TYPE FormType, + const CssmData &Form, + const CSSM_TP_AUTHORITY_ID *ClearanceAuthority, + const CSSM_TP_AUTHORITY_ID *RepresentedAuthority, + AccessCredentials *Credentials) = 0; + virtual void CertSign(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CssmData &CertTemplateToBeSigned, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *SignerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *SignerVerifyResult, + CssmData &SignedCert) = 0; + virtual void CrlCreateTemplate(CSSM_CL_HANDLE CLHandle, + uint32 NumberOfFields, + const CSSM_FIELD CrlFields[], + CssmData &NewCrlTemplate) = 0; + virtual void CertReclaimAbort(CSSM_LONG_HANDLE KeyCacheHandle) = 0; + virtual void PassThrough(CSSM_CL_HANDLE CLHandle, + CSSM_CC_HANDLE CCHandle, + const CSSM_DL_DB_LIST *DBList, + uint32 PassThroughId, + const void *InputParams, + void **OutputParams) = 0; + virtual void CertGroupConstruct(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_DL_DB_LIST &DBList, + const void *ConstructParams, + const CSSM_CERTGROUP &CertGroupFrag, + CSSM_CERTGROUP_PTR &CertGroup) = 0; + virtual void TupleGroupToCertGroup(CSSM_CL_HANDLE CLHandle, + const CSSM_TUPLEGROUP &TupleGroup, + CSSM_CERTGROUP_PTR &CertTemplates) = 0; + virtual void CertGetAllTemplateFields(CSSM_CL_HANDLE CLHandle, + const CssmData &CertTemplate, + uint32 &NumberOfFields, + CSSM_FIELD_PTR &CertFields) = 0; + virtual void ReceiveConfirmation(const CssmData &ReferenceIdentifier, + CSSM_TP_CONFIRM_RESPONSE_PTR &Responses, + sint32 &ElapsedTime) = 0; + virtual void ConfirmCredResult(const CssmData &ReferenceIdentifier, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, + const CSSM_TP_CONFIRM_RESPONSE &Responses, + const CSSM_TP_AUTHORITY_ID *PreferredAuthority) = 0; + virtual void SubmitCredRequest(const CSSM_TP_AUTHORITY_ID *PreferredAuthority, + CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, + const CSSM_TP_REQUEST_SET &RequestInput, + const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, + sint32 &EstimatedTime, + CssmData &ReferenceIdentifier) = 0; + virtual void CertGroupVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_CERTGROUP &CertGroupToBeVerified, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *VerifyContextResult) = 0; + virtual void CertRemoveFromCrlTemplate(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CssmData *OldCrlTemplate, + const CSSM_CERTGROUP &CertGroupToBeRemoved, + const CSSM_CERTGROUP &RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT &RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &RevokerVerifyResult, + CssmData &NewCrlTemplate) = 0; + virtual void ApplyCrlToDb(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL &CrlToBeApplied, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *ApplyCrlVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &ApplyCrlVerifyResult) = 0; + virtual void CertGroupPrune(CSSM_CL_HANDLE CLHandle, + const CSSM_DL_DB_LIST &DBList, + const CSSM_CERTGROUP &OrderedCertGroup, + CSSM_CERTGROUP_PTR &PrunedCertGroup) = 0; + virtual void CertRevoke(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CssmData *OldCrlTemplate, + const CSSM_CERTGROUP &CertGroupToBeRevoked, + const CSSM_CERTGROUP &RevokerCertGroup, + const CSSM_TP_VERIFY_CONTEXT &RevokerVerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT &RevokerVerifyResult, + CSSM_TP_CERTCHANGE_REASON Reason, + CssmData &NewCrlTemplate) = 0; + virtual void CrlVerify(CSSM_CL_HANDLE CLHandle, + CSSM_CSP_HANDLE CSPHandle, + const CSSM_ENCODED_CRL &CrlToBeVerified, + const CSSM_CERTGROUP &SignerCertGroup, + const CSSM_TP_VERIFY_CONTEXT *VerifyContext, + CSSM_TP_VERIFY_CONTEXT_RESULT *RevokerVerifyResult) = 0; +}; + +} // end namespace Security + +#endif //_H_TPABSTRACTSESSION diff --git a/OSX/libsecurity_cdsa_plugin/lib/generator.cfg b/OSX/libsecurity_cdsa_plugin/lib/generator.cfg deleted file mode 100644 index 6a585002..00000000 --- a/OSX/libsecurity_cdsa_plugin/lib/generator.cfg +++ /dev/null @@ -1,59 +0,0 @@ -# -# transition.cfg -# -# Configuration file for generating the CSSM plugin framework transition layer. -# - - -# -# Specify optional arguments -# - -# CSP -optional CSP:Login LoginName -optional CSP:GetLoginAcl SelectionTag -optional CSP:GetKeyAcl SelectionTag -optional DL:GetDbAcl SelectionTag -optional CSP:GenerateKey KeyLabel CredAndAclEntry -optional CSP:GenerateKeyPair PrivateKeyLabel PublicKeyLabel CredAndAclEntry -optional CSP:WrapKey DescriptiveData -optional CSP:UnwrapKey PublicKey KeyLabel CredAndAclEntry -optional CSP:DeriveKey KeyLabel CredAndAclEntry -optional CSP:FreeKey AccessCred -optional CSP:QuerySize DataBlock -optional CSP:QueryKeySizeInBits Context Key - -# CL/TP -optional TP:SubmitCredRequest PreferredAuthority CallerAuthContext -optional TP:RetrieveCredResult CallerAuthCredentials -optional TP:ConfirmCredResult CallerAuthCredentials PreferredAuthority -optional TP:CertReclaimKey CredAndAclEntry -optional TP:FormRequest PreferredAuthority -optional TP:FormSubmit ClearanceAuthority RepresentedAuthority Credentials -optional TP:CertGroupVerify VerifyContext VerifyContextResult -optional TP:CertSign SignerVerifyContext SignerVerifyResult -optional TP:CrlVerify VerifyContext RevokerVerifyResult -optional TP:CertRevoke OldCrlTemplate -optional TP:CertRemoveFromCrlTemplate OldCrlTemplate -optional TP:CrlSign SignerVerifyContext SignerVerifyResult -optional TP:ApplyCrlToDb ApplyCrlVerifyContext -optional TP:PassThrough DBList -optional AC:AuthCompute Credentials RequestedAuthorizationPeriod -optional CL:CertSign SignScope -optional CL:CertVerify SignerCert VerifyScope -optional CL:CertGroupToSignedBundle SignerCert BundleInfo -optional CL:CertGroupFromVerifiedBundle SignerCert -optional CL:CrlSign SignScope -optional CL:CrlVerify SignerCert VerifyScope -optional CL:CrlGetFirstCachedFieldValue CrlRecordIndex - -# DL -optional DL:DbOpen DbLocation AccessCred -optional DL:DbCreate DbLocation CredAndAclEntry -optional DL:DbDelete DbLocation AccessCred -optional DL:DataInsert Attributes Data -optional DL:DataModify AttributesToBeModified DataToBeModified -optional DL:DataGetFirst Query Attributes Data -optional DL:DataGetNext Query Attributes Data -optional DL:DataGetFromUniqueRecordId Attributes Data -optional DL:CreateRelation pAttributeInfo diff --git a/OSX/libsecurity_cdsa_plugin/lib/generator.mk b/OSX/libsecurity_cdsa_plugin/lib/generator.mk deleted file mode 100644 index 0451e8c4..00000000 --- a/OSX/libsecurity_cdsa_plugin/lib/generator.mk +++ /dev/null @@ -1,29 +0,0 @@ -# Makefile for generated files. - -SOURCES = $(BUILT_PRODUCTS_DIR)/derived_src/security_cdsa_plugin -HEADERS = $(SOURCES) - -HFILES = $(HEADERS)/ACabstractsession.h -CPPFILES = $(SOURCES)/ACabstractsession.cpp - -build: $(HFILES) $(CPPFILES) - -install: build - -installhdrs: $(HFILES) - -installsrc: - -clean: - rm -f $(SPIGLUE_GEN) - -debug: build - -profile: build - -.PHONY: build clean debug profile - -# partial dependencies only -$(HFILES) $(CPPFILES) : $(PROJECT_DIR)/lib/generator.pl $(PROJECT_DIR)/lib/generator.cfg - mkdir -p $(SOURCES) - perl $(PROJECT_DIR)/lib/generator.pl $(CSSM_HEADERS) $(PROJECT_DIR)/lib/generator.cfg $(HEADERS) $(SOURCES) diff --git a/OSX/libsecurity_cdsa_plugin/lib/generator.pl b/OSX/libsecurity_cdsa_plugin/lib/generator.pl deleted file mode 100644 index 585186b0..00000000 --- a/OSX/libsecurity_cdsa_plugin/lib/generator.pl +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/perl -# -# generator.pl - auto-generate code for the CSSM plugin interfaces -# -# Usage: -# perl generator.pl input-directory h-output-dir c-output-dir -# -# Perry The Cynic, Fall 1999. -# -@API_H=("cssmapi.h"); -%SPI_H=("AC" => "cssmaci.h", "CSP" => "cssmcspi.h", "DL" => "cssmdli.h", - "CL" => "cssmcli.h", "TP" => "cssmtpi.h"); - -$SOURCEPATH=$ARGV[0]; # where all the input files are -$APICFG=$ARGV[1]; # configuration file -$HTARGETDIR=$ARGV[2]; # where the generated headers go -$CTARGETDIR=$ARGV[3]; # where the generated sources go - - -$tabs = "\t\t\t"; # argument indentation (noncritical) -$warning = "This file was automatically generated. Do not edit on penalty of futility!"; - - -# -# Open and read the configuration file -# -$/=undef; # gulp file -open(APICFG, $APICFG) or die "Cannot open $APICFG: $^E"; -$_=; -close(APICFG); -%optionals = /^\s*optional\s+(\w+:\w+)\s+(.*)$/gm; - - -# -# Pre-arranged arrays for processing below -# -%noDataReturnError = ( CL => "CSSMERR_CL_NO_FIELD_VALUES", - DL => "CSSMERR_DL_ENDOFDATA" ); - - -# -# process one SPI at a time -# -while (($type, $header) = each %SPI_H) { - my(%functions, %methods, %actuals); - ($typelower = $type) =~ tr/A-Z/a-z/; # lowercase version of type - - # start in on the $type header file - for my $sourcedir (split (/:/, $SOURCEPATH)) { - open(SPI, "$sourcedir/$header") and last; - } - SPI or die "cannot find $header in $SOURCEPATH: $^E"; - $/=undef; # big gulp mode - $_ = ; # aaaaah... - close(SPI); # done - # throw away leading and trailing crud (only interested in SPI structure) - s/^.*struct cssm_spi.*{(.*)} CSSM_SPI.*$/$1/s - or die "bad format in $SPI_H{$name}"; - - # break up into functions (you'd do that HOW in YOUR language? :-) - @functions = /CSSM_RETURN \(CSSM${type}I \*([A-Za-z_]+)\)\s+\(([^)]+)\);/g; - %functions = @functions; - - $MOREHEADERS=""; - $MOREHEADERS .= "#include \n" if /CSSM_CONTEXT/; - $MOREHEADERS .= "#include \n" if /CSSM_(ACL|ACCESS)/; - $MOREHEADERS .= "#include \n" if /CSSM_QUERY/; - - # break function arguments into many forms: - # functions => formal SPI arguments - # methods => formal C++ method arguments - # actuals => actual expression forms for transition layer use - # and (by the way) massage them into a more palatable form... - $nFunctions = 0; - while (($function, $_) = each %functions) { - # - # Turn CSSM SPI formal into method formal - # - $returntype{$function} = "void"; - $prefix{$function} = ""; - $postfix{$function} = ";"; - # reshape initial argument (the module handle, more or less) - s/^CSSM_${type}_HANDLE ${type}Handle(,\s*\n\s*|$)//s; # remove own handle (-> this) - s/^CSSM_DL_DB_HANDLE DLDBHandle/CSSM_DB_HANDLE DBHandle/s; # DL_DB handle -> DB handle - s/CSSM_HANDLE_PTR ResultsHandle(,?)\n//m # turn ptr-to-resultshandle into fn result - and do { - $returntype{$function} = "CSSM_HANDLE"; - $prefix{$function} = "if ((Required(ResultsHandle) = "; - $postfix{$function} = ") == CSSM_INVALID_HANDLE)\n return $noDataReturnError{$type};"; - }; - if ($function =~ /GetNext/) { # *GetNext* returns a bool - $returntype{$function} = "bool"; - $prefix{$function} = "if (!"; - $postfix{$function} = ")\n return $noDataReturnError{$type};"; - } - # reshape subsequent arguments - s/([su]int32) \*(\w+,?)/$1 \&$2/gm; # int * -> int & (output integer) - s/(CSSM_\w+_PTR) \*(\w+,?)/$1 \&$2/gm; # _PTR * -> _PTR & - s/(CSSM_\w+)_PTR (\w+)/$1 \*$2/gm; # XYZ_PTR -> XYZ * (explicit) - s/(const )?CSSM_DATA \*(\w+)Bufs/$1CssmData $2Bufs\[\]/gm; # c DATA *Bufs (plural) - s/(const )?CSSM_(DATA|OID) \*/$1CssmData \&/gm; # c DATA * -> c Data & - s/(const )?CSSM_FIELD \*(\w+)Fields/$1CSSM_FIELD $2Fields\[\]/gm; # c FIELD *Fields (plural) - s/(const )?CSSM_FIELD \*CrlTemplate/$1CSSM_FIELD CrlTemplate\[\]/gm; # c FIELD *CrlTemplate - s/const CSSM_CONTEXT \*/const Context \&/gm; # c CSSM_CONTEXT * -> c Context & - s/(const )?CSSM_ACCESS_CREDENTIALS \*/$1AccessCredentials \&/gm; # ditto - s/(const )?CSSM_QUERY_SIZE_DATA \*/$1QuerySizeData \&/gm; # ditto - s/(const )?CSSM_CSP_OPERATIONAL_STATISTICS \*/$1CSPOperationalStatistics \&/gm; # ditto - s/(const )?CSSM_(WRAP_)?KEY \*/$1CssmKey \&/gm; # CSSM[WRAP]KEY * -> CssmKey & - s/const CSSM_QUERY \*/const CssmQuery \&/gm; # c QUERY * -> c Query & - s/(const )?(CSSM_[A-Z_]+) \*/$1$2 \&/gm; # c CSSM_ANY * -> c CSSM_ANY & - $methods{$function} = $_; - - # - # Now turn the method formal into the transition invocation actuals - # - s/^CSSM_DB_HANDLE \w+(,?)/DLDBHandle.DBHandle$1/s; # matching change to DL_DB handles - s/(const )?([A-Z][a-z]\w+) &(\w+)(,?)/$2::required($3)$4/gm; # BIG_ * -> Small_ & - s/(const )?CssmData (\w+)Bufs\[\](,?)/\&\&CssmData::required($2Bufs)$3/gm; # c DATA *DataBufs - s/(const )?CSSM_FIELD (\w+)Fields\[\](,?)/$2Fields$3/gm; # c CSSM_FIELD *Fields - s/(const )?CSSM_FIELD CrlTemplate\[\](,?)/CrlTemplate$2/gm; # c CSSM_FIELD *CrlTemplate - # now remove formal arguments and clean up - s/^.* \&\&(\w+,?)/$tabs\&$1/gm; # && escape (to keep real &) - s/^.* \&(\w+)(,?)/${tabs}Required($1)$2/gm; # dereference for ref transition - s/^.* \**(\w+,?)/$tabs$1/gm; # otherwise, plain actual argument - s/^$tabs//; - $actuals{$function} = $_; - - # - # Fix optional arguments - # - foreach $opt (split " ", $optionals{"$type:$function"}) { - $methods{$function} =~ s/\&$opt\b/\*$opt/; # turn refs back into pointers - $actuals{$function} =~ s/::required\($opt\)/::optional($opt)/; # optional specific - $actuals{$function} =~ s/Required\($opt\)/$opt/; # optional generic - }; - $nFunctions++; - }; - - # - # Prepare to write header and source files - # - open(H, ">$HTARGETDIR/${type}abstractsession.h") or die "cannot write ${type}abstractsession.h: $^E"; - open(C, ">$CTARGETDIR/${type}abstractsession.cpp") or die "cannot write ${type}abstractsession.cpp: $^E"; - - # - # Create header file - # - print H < -#include -$MOREHEADERS - -namespace Security { - - -// -// A pure abstract class to define the ${type} module interface -// -class ${type}AbstractPluginSession { -public: - virtual ~${type}AbstractPluginSession(); -HDRHEAD - - $functionCount = 0; - while (($function, $arglist) = each %methods) { - # generate method declaration - print H " virtual $returntype{$function} $function($arglist) = 0;\n"; - $functionCount++; - }; - print H < -#include -#include -#include - - -${type}AbstractPluginSession::~${type}AbstractPluginSession() -{ /* virtual */ } - -BODY - - # write transition layer functions - while (($function, $arglist) = each %functions) { - $lookupHandle = "${type}Handle"; - $lookupHandle = "DLDBHandle.DLHandle" if $arglist =~ /DL_DB_HANDLE/; - print C <($lookupHandle).$function($actuals{$function})${postfix{$function}} - END_API($type) -} - -SHIM - }; - - # generate dispatch table - in the right order, please - print C "\nstatic const CSSM_SPI_${type}_FUNCS ${type}FunctionStruct = {\n"; - while ($function = shift @functions) { - print C " cssm_$function,\n"; - shift @functions; # skip over arglist part - }; - print C "};\n\n"; - - print C <fillInAuthorizationValue(valueVector.values[i]); - } - - DataWalkers::Copier flatValueVector(&valueVector); - *length = flatValueVector.length(); - *data = flatValueVector.keep(); - - delete[] valueVector.values; -} - AuthItem::AuthItem(const AuthorizationItem &item) : mFlags(item.flags), mOwnsName(true), @@ -206,36 +187,14 @@ AuthItem::operator = (const AuthItem &other) return *this; } -void -AuthItem::fillInAuthorizationItem(AuthorizationItem &item) -{ - item.name = mName; - item.valueLength = mValue.length; - item.value = mValue.data; - item.flags = mFlags; -} - -bool -AuthItem::getBool(bool &value) -{ - if (mValue.length == sizeof(bool)) - { - bool *tmpValue = (bool *)mValue.data; - - if (tmpValue) - { - value = *tmpValue; - return true; - } - } - - return false; -} - bool AuthItem::getString(string &value) { - value = string(static_cast(mValue.data), mValue.length); + // if terminating NUL is included, ignore it + size_t len = mValue.length; + if (len > 0 && (static_cast(mValue.data)[len - 1] == 0)) + --len; + value = string(static_cast(mValue.data), len); return true; } @@ -258,14 +217,11 @@ AuthItemRef::AuthItemRef(AuthorizationString name, AuthorizationValue value, Aut // AuthItemSet // AuthItemSet::AuthItemSet() -: firstItemName(NULL) { } AuthItemSet::~AuthItemSet() { - if (NULL != firstItemName) - free(firstItemName); } AuthItemSet & @@ -284,21 +240,13 @@ AuthItemSet::operator=(const AuthItemSet& itemSet) { std::set::operator=(itemSet); - if (this != &itemSet) { - duplicate(itemSet); - } - return *this; } AuthItemSet::AuthItemSet(const AuthorizationItemSet *itemSet) -: firstItemName(NULL) { if (NULL != itemSet && NULL != itemSet->items) { - if (0 < itemSet->count && NULL != itemSet->items[0].name) - firstItemName = strdup(itemSet->items[0].name); - for (unsigned int i=0; i < itemSet->count; i++) insert(AuthItemRef(itemSet->items[i])); } @@ -307,46 +255,6 @@ AuthItemSet::AuthItemSet(const AuthorizationItemSet *itemSet) AuthItemSet::AuthItemSet(const AuthItemSet& itemSet) : std::set(itemSet) { - duplicate(itemSet); -} - -void -AuthItemSet::duplicate(const AuthItemSet& itemSet) -{ - if (itemSet.firstItemName != NULL) - firstItemName = strdup(itemSet.firstItemName); - else - firstItemName = NULL; -} - -void -AuthItemSet::copy(AuthorizationItemSet *&data, size_t &length, Allocator &alloc) const -{ - AuthorizationItemSet itemSet; - itemSet.count = (UInt32)size(); - itemSet.items = new AuthorizationItem[itemSet.count]; - int i = 0; - for (const_iterator it = begin(); it != end(); ++it, ++i) - { - (*it)->fillInAuthorizationItem(itemSet.items[i]); - } - - DataWalkers::Copier flatItemSet(&itemSet, alloc); - length = flatItemSet.length(); - - data = flatItemSet.keep(); - // else flatItemSet disappears again - - delete[] itemSet.items; -} - -AuthorizationItemSet * -AuthItemSet::copy() const -{ - AuthorizationItemSet *aCopy; - size_t aLength; - copy(aCopy, aLength); - return aCopy; } AuthItem * diff --git a/OSX/libsecurity_cdsa_utilities/lib/AuthorizationData.h b/OSX/libsecurity_cdsa_utilities/lib/AuthorizationData.h index 3b2c24fa..8dbdc8d0 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/AuthorizationData.h +++ b/OSX/libsecurity_cdsa_utilities/lib/AuthorizationData.h @@ -95,8 +95,6 @@ public: ~AuthValueVector() {} AuthValueVector &operator = (const AuthorizationValueVector& valueVector); - - void copy(AuthorizationValueVector **data, size_t *length) const; }; @@ -120,8 +118,6 @@ public: AuthItem &operator = (const AuthItem &other); ~AuthItem(); - void fillInAuthorizationItem(AuthorizationItem &item); - AuthorizationString name() const { return mName; } const AuthorizationValue& value() const { return mValue; } string stringValue() const { return string(static_cast(mValue.data), mValue.length); } @@ -136,7 +132,6 @@ private: mutable bool mOwnsValue; public: - bool getBool(bool &value); bool getString(string &value); bool getCssmData(CssmAutoData &value); }; @@ -166,16 +161,8 @@ public: AuthItemSet &operator = (const AuthorizationItemSet& itemSet); AuthItemSet &operator = (const AuthItemSet& itemSet); - void copy(AuthorizationItemSet *&data, size_t &length, Allocator &alloc = Allocator::standard()) const; - AuthorizationItemSet *copy() const; - - char *firstItemName; - public: AuthItem *find(const char *name); - -private: - void duplicate(const AuthItemSet& itemSet); }; class FindAuthItemByRightName @@ -191,7 +178,7 @@ public: { return (!strcmp(name, authitem->name)); } - + private: const char *name; }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 b/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 index f3b84278..1d4f9e12 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 +++ b/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 @@ -291,7 +291,7 @@ newAttribute(` Ss', Alias, kSecAlias, (char*) "Alias", 0, NULL, BLOB) newAttribute(`UISs', Issuer, kSecIssuerItemAttr, (char*) "Issuer", 0, NULL, BLOB) newAttribute(`UISs', ThisUpdate, kSecThisUpdateItemAttr, (char*) "ThisUpdate", 0, NULL, BLOB) newAttribute(`UISs', NextUpdate, kSecNextUpdateItemAttr, (char*) "NextUpdate", 0, NULL, BLOB) -newAttribute(` Ss', URI, kSecUriItemAttr, (char*) "URI", 0, NULL, BLOB) +newAttribute(`UISs', URI, kSecUriItemAttr, (char*) "URI", 0, NULL, BLOB) newAttribute(` ISs', CrlNumber, kSecCrlNumberItemAttr, (char*) "CrlNumber", 0, NULL, UINT32) newAttribute(` ISs', DeltaCrlNumber, kSecDeltaCrlNumberItemAttr, (char*) "DeltaCrlNumber", 0, NULL, UINT32) endNewClass() diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp index 5c0cc03f..340bbd2b 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp @@ -91,11 +91,11 @@ CodeSignatureAclSubject *CodeSignatureAclSubject::Maker::make(const TypedList &l if (list[n].is(CSSM_LIST_ELEMENT_DATUM)) { const BlobCore *blob = list[n].data().interpretedAs(); if (blob->length() < sizeof(BlobCore)) { - secdebug("csblob", "runt blob (0x%x/%zd) slot %d in CSSM_LIST", + secinfo("csblob", "runt blob (0x%x/%zd) slot %d in CSSM_LIST", blob->magic(), blob->length(), n); CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); } else if (blob->length() != list[n].data().length()) { - secdebug("csblob", "badly sized blob (0x%x/%zd) slot %d in CSSM_LIST", + secinfo("csblob", "badly sized blob (0x%x/%zd) slot %d in CSSM_LIST", blob->magic(), blob->length(), n); CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); } @@ -133,7 +133,7 @@ CodeSignatureAclSubject *CodeSignatureAclSubject::Maker::make(const SHA1::Byte * blob = increment(blob, alignUp(blob->length(), commentBagAlignment))) { size_t leftInBag = difference(commentBag.end(), blob); if (leftInBag < sizeof(BlobCore) || blob->length() < sizeof(BlobCore) || blob->length() > leftInBag) { - secdebug("csblob", "invalid blob (0x%x/%zd) [%zd in bag] in code signing ACL for %s - stopping scan", + secinfo("csblob", "invalid blob (0x%x/%zd) [%zd in bag] in code signing ACL for %s - stopping scan", blob->magic(), blob->length(), leftInBag, subj->path().c_str()); break; // can't trust anything beyond this blob } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp index cd4a5f81..35d806ad 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp @@ -170,13 +170,13 @@ bool SourceAclSubject::SourceAclSubject::validates(const AclValidationContext &b if (!CSSM_ACL_AUTHORIZATION_IS_PREAUTH(auth)) // all muddled up; bail CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); uint32 slot = CSSM_ACL_AUTHORIZATION_PREAUTH_SLOT(auth); - secdebug("preauth", "using state %d@%p", slot, &env->store(this)); + secinfo("preauth", "using state %d@%p", slot, &env->store(this)); bool &accepted = env->store(this).attachment((void *)((size_t) slot)).accepted; if (!accepted) { - secdebug("preauth", "%p needs to authenticate its subject", this); + secinfo("preauth", "%p needs to authenticate its subject", this); SourceValidationContext ctx(baseCtx); if (mSourceSubject->validates(ctx)) { - secdebug("preauth", "%p pre-authenticated", this); + secinfo("preauth", "%p pre-authenticated", this); accepted = true; } } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp index df678e2a..db73d9b7 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp @@ -67,9 +67,9 @@ void SecretAclSubject::secret(const CssmData &s) const if (mCacheSecret) { mSecret = s; mSecretValid = true; - secdebug("aclsecret", "%p secret stored", this); + secinfo("aclsecret", "%p secret stored", this); } else - secdebug("aclsecret", "%p refused to store secret", this); + secinfo("aclsecret", "%p refused to store secret", this); } void SecretAclSubject::secret(CssmManagedData &s) const @@ -78,9 +78,9 @@ void SecretAclSubject::secret(CssmManagedData &s) const if (mCacheSecret) { mSecret = s; mSecretValid = true; - secdebug("aclsecret", "%p secret stored", this); + secinfo("aclsecret", "%p secret stored", this); } else - secdebug("aclsecret", "%p refused to store secret", this); + secinfo("aclsecret", "%p refused to store secret", this); } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp index 835a56be..7cccfa6d 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp @@ -156,7 +156,7 @@ void ThresholdAclSubject::exportBlob(Writer &pub, Writer &priv) void ThresholdAclSubject::add(AclSubject *subject, unsigned beforePosition) { - secdebug("threshacl", "adding subject %p before position %u", + secinfo("threshacl", "adding subject %p before position %u", subject, beforePosition); elements.insert(elements.begin() + beforePosition, subject); totalSubjects++; diff --git a/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h b/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h index d7603184..77374ba3 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h +++ b/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/OSX/libsecurity_cdsa_utilities/lib/context.h b/OSX/libsecurity_cdsa_utilities/lib/context.h index f5eb57d7..d5e9532d 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/context.h +++ b/OSX/libsecurity_cdsa_utilities/lib/context.h @@ -244,7 +244,7 @@ void walk(Action &operate, CSSM_CONTEXT_ATTRIBUTE &attr) case CSSM_ATTRIBUTE_DATA_UINT32: break; default: - secdebug("walkers", "invalid attribute (%ux) in context", (unsigned)attr.AttributeType); + secinfo("walkers", "invalid attribute (%ux) in context", (unsigned)attr.AttributeType); break; } } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp index 44a31a05..5f877bbc 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp @@ -92,7 +92,7 @@ bool AccessCredentials::authorizesUI() const { TypedList &sample = *it; if(!sample.isProper()) { - secdebugfunc("integrity", "found a non-proper sample, skipping..."); + secnotice("integrity", "found a non-proper sample, skipping..."); continue; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdbname.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmdbname.cpp index 48706c99..b72c0d4f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdbname.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdbname.cpp @@ -134,6 +134,7 @@ DbName & DbName::operator =(const DbName &other) { mDbName = other.mDbName; + mCanonicalName = other.mCanonicalName; mDbNameValid = other.mDbNameValid; if (other.mDbLocation) { diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp index 0d0f7c29..301ced86 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmerrors.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace Security { @@ -36,12 +37,16 @@ namespace Security { CssmError::CssmError(CSSM_RETURN err) : error(err) { SECURITY_EXCEPTION_THROW_CSSM(this, err); + + snprintf(whatBuffer, whatBufferSize, "CSSM Exception: %d %s", err, cssmErrorString(err)); + secnotice("security_exception", "%s", what()); + LogBacktrace(); } const char *CssmError::what() const throw () { - return "CSSM exception"; + return whatBuffer; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h index 6506b0df..40f77b76 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmlist.h @@ -29,6 +29,7 @@ #define _H_CSSMLIST #include +#include #include #include @@ -207,7 +208,7 @@ ListElement *walk(Action &operate, ListElement * &elem) case CSSM_LIST_ELEMENT_WORDID: break; default: - secdebug("walkers", "invalid list element type (%ux)", (unsigned)elem->type()); + secinfo("walkers", "invalid list element type (%ux)", (unsigned)elem->type()); break; } if (elem->next()) diff --git a/OSX/libsecurity_cdsa_utilities/lib/db++.cpp b/OSX/libsecurity_cdsa_utilities/lib/db++.cpp index 94874b5a..8f48c05e 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/db++.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/db++.cpp @@ -57,7 +57,7 @@ void UnixDb::open(const char *path, int flags, int mode, DBTYPE type) close(); mDb = newDb; setFd(mDb->fd(mDb)); - secdebug("unixdb", "open(%s,0x%x,0x%x,type=%d)=%p", path, flags, mode, type, mDb); + secnotice("unixdb", "open(%s,0x%x,0x%x,type=%d)=%p", path, flags, mode, type, mDb); } else UnixError::throwMe(); } @@ -70,7 +70,7 @@ void UnixDb::open(const std::string &path, int flags, int mode, DBTYPE type) void UnixDb::close() { if (mDb) { - secdebug("unixdb", "close(%p)", mDb); + secnotice("unixdb", "close(%p)", mDb); mDb->close(mDb); mDb = NULL; setFd(invalidFd); @@ -82,7 +82,7 @@ bool UnixDb::get(const CssmData &key, CssmData &value, int flags) const Data dKey(key); Data val; int rc = mDb->get(mDb, &dKey, &val, flags); - secdebug("unixdb", "get(%p,[:%ld],flags=0x%x)=%d[:%ld]", + secnotice("unixdb", "get(%p,[:%ld],flags=0x%x)=%d[:%ld]", mDb, key.length(), flags, rc, value.length()); checkError(rc); if (!rc) { @@ -107,7 +107,7 @@ bool UnixDb::put(const CssmData &key, const CssmData &value, int flags) Data dKey(key); Data dValue(value); int rc = mDb->put(mDb, &dKey, &dValue, flags); - secdebug("unixdb", "put(%p,[:%ld],[:%ld],flags=0x%x)=%d", + secnotice("unixdb", "put(%p,[:%ld],[:%ld],flags=0x%x)=%d", mDb, key.length(), value.length(), flags, rc); checkError(rc); return !rc; @@ -116,7 +116,7 @@ bool UnixDb::put(const CssmData &key, const CssmData &value, int flags) void UnixDb::erase(const CssmData &key, int flags) { Data dKey(key); - secdebug("unixdb", "delete(%p,[:%ld],flags=0x%x)", mDb, key.length(), flags); + secnotice("unixdb", "delete(%p,[:%ld],flags=0x%x)", mDb, key.length(), flags); checkError(mDb->del(mDb, &dKey, flags)); } diff --git a/OSX/libsecurity_cdsa_utilities/lib/handletemplates_defs.h b/OSX/libsecurity_cdsa_utilities/lib/handletemplates_defs.h index 1d365838..c815840f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/handletemplates_defs.h +++ b/OSX/libsecurity_cdsa_utilities/lib/handletemplates_defs.h @@ -78,7 +78,7 @@ void MappingHandle<_Handle>::make() _Handle handle = hbase ^ state().nextSeq(); if (!state().handleInUse(handle)) { // assumes sizeof(unsigned long) >= sizeof(handle) - secdebug("handleobj", "create %#lx for %p", static_cast(handle), this); + secinfo("handleobj", "create %#lx for %p", static_cast(handle), this); TypedHandle<_Handle>::setHandle(handle); state().add(handle, this); return; diff --git a/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp b/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp index 90f8d484..91cecb6d 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp @@ -116,7 +116,7 @@ bool ObjectAcl::validates(AclValidationContext &ctx) pair range; if (getRange(ctx.s_credTag(), range) == 0) { // no such tag - secdebugfunc("SecAccess", "no tag for cred tag: \"%s\"", ctx.s_credTag().c_str()); + secinfo("SecAccess", "no tag for cred tag: \"%s\"", ctx.s_credTag().c_str()); CssmError::throwMe(CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND); } // try each entry in turn @@ -249,14 +249,14 @@ unsigned int ObjectAcl::getRange(const std::string &tag, pair &range, bool tolerant /* = false */) const { if (!tag.empty()) { // tag restriction in effect - secdebugfunc("SecAccess", "looking for ACL entries matching tag: \"%s\"", tag.c_str()); + secinfo("SecAccess", "looking for ACL entries matching tag: \"%s\"", tag.c_str()); range = mEntries.equal_range(tag); unsigned int count = (unsigned int)mEntries.count(tag); if (count == 0 && !tolerant) CssmError::throwMe(CSSM_ERRCODE_ACL_ENTRY_TAG_NOT_FOUND); return count; } else { // try all tags - secdebugfunc("SecAccess", "no tag given; looking for all ACL entries"); + secinfo("SecAccess", "no tag given; looking for all ACL entries"); range.first = mEntries.begin(); range.second = mEntries.end(); return (unsigned int)mEntries.size(); @@ -283,12 +283,12 @@ void ObjectAcl::cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls) acls = allocator.alloc(count); uint32 n = 0; - secdebugfunc("SecAccess", "getting the ACL for %p (%d entries) tag: %s", this, count, tag ? tag : ""); + secinfo("SecAccess", "getting the ACL for %p (%d entries) tag: %s", this, count, tag ? tag : ""); for (EntryMap::const_iterator it = range.first; it != range.second; it++, n++) { acls[n].EntryHandle = it->second.handle; it->second.toEntryInfo(acls[n].EntryPublicInfo, allocator); - secdebugfunc("SecAccess", "found an entry of type %d", acls[n].EntryPublicInfo.TypedSubject.Head->WordID); + secinfo("SecAccess", "found an entry of type %d", acls[n].EntryPublicInfo.TypedSubject.Head->WordID); } count = n; } @@ -307,45 +307,47 @@ void ObjectAcl::cssmChangeAcl(const AclEdit &edit, // what is Thy wish, effendi? switch (edit.EditMode) { case CSSM_ACL_EDIT_MODE_ADD: { - secdebugfunc("SecAccess", "adding ACL for %p (%d) while preserving: %s", this, edit.handle(), preserveTag); + secinfo("SecAccess", "adding ACL for %p (%ld) while preserving: %s", this, edit.handle(), preserveTag); const AclEntryInput &input = Required(edit.newEntry()); if (preserveTag && input.proto().s_tag() == preserveTag) MacOSError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); add(input.proto().s_tag(), input.proto()); - secdebugfunc("SecAccess", "subject type is %d", input.proto().TypedSubject.Head->WordID); + secinfo("SecAccess", "subject type is %d", input.proto().TypedSubject.Head->WordID); } break; case CSSM_ACL_EDIT_MODE_REPLACE: { - secdebugfunc("SecAccess", "replacing ACL for %p (%d to %d) while preserving: %s", this, edit.handle(), edit.newEntry(), preserveTag); + secinfo("SecAccess", "replacing ACL for %p (%ld to %p) while preserving: %s", this, edit.handle(), edit.newEntry(), preserveTag); // keep the handle, and try for some modicum of atomicity EntryMap::iterator it = findEntryHandle(edit.handle()); if (preserveTag && it->second.tag == preserveTag) MacOSError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); AclEntryPrototype proto2; it->second.toEntryInfo(proto2, allocator); - secdebugfunc("SecAccess", "subject type was %d", proto2.TypedSubject.Head->WordID); + secinfo("SecAccess", "subject type was %d", proto2.TypedSubject.Head->WordID); + DataWalkers::chunkFree(proto2, allocator); AclEntryPrototype proto = Required(edit.newEntry()).proto(); // (bypassing callbacks) add(proto.s_tag(), proto, edit.handle()); - secdebugfunc("SecAccess", "new subject type is %d", proto.TypedSubject.Head->WordID); + secinfo("SecAccess", "new subject type is %d", proto.TypedSubject.Head->WordID); mEntries.erase(it); } break; case CSSM_ACL_EDIT_MODE_DELETE: { - secdebugfunc("SecAccess", "deleting ACL for %p (%d) while preserving: %s", this, edit.handle(), preserveTag); + secinfo("SecAccess", "deleting ACL for %p (%ld) while preserving: %s", this, edit.handle(), preserveTag); EntryMap::iterator it = findEntryHandle(edit.handle()); if (preserveTag && it->second.tag == preserveTag) MacOSError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); AclEntryPrototype proto; it->second.toEntryInfo(proto, allocator); - secdebugfunc("SecAccess", "subject type was %d", proto.TypedSubject.Head->WordID); + secinfo("SecAccess", "subject type was %d", proto.TypedSubject.Head->WordID); + DataWalkers::chunkFree(proto, allocator); mEntries.erase(it); break; } default: - secdebugfunc("SecAccess", "no idea what this CSSM_ACL_EDIT type is: %d", edit.EditMode); + secinfo("SecAccess", "no idea what this CSSM_ACL_EDIT type is: %d", edit.EditMode); CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_EDIT_MODE); } @@ -361,7 +363,7 @@ void ObjectAcl::cssmGetOwner(AclOwnerPrototype &outOwner) outOwner.TypedSubject = mOwner.subject->toList(allocator); outOwner.Delegate = mOwner.delegate; - secdebugfunc("SecAccess", "%p: getting the owner ACL: type %d", this, outOwner.TypedSubject.Head->WordID); + secinfo("SecAccess", "%p: getting the owner ACL: type %d", this, outOwner.TypedSubject.Head->WordID); } void ObjectAcl::cssmChangeOwner(const AclOwnerPrototype &newOwner, @@ -377,7 +379,7 @@ void ObjectAcl::cssmChangeOwner(const AclOwnerPrototype &newOwner, // okay, replace it mOwner = newOwner; - secdebugfunc("SecAccess", "%p: new owner's type is %d", this, newOwner.subject().Head->WordID); + secinfo("SecAccess", "%p: new owner's type is %d", this, newOwner.subject().Head->WordID); changedAcl(); @@ -420,7 +422,7 @@ void ObjectAcl::clear() { mOwner = OwnerEntry(); mEntries.erase(mEntries.begin(), mEntries.end()); - secdebug("acl", "%p cleared", this); + secinfo("acl", "%p cleared", this); } diff --git a/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp b/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp index 3bf4520b..6075df06 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/osxverifier.cpp @@ -43,17 +43,17 @@ namespace Security { OSXVerifier::OSXVerifier(OSXCode *code) { mPath = code->canonicalPath(); - secdebug("codesign", "building verifier for %s", mPath.c_str()); + secinfo("codesign", "building verifier for %s", mPath.c_str()); // build new-style verifier CFRef staticCode = code->codeRef(); switch (OSStatus rc = SecCodeCopyDesignatedRequirement(staticCode, kSecCSDefaultFlags, &mRequirement.aref())) { case errSecSuccess: - secdebug("codesign", " is signed; canonical requirement loaded"); + secinfo("codesign", " is signed; canonical requirement loaded"); break; case errSecCSUnsigned: - secdebug("codesign", " is unsigned; no requirement"); + secinfo("codesign", " is unsigned; no requirement"); break; default: MacOSError::throwMe(rc); @@ -61,7 +61,7 @@ OSXVerifier::OSXVerifier(OSXCode *code) // build old-style verifier makeLegacyHash(code, mLegacyHash); - secdebug("codesign", " hash generated"); + secinfo("codesign", " hash generated"); } @@ -72,7 +72,7 @@ OSXVerifier::OSXVerifier(OSXCode *code) OSXVerifier::OSXVerifier(const SHA1::Byte *hash, const std::string &path) : mPath(path) { - secdebug("codesign", "building verifier from hash %p and path=%s", hash, path.c_str()); + secinfo("codesign", "building verifier from hash %p and path=%s", hash, path.c_str()); if (hash) memcpy(mLegacyHash, hash, sizeof(mLegacyHash)); else @@ -82,7 +82,7 @@ OSXVerifier::OSXVerifier(const SHA1::Byte *hash, const std::string &path) OSXVerifier::~OSXVerifier() { - secdebug("codesign", "%p verifier destroyed", this); + secinfo("codesign", "%p verifier destroyed", this); } @@ -94,15 +94,15 @@ void OSXVerifier::add(const BlobCore *blob) { if (blob->is()) { #if defined(NDEBUG) - secdebug("codesign", "%p verifier adds requirement", this); + secinfo("codesign", "%p verifier adds requirement", this); #else - secdebug("codesign", "%p verifier adds requirement %s", this, + secinfo("codesign", "%p verifier adds requirement %s", this, Dumper::dump(Requirement::specific(blob), true).c_str()); #endif //NDEBUG MacOSError::check(SecRequirementCreateWithData(CFTempData(*blob), kSecCSDefaultFlags, &mRequirement.aref())); } else { - secdebug("codesign", "%p verifier adds blob (0x%x,%zd)", + secinfo("codesign", "%p verifier adds blob (0x%x,%zd)", this, blob->magic(), blob->length()); BlobCore * &slot = mAuxiliary[blob->magic()]; if (slot) @@ -124,7 +124,7 @@ const BlobCore *OSXVerifier::find(BlobCore::Magic magic) void OSXVerifier::makeLegacyHash(OSXCode *code, SHA1::Digest digest) { - secdebug("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str()); + secinfo("codesign", "calculating legacy hash for %s", code->canonicalPath().c_str()); UnixPlusPlus::AutoFileDesc fd(code->executablePath(), O_RDONLY); char buffer[legacyHashLimit]; size_t size = fd.read(buffer, legacyHashLimit); diff --git a/OSX/libsecurity_cdsa_utilities/lib/walkers.h b/OSX/libsecurity_cdsa_utilities/lib/walkers.h index b8fcb598..4ea7884e 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/walkers.h +++ b/OSX/libsecurity_cdsa_utilities/lib/walkers.h @@ -56,7 +56,7 @@ namespace DataWalkers { #if WALKERDEBUG -# define DEBUGWALK(who) secdebug("walkers", "walk " who " %s@%p (%ld)", \ +# define DEBUGWALK(who) secinfo("walkers", "walk " who " %s@%p (%ld)", \ Debug::typeName(addr).c_str(), addr, size) #else # define DEBUGWALK(who) /* nothing */ @@ -316,7 +316,7 @@ void chunkFree(T *obj, Allocator &alloc = Allocator::standard()) } template -void chunkFree(const T &obj, Allocator &alloc = Allocator::standard()) +void chunkFree(T &obj, Allocator &alloc = Allocator::standard()) { ChunkFreeWalker w(alloc); walk(w, obj); diff --git a/OSX/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj b/OSX/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj index fc8b8afa..f172ab63 100644 --- a/OSX/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cdsa_utilities/libsecurity_cdsa_utilities.xcodeproj/project.pbxproj @@ -167,7 +167,7 @@ 4CF64CFB052A3278008ED0EA /* cssmalloc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmalloc.h; sourceTree = ""; }; 4CF64CFC052A3278008ED0EA /* cssmcert.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmcert.cpp; sourceTree = ""; }; 4CF64CFD052A3278008ED0EA /* cssmcert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcert.h; sourceTree = ""; }; - 4CF64CFE052A3278008ED0EA /* cssmcred.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmcred.cpp; sourceTree = ""; }; + 4CF64CFE052A3278008ED0EA /* cssmcred.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cssmcred.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CF64CFF052A3278008ED0EA /* cssmcred.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmcred.h; sourceTree = ""; }; 4CF64D00052A3278008ED0EA /* cssmdata.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cssmdata.cpp; sourceTree = ""; }; 4CF64D01052A3278008ED0EA /* cssmdata.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cssmdata.h; sourceTree = ""; }; @@ -207,7 +207,7 @@ C2371E3F06DD3E5E00E15E6F /* acl_preauth.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_preauth.h; sourceTree = ""; }; C2BFD03006E6CDFE0047EA99 /* aclsubject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = aclsubject.cpp; sourceTree = ""; }; C2BFD03106E6CDFE0047EA99 /* aclsubject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aclsubject.h; sourceTree = ""; }; - C2BFD03206E6CDFE0047EA99 /* objectacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = objectacl.cpp; sourceTree = ""; }; + C2BFD03206E6CDFE0047EA99 /* objectacl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = objectacl.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2BFD03306E6CDFE0047EA99 /* objectacl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = objectacl.h; sourceTree = ""; }; C2BFD05A06E6D0560047EA99 /* acl_secret.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = acl_secret.cpp; sourceTree = ""; }; C2BFD05B06E6D0560047EA99 /* acl_secret.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = acl_secret.h; sourceTree = ""; }; @@ -456,7 +456,6 @@ buildRules = ( ); dependencies = ( - 182BB4F1146F2734000BF1F3 /* PBXTargetDependency */, 4CFF43000535E5E900638F31 /* PBXTargetDependency */, ); name = libsecurity_cdsa_utilities; @@ -486,7 +485,7 @@ 4CA2A5330523D2CD00978A7B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD2FA0987FCDD001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_utilities" */; compatibilityVersion = "Xcode 3.2"; @@ -532,18 +531,27 @@ files = ( ); inputPaths = ( + "$(SRCROOT)/", + "$(SRCROOT)/lib/", ); outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "nmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + shellScript = "# with our source directories as input files, Xcode will only re-run this phase if there's been a source change\nnmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; }; 4CFF42FC0535E5B100638F31 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputPaths = ( + "$(SRCROOT)/lib/KeySchema.m4", + ); + outputPaths = ( + $BUILT_PRODUCTS_DIR/derived_src/KeySchema.cpp, + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "TARGET=$BUILT_PRODUCTS_DIR/derived_src/KeySchema.cpp\nmkdir -p $BUILT_PRODUCTS_DIR/derived_src\n/usr/bin/m4 lib/KeySchema.m4 > $TARGET.new\ncmp -s $TARGET.new $TARGET || mv $TARGET.new $TARGET\nTARGET=$BUILT_PRODUCTS_DIR/derived_src/Schema.cpp\n/usr/bin/m4 lib/Schema.m4 > $TARGET.new\ncmp -s $TARGET.new $TARGET || mv $TARGET.new $TARGET"; @@ -653,12 +661,16 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1879B516146DD045007E536C /* debug.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_TESTABILITY = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -666,11 +678,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1879B518146DD045007E536C /* release.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; }; name = Release; diff --git a/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.cpp b/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.cpp index 9e8f65a0..0a822a4b 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.cpp +++ b/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.cpp @@ -189,7 +189,7 @@ CSSM_RETURN cuAddCrlToDb( CSSM_DL_DB_HANDLE dlDbHand, CSSM_CL_HANDLE clHand, const CSSM_DATA *crl, - const CSSM_DATA *URI) // optional + const CSSM_DATA *URI) { CSSM_DB_ATTRIBUTE_DATA attrs[MAX_CRL_ATTRS]; CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs; @@ -376,7 +376,20 @@ CSSM_RETURN cuAddCrlToDb( attr->NumberOfValues = 1; attr->Value = &nextUpdateData; attr++; - + + /* ensure URI string does not contain NULL */ + attrUri = *URI; + if((attrUri.Length != 0) && + (attrUri.Data[attrUri.Length - 1] == 0)) { + attrUri.Length--; + } + attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + attr->Info.Label.AttributeName = (char*) "URI"; + attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; + attr->NumberOfValues = 1; + attr->Value = &attrUri; + attr++; + /* now the optional attributes */ if(crlNumberPresent) { attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; @@ -394,20 +407,6 @@ CSSM_RETURN cuAddCrlToDb( attr->Value = &deltaCrlNumberData; attr++; } - if(URI) { - /* ensure URI string does not contain NULL */ - attrUri = *URI; - if((attrUri.Length != 0) && - (attrUri.Data[attrUri.Length - 1] == 0)) { - attrUri.Length--; - } - attr->Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; - attr->Info.Label.AttributeName = (char*) "URI"; - attr->Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB; - attr->NumberOfValues = 1; - attr->Value = &attrUri; - attr++; - } recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_X509_CRL; recordAttrs.SemanticInformation = 0; recordAttrs.NumberOfAttributes = (uint32)(attr - attrs); diff --git a/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.h b/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.h index c2c0d76d..07f0febd 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.h +++ b/OSX/libsecurity_cdsa_utils/lib/cuDbUtils.h @@ -51,7 +51,7 @@ CSSM_RETURN cuAddCrlToDb( CSSM_DL_DB_HANDLE dlDbHand, CSSM_CL_HANDLE clHand, const CSSM_DATA *crl, - const CSSM_DATA *URI); // optional + const CSSM_DATA *URI); /* * Search DB for all records of type CRL or cert, calling appropriate diff --git a/OSX/libsecurity_cdsa_utils/lib/cuFileIo.c b/OSX/libsecurity_cdsa_utils/lib/cuFileIo.c index b6181543..7b14cd29 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuFileIo.c +++ b/OSX/libsecurity_cdsa_utils/lib/cuFileIo.c @@ -32,9 +32,18 @@ #include "cuFileIo.h" int writeFile( + const char *fileName, + const unsigned char *bytes, + unsigned numBytes) +{ + size_t n = numBytes; + return writeFileSizet(fileName, bytes, n); +} + +int writeFileSizet( const char *fileName, const unsigned char *bytes, - unsigned numBytes) + size_t numBytes) { int rtn; int fd; diff --git a/OSX/libsecurity_cdsa_utils/lib/cuFileIo.h b/OSX/libsecurity_cdsa_utils/lib/cuFileIo.h index c02fdbde..44ecc853 100644 --- a/OSX/libsecurity_cdsa_utils/lib/cuFileIo.h +++ b/OSX/libsecurity_cdsa_utils/lib/cuFileIo.h @@ -22,6 +22,8 @@ Description: simple file read/write utilities */ +#include + #ifdef __cplusplus extern "C" { #endif @@ -36,6 +38,11 @@ int writeFile( const unsigned char *bytes, unsigned numBytes); +int writeFileSizet( + const char *fileName, + const unsigned char *bytes, + size_t numBytes); + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj b/OSX/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj index ce22fcc4..8bda508b 100644 --- a/OSX/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cdsa_utils/libsecurity_cdsa_utils.xcodeproj/project.pbxproj @@ -157,7 +157,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3080987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cdsa_utils" */; compatibilityVersion = "Xcode 3.2"; @@ -183,12 +183,15 @@ files = ( ); inputPaths = ( + "$(SRCROOT)/", + "$(SRCROOT)/lib/", ); outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "nmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + shellScript = "# with our source directories as input files, Xcode will only re-run this phase if there's been a source change\nnmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; }; /* End PBXShellScriptBuildPhase section */ @@ -235,12 +238,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1879B51D146DD04F007E536C /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -248,12 +260,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1879B51D146DD04F007E536C /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj b/OSX/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj index 97fd1682..7bc90be2 100644 --- a/OSX/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_checkpw/libsecurity_checkpw.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ 1C6C402A1121FC0C00031CDE /* libsecurity_checkpw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */; }; 1CB7B4C411065DDB003458C5 /* libsecurity_checkpw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_checkpw.a */; }; 1CD90B71110111A4008DD07F /* test-checkpw.c in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B631101115E008DD07F /* test-checkpw.c */; }; - 1CD90B90110112DD008DD07F /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B8F110112DD008DD07F /* libpam.dylib */; }; 1CD90BA2110113AE008DD07F /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD90B8F110112DD008DD07F /* libpam.dylib */; }; 4CCF8664052A491D00F2E8D8 /* checkpw.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CCF8662052A491D00F2E8D8 /* checkpw.c */; }; 4CF36F400581369C00834D11 /* checkpw.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CCF8663052A491D00F2E8D8 /* checkpw.h */; settings = {ATTRIBUTES = (); }; }; @@ -74,7 +73,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1CD90B90110112DD008DD07F /* libpam.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -205,7 +203,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3160987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_checkpw" */; compatibilityVersion = "Xcode 3.2"; @@ -332,12 +330,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1844616D146E966100B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -345,12 +352,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1844616D146E966100B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_cms/lib/CMSEncoder.cpp b/OSX/libsecurity_cms/lib/CMSEncoder.cpp index 4055192a..fd320aca 100644 --- a/OSX/libsecurity_cms/lib/CMSEncoder.cpp +++ b/OSX/libsecurity_cms/lib/CMSEncoder.cpp @@ -444,7 +444,6 @@ static OSStatus cmsSetupForSignedData( numSigners = CFArrayGetCount(cmsEncoder->signers); } CFIndex dex; - SecKeychainRef ourKc = NULL; SecCertificateRef ourCert = NULL; SecCmsCertChainMode chainMode = SecCmsCMCertChain; @@ -471,11 +470,6 @@ static OSStatus cmsSetupForSignedData( CSSM_PERROR("SecIdentityCopyCertificate", ortn); break; } - ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)ourCert, &ourKc); - if(ortn) { - CSSM_PERROR("SecKeychainItemCopyKeychain", ortn); - break; - } signerInfo = SecCmsSignerInfoCreate(cmsEncoder->cmsMsg, ourId, cmsEncoder->digestalgtag); if (signerInfo == NULL) { ortn = errSecInternalComponent; @@ -502,7 +496,7 @@ static OSStatus cmsSetupForSignedData( } } if(cmsEncoder->signedAttributes & kCMSAttrSmimeEncryptionKeyPrefs) { - ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc); + ortn = SecCmsSignerInfoAddSMIMEEncKeyPrefs(signerInfo, ourCert, NULL); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddSMIMEEncKeyPrefs", ortn); @@ -510,7 +504,7 @@ static OSStatus cmsSetupForSignedData( } } if(cmsEncoder->signedAttributes & kCMSAttrSmimeMSEncryptionKeyPrefs) { - ortn = SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerInfo, ourCert, ourKc); + ortn = SecCmsSignerInfoAddMSSMIMEEncKeyPrefs(signerInfo, ourCert, NULL); if(ortn) { ortn = cmsRtnToOSStatus(ortn); CSSM_PERROR("SecCmsSignerInfoAddMSSMIMEEncKeyPrefs", ortn); @@ -545,13 +539,10 @@ static OSStatus cmsSetupForSignedData( break; } - CFRELEASE(ourKc); CFRELEASE(ourCert); - ourKc = NULL; ourCert = NULL; } if(ortn) { - CFRELEASE(ourKc); CFRELEASE(ourCert); } return ortn; diff --git a/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj b/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj index 8900beec..41a286c5 100644 --- a/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ 052C07F709894AF300E7641D /* CMSDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F409894AF300E7641D /* CMSDecoder.cpp */; }; 052C07F809894AF300E7641D /* CMSEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F509894AF300E7641D /* CMSEncoder.cpp */; }; 052C07F909894AF300E7641D /* CMSUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 052C07F609894AF300E7641D /* CMSUtils.cpp */; }; + D43B9E7E1D064F0B00B9DDDA /* cms-trust-settings-test.c in Sources */ = {isa = PBXBuildFile; fileRef = D43B9E7C1D064F0B00B9DDDA /* cms-trust-settings-test.c */; }; + D43B9E7F1D064F0B00B9DDDA /* cms-trust-settings-test.h in Headers */ = {isa = PBXBuildFile; fileRef = D43B9E7D1D064F0B00B9DDDA /* cms-trust-settings-test.h */; }; D4C334601BE2A2B900D8C1EF /* cms_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = D4C334571BE29F5200D8C1EF /* cms_regressions.h */; }; D4C334631BE2A31200D8C1EF /* cms-hashagility-test.c in Sources */ = {isa = PBXBuildFile; fileRef = D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */; }; D4C334641BE2A31200D8C1EF /* cms-hashagility-test.h in Headers */ = {isa = PBXBuildFile; fileRef = D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */; }; @@ -33,6 +35,8 @@ 1844617A146E984400B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_cms.a; sourceTree = BUILT_PRODUCTS_DIR; }; 4CCB008B05800B0B00981D43 /* security_cms.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_cms.exp; sourceTree = ""; }; + D43B9E7C1D064F0B00B9DDDA /* cms-trust-settings-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-trust-settings-test.c"; path = "regressions/cms-trust-settings-test.c"; sourceTree = ""; }; + D43B9E7D1D064F0B00B9DDDA /* cms-trust-settings-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-trust-settings-test.h"; path = "regressions/cms-trust-settings-test.h"; sourceTree = ""; }; D4C334571BE29F5200D8C1EF /* cms_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cms_regressions.h; path = regressions/cms_regressions.h; sourceTree = ""; }; D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_cms_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "cms-hashagility-test.c"; path = "regressions/cms-hashagility-test.c"; sourceTree = ""; }; @@ -107,6 +111,8 @@ isa = PBXGroup; children = ( D4C334571BE29F5200D8C1EF /* cms_regressions.h */, + D43B9E7C1D064F0B00B9DDDA /* cms-trust-settings-test.c */, + D43B9E7D1D064F0B00B9DDDA /* cms-trust-settings-test.h */, D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */, D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */, ); @@ -131,6 +137,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + D43B9E7F1D064F0B00B9DDDA /* cms-trust-settings-test.h in Headers */, D4C334641BE2A31200D8C1EF /* cms-hashagility-test.h in Headers */, D4C334601BE2A2B900D8C1EF /* cms_regressions.h in Headers */, ); @@ -179,7 +186,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; TargetAttributes = { D4C3345B1BE2A2B100D8C1EF = { CreatedOnToolsVersion = 7.1; @@ -220,6 +227,7 @@ buildActionMask = 2147483647; files = ( D4C334631BE2A31200D8C1EF /* cms-hashagility-test.c in Sources */, + D43B9E7E1D064F0B00B9DDDA /* cms-trust-settings-test.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -246,13 +254,22 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446179146E984400B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -260,13 +277,20 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18446179146E984400B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; @@ -276,13 +300,13 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -312,13 +336,13 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; diff --git a/OSX/libsecurity_cms/regressions/cms-hashagility-test.c b/OSX/libsecurity_cms/regressions/cms-hashagility-test.c index 3024ca49..03961272 100644 --- a/OSX/libsecurity_cms/regressions/cms-hashagility-test.c +++ b/OSX/libsecurity_cms/regressions/cms-hashagility-test.c @@ -56,6 +56,7 @@ static void encode_test(void) "Set digest algorithm to SHA256"); /* Load identity and set as signer */ + unlink(TMP_KEYCHAIN_PATH); ok_status(SecKeychainCreate(TMP_KEYCHAIN_PATH, 8, "password", false, NULL, &keychain), "Create keychain for identity"); ok(p12Data = CFDataCreate(NULL, signing_identity_p12, sizeof(signing_identity_p12)), diff --git a/OSX/libsecurity_cms/regressions/cms-hashagility-test.h b/OSX/libsecurity_cms/regressions/cms-hashagility-test.h index 24055e72..27bf5ee3 100644 --- a/OSX/libsecurity_cms/regressions/cms-hashagility-test.h +++ b/OSX/libsecurity_cms/regressions/cms-hashagility-test.h @@ -25,6 +25,7 @@ #define cms_hashagility_test_h #include +#include int cms_hash_agility_test(int argc, char *const *argv); diff --git a/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c new file mode 100644 index 00000000..84a7dbf9 --- /dev/null +++ b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.c @@ -0,0 +1,127 @@ +/* + * 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define kSystemLoginKeychainPath "/Library/Keychains/System.keychain" + +#include +#include "cms-trust-settings-test.h" + +// See +static void test(void) { + SecCertificateRef cert = NULL; + SecKeychainRef kcRef = NULL; + CFMutableDictionaryRef query = NULL; + CFDictionaryRef trustSettings = NULL; + CFArrayRef persistentRef = NULL; + CMSDecoderRef decoder = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CMSSignerStatus signerStatus = kCMSSignerInvalidIndex; + SecTrustResultType trustResult = kSecTrustResultInvalid; + + /* Add cert to keychain */ + ok(cert = SecCertificateCreateWithBytes(NULL, _cert, sizeof(_cert)), "Create cert"); + ok_status(SecKeychainOpen(kSystemLoginKeychainPath, &kcRef), "Open system keychain"); + if (!kcRef) { + goto out; + } + ok(query = CFDictionaryCreateMutable(NULL, 3, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), + "Create SecItem dictionary"); + CFDictionaryAddValue(query, kSecValueRef, cert); + CFDictionaryAddValue(query, kSecUseKeychain, kcRef); + CFDictionaryAddValue(query, kSecReturnPersistentRef, kCFBooleanTrue); + ok_status(SecItemAdd(query, (void *)&persistentRef), + "Add cert to system keychain"); + + /* Set trust settings */ + CFStringRef temp = kSecTrustSettingsResult; + uint32_t otherTemp = kSecTrustSettingsResultDeny; + CFNumberRef deny = CFNumberCreate(NULL, kCFNumberSInt32Type, &otherTemp); + trustSettings = CFDictionaryCreate(NULL, (const void **)&temp, (const void **)&deny, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFReleaseNull(deny); + ok_status(SecTrustSettingsSetTrustSettings(cert, kSecTrustSettingsDomainAdmin, trustSettings), + "Set cert as denied"); + // Wait for trustd to get the message + sleep(1); + + /* Create the Decoder */ + ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); + ok_status(CMSDecoderUpdateMessage(decoder, _signed_message, sizeof(_signed_message)), + "Update decoder with CMS message"); + ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); + + /* Evaluate trust */ + ok(policy = SecPolicyCreateBasicX509(), "Create policy"); + ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, true, &signerStatus, &trust, NULL), + "Copy Signer status"); + ok_status(SecTrustGetTrustResult(trust, &trustResult), "Get trust result"); + is(trustResult, kSecTrustResultDeny, "Not denied"); + +out: + if (persistentRef) { + CFTypeRef item = CFArrayGetValueAtIndex(persistentRef, 0); + CFDictionaryRef del = CFDictionaryCreate(NULL, (const void **)&kSecValuePersistentRef, &item, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + SecItemDelete(del); + CFReleaseNull(del); + } + CFReleaseNull(cert); + CFReleaseNull(kcRef); + CFReleaseNull(query); + CFReleaseNull(persistentRef); + CFReleaseNull(trustSettings); + CFReleaseNull(decoder); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +int cms_trust_settings_test(int argc, char *const *argv) { + plan_tests(12); + +#if !TARGET_OS_IPHONE + if (getuid() != 0) { + printf("Test must be run as root on OS X"); + return 0; + } +#endif + + test(); + + return 0; +} diff --git a/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h new file mode 100644 index 00000000..10f1021d --- /dev/null +++ b/OSX/libsecurity_cms/regressions/cms-trust-settings-test.h @@ -0,0 +1,180 @@ +/* + * 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@ + */ + +#ifndef cms_trust_settings_test_h +#define cms_trust_settings_test_h + +#include + +int cms_trust_settings_test(int argc, char *const *argv); + +unsigned char _cert[] = { + 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, +}; + +unsigned char _signed_message[] = { + 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, 0x01, 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 +}; + +#endif /* cms_trust_settings_test_h */ diff --git a/OSX/libsecurity_cms/regressions/cms_regressions.h b/OSX/libsecurity_cms/regressions/cms_regressions.h index 30a2e4e6..8d8d5509 100644 --- a/OSX/libsecurity_cms/regressions/cms_regressions.h +++ b/OSX/libsecurity_cms/regressions/cms_regressions.h @@ -25,4 +25,5 @@ #include -ONE_TEST(cms_hash_agility_test) \ No newline at end of file +ONE_TEST(cms_hash_agility_test) +ONE_TEST(cms_trust_settings_test) diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist b/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist index 49b47515..40272dbb 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/CodeSigningHelper-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - ${PRODUCT_NAME} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.c b/OSX/libsecurity_codesigning/CodeSigningHelper/main.c index 553a8c4d..f81de057 100644 --- a/OSX/libsecurity_codesigning/CodeSigningHelper/main.c +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.c @@ -94,6 +94,9 @@ fetchData(xpc_connection_t peer, xpc_object_t event) pid = (pid_t)xpc_dictionary_get_int64(event, "pid"); if (pid <= 0) return; + + size_t iphLength; + const void* iphash = xpc_dictionary_get_data(event, "infohash", &iphLength); xpc_object_t reply = xpc_dictionary_create_reply(event); if (reply == NULL) @@ -130,6 +133,8 @@ fetchData(xpc_connection_t peer, xpc_object_t event) xpc_dictionary_set_string(reply, "error", "can't get content of Info.plist"); goto send; } + + ... check the "right" hash against iphash/iphLength xpc_dictionary_set_data(reply, "infoPlist", CFDataGetBytePtr(data), CFDataGetLength(data)); CFRelease(data); diff --git a/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp new file mode 100644 index 00000000..be200db3 --- /dev/null +++ b/OSX/libsecurity_codesigning/CodeSigningHelper/main.cpp @@ -0,0 +1,108 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "codedirectory.h" + + + +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; + + xpc_object_t reply = xpc_dictionary_create_reply(event); + if (reply == NULL) + return; + + CFTemp attributes("{%O=%d}", kSecGuestAttributePid, pid); + CFRef code; + if ((rc = SecCodeCopyGuestWithAttributes(NULL, attributes, kSecCSDefaultFlags, &code.aref())) == noErr) { + + // path to base of client code + CFRef codePath; + if ((rc = SecCodeCopyPath(code, kSecCSDefaultFlags, &codePath.aref())) == noErr) { + CFRef data = CFURLCreateData(NULL, codePath, kCFStringEncodingUTF8, true); + xpc_dictionary_set_data(reply, "bundleURL", CFDataGetBytePtr(data), CFDataGetLength(data)); + } + + // if the caller wants the Info.plist, get it and verify the hash passed by the caller + size_t iphLength; + if (const void *iphash = xpc_dictionary_get_data(event, "infohash", &iphLength)) { + if (CFRef data = SecCodeCopyComponent(code, Security::CodeSigning::cdInfoSlot, CFTempData(iphash, iphLength))) { + xpc_dictionary_set_data(reply, "infoPlist", CFDataGetBytePtr(data), CFDataGetLength(data)); + } + } + } + xpc_connection_send_message(peer, reply); + xpc_release(reply); +} + + +static void CodeSigningHelper_peer_event_handler(xpc_connection_t peer, xpc_object_t event) +{ + xpc_type_t type = xpc_get_type(event); + if (type == XPC_TYPE_ERROR) + return; + + assert(type == XPC_TYPE_DICTIONARY); + + const char *cmd = xpc_dictionary_get_string(event, "command"); + if (cmd == NULL) { + xpc_connection_cancel(peer); + } else if (strcmp(cmd, "fetchData") == 0) + request(peer, event); + else { + Syslog::error("peer sent invalid command %s", cmd); + xpc_connection_cancel(peer); + } +} + + +static void CodeSigningHelper_event_handler(xpc_connection_t peer) +{ + xpc_connection_set_event_handler(peer, ^(xpc_object_t event) { + CodeSigningHelper_peer_event_handler(peer, event); + }); + xpc_connection_resume(peer); +} + +int main(int argc, const char *argv[]) +{ + char *error = NULL; + if (sandbox_init("com.apple.CodeSigningHelper", SANDBOX_NAMED, &error)) { + Syslog::error("failed to enter sandbox: %s", error); + exit(EXIT_FAILURE); + } + xpc_main(CodeSigningHelper_event_handler); + return 0; +} diff --git a/OSX/libsecurity_codesigning/lib/CSCommon.h b/OSX/libsecurity_codesigning/lib/CSCommon.h index be1be0fd..11e2f517 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommon.h +++ b/OSX/libsecurity_codesigning/lib/CSCommon.h @@ -118,6 +118,9 @@ CF_ENUM(OSStatus) { errSecCSNotAppLike = -67002, /* the code is valid but does not seem to be an app */ errSecCSBadDiskImageFormat = -67001, /* disk image format unrecognized, invalid, or unsuitable */ errSecCSUnsupportedDigestAlgorithm = -67000, /* signature digest algorithm(s) specified are not supported */ + errSecCSInvalidAssociatedFileData = -66999, /* resource fork, Finder information, or similar detritus not allowed */ + errSecCSInvalidTeamIdentifier = -66998, /* a Team Identifier string is invalid */ + errSecCSBadTeamIdentifier = -66997, /* a Team Identifier is wrong or inappropriate */ }; /* @@ -135,6 +138,7 @@ extern const CFStringRef kSecCFErrorResourceSeal; /* CFTypeRef: invalid componen extern const CFStringRef kSecCFErrorResourceAdded; /* CFURLRef: unsealed resource found */ extern const CFStringRef kSecCFErrorResourceAltered; /* CFURLRef: modified resource found */ extern const CFStringRef kSecCFErrorResourceMissing; /* CFURLRef: sealed (non-optional) resource missing */ +extern const CFStringRef kSecCFErrorResourceSideband; /* CFURLRef: sealed resource has invalid sideband data (resource fork, etc.) */ extern const CFStringRef kSecCFErrorInfoPlist; /* CFTypeRef: Info.plist dictionary or component thereof found invalid */ extern const CFStringRef kSecCFErrorGuestAttributes; /* CFTypeRef: Guest attribute set of element not accepted */ extern const CFStringRef kSecCFErrorRequirementSyntax; /* CFStringRef: compilation error for Requirement source */ @@ -200,11 +204,12 @@ CF_ENUM(SecGuestRef) { typedef CF_OPTIONS(uint32_t, SecCSFlags) { kSecCSDefaultFlags = 0, /* no particular flags (default behavior) */ - kSecCSConsiderExpiration = 1 << 31, /* consider expired certificates invalid */ + kSecCSConsiderExpiration = 1U << 31, /* consider expired certificates invalid */ kSecCSEnforceRevocationChecks = 1 << 30, /* force revocation checks regardless of preference settings */ kSecCSNoNetworkAccess = 1 << 29, /* do not use the network, cancels "kSecCSEnforceRevocationChecks" */ 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) */ }; diff --git a/OSX/libsecurity_codesigning/lib/Code.cpp b/OSX/libsecurity_codesigning/lib/Code.cpp index 3194bf3d..d5de3047 100644 --- a/OSX/libsecurity_codesigning/lib/Code.cpp +++ b/OSX/libsecurity_codesigning/lib/Code.cpp @@ -259,9 +259,9 @@ SecCode *SecCode::autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags) if (CFDictionaryGetCount(attributes) == 0) return KernelCode::active()->retain(); - // main logic: we need a pid, and we'll take a canonical guest id as an option - int pid = 0; - if (!cfscan(attributes, "{%O=%d}", kSecGuestAttributePid, &pid)) + // main logic: we need a pid or audit trailer; everything else goes to the guests + if (CFDictionaryGetValue(attributes, kSecGuestAttributePid) == NULL + && CFDictionaryGetValue(attributes, kSecGuestAttributeAudit) == NULL) CSError::throwMe(errSecCSUnsupportedGuestAttributes, kSecCFErrorGuestAttributes, attributes); if (SecCode *process = KernelCode::active()->locateGuest(attributes)) { @@ -271,6 +271,7 @@ SecCode *SecCode::autoLocateGuest(CFDictionaryRef attributes, SecCSFlags flags) // might be a code host. Let's find out CFRef rest = makeCFMutableDictionary(attributes); CFDictionaryRemoveValue(rest, kSecGuestAttributePid); + CFDictionaryRemoveValue(rest, kSecGuestAttributeAudit); if (SecCode *guest = code->locateGuest(rest)) return guest; } diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp index 783262ba..ee8045f9 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp @@ -138,12 +138,12 @@ void SecCodeSigner::sign(SecStaticCode *code, SecCSFlags flags) return; Signer operation(*this, code); if ((flags | mOpFlags) & kSecCSRemoveSignature) { - secdebug("signer", "%p will remove signature from %p", this, code); + secinfo("signer", "%p will remove signature from %p", this, code); operation.remove(flags); } else { if (!valid()) MacOSError::throwMe(errSecCSInvalidObjectRef); - secdebug("signer", "%p will sign %p (flags 0x%x)", this, code, flags); + secinfo("signer", "%p will sign %p (flags 0x%x)", this, code, flags); operation.sign(flags); } code->resetValidity(); diff --git a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp index ff228381..2c1e06bd 100644 --- a/OSX/libsecurity_codesigning/lib/SecAssessment.cpp +++ b/OSX/libsecurity_codesigning/lib/SecAssessment.cpp @@ -27,6 +27,7 @@ #include "xpcengine.h" #include "csutilities.h" #include +#include #include #include #include @@ -133,6 +134,8 @@ CFStringRef kSecAssessmentFeedbackProgress = CFSTR("feedback:progress"); CFStringRef kSecAssessmentFeedbackInfoCurrent = CFSTR("current"); CFStringRef kSecAssessmentFeedbackInfoTotal = CFSTR("total"); +CFStringRef kSecAssessmentContextKeyPrimarySignature = CFSTR("context:primary-signature"); + CFStringRef kSecAssessmentAssessmentVerdict = CFSTR("assessment:verdict"); CFStringRef kSecAssessmentAssessmentOriginator = CFSTR("assessment:originator"); CFStringRef kSecAssessmentAssessmentAuthority = CFSTR("assessment:authority"); @@ -140,6 +143,7 @@ CFStringRef kSecAssessmentAssessmentSource = CFSTR("assessment:authority:source" CFStringRef kSecAssessmentAssessmentAuthorityRow = CFSTR("assessment:authority:row"); CFStringRef kSecAssessmentAssessmentAuthorityOverride = CFSTR("assessment:authority:override"); CFStringRef kSecAssessmentAssessmentAuthorityOriginalVerdict = CFSTR("assessment:authority:verdict"); +CFStringRef kSecAssessmentAssessmentAuthorityFlags = CFSTR("assessment:authority:flags"); CFStringRef kSecAssessmentAssessmentFromCache = CFSTR("assessment:authority:cached"); CFStringRef kSecAssessmentAssessmentWeakSignature = CFSTR("assessment:authority:weak"); CFStringRef kSecAssessmentAssessmentCodeSigningError = CFSTR("assessment:cserror"); @@ -238,7 +242,7 @@ static void traceResult(CFURLRef target, MessageTrace &trace, std::string &sanit string identifier = "UNBUNDLED"; string version = "UNKNOWN"; - if (CFRef bundle = CFBundleCreate(NULL, target)) { + if (CFRef bundle = _CFBundleCreateUnique(NULL, target)) { if (CFStringRef ident = CFBundleGetIdentifier(bundle)) identifier = cfString(ident); if (CFStringRef vers = CFStringRef(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString")))) @@ -497,20 +501,21 @@ Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *e result = kCFBooleanTrue; return true; } else if (CFEqual(control, CFSTR("ui-enable-devid"))) { - CFTemp ctx("{%O=%s}", kSecAssessmentUpdateKeyLabel, "Developer ID"); - if (CFDictionaryRef result = gEngine().enable(NULL, kAuthorityInvalid, kSecCSDefaultFlags, ctx, false)) - CFRelease(result); + CFTemp ctx("{%O=%s, %O=%O}", kSecAssessmentUpdateKeyLabel, "Developer ID", kSecAssessmentContextKeyUpdate, kSecAssessmentUpdateOperationEnable); + SecAssessmentUpdate(NULL, kSecCSDefaultFlags, ctx, errors); MessageTrace trace("com.apple.security.assessment.state", "enable-devid"); trace.send("enable Developer ID approval"); return true; } else if (CFEqual(control, CFSTR("ui-disable-devid"))) { - CFTemp ctx("{%O=%s}", kSecAssessmentUpdateKeyLabel, "Developer ID"); - if (CFDictionaryRef result = gEngine().disable(NULL, kAuthorityInvalid, kSecCSDefaultFlags, ctx, false)) - CFRelease(result); + CFTemp ctx("{%O=%s, %O=%O}", kSecAssessmentUpdateKeyLabel, "Developer ID", kSecAssessmentContextKeyUpdate, kSecAssessmentUpdateOperationDisable); + SecAssessmentUpdate(NULL, kSecCSDefaultFlags, ctx, errors); MessageTrace trace("com.apple.security.assessment.state", "disable-devid"); trace.send("disable Developer ID approval"); return true; - } else if (CFEqual(control, CFSTR("ui-get-devid"))) { + } else if (CFEqual(control, CFSTR("ui-get-devid"))) { + xpcEngineCheckDevID((CFBooleanRef*)(arguments)); + return true; + } else if (CFEqual(control, CFSTR("ui-get-devid-local"))) { CFBooleanRef &result = *(CFBooleanRef*)(arguments); if (gEngine().value("SELECT disabled FROM authority WHERE label = 'Developer ID';", true)) result = kCFBooleanFalse; diff --git a/OSX/libsecurity_codesigning/lib/SecAssessment.h b/OSX/libsecurity_codesigning/lib/SecAssessment.h index fb17a20e..efc6dd4a 100644 --- a/OSX/libsecurity_codesigning/lib/SecAssessment.h +++ b/OSX/libsecurity_codesigning/lib/SecAssessment.h @@ -87,7 +87,6 @@ extern CFStringRef kSecAssessmentOperationTypeOpenDocument; // .. LaunchServices @constant kSecAssessmentAllowWeak Allow signatures that contain known weaknesses, such as an insecure resource envelope. @constant kSecAssessmentIgnoreWhitelist Do not search the weak signature whitelist. - @constant kSecAssessmentFlagDequarantine Set the ASSESSMENT_OK flag if successful. @constant kSecAssessmentFlagIgnoreActiveAssessments Permit parallel re-assessment of the same target. @constant kSecAssessmentFlagLowPriority Run the assessment in low priority. @@ -105,7 +104,7 @@ enum { kSecAssessmentFlagEnforce = 1 << 26, // force on (disable bypass switches) kSecAssessmentFlagAllowWeak = 1 << 25, // allow weak signatures kSecAssessmentFlagIgnoreWhitelist = 1 << 24, // do not search weak signature whitelist - kSecAssessmentFlagDequarantine = 1 << 23, // set the ASSESSMENT_OK flag if successful + // 1 << 23 removed (was kSecAssessmentFlagDequarantine) kSecAssessmentFlagIgnoreActiveAssessments = 1 << 22, // permit parallel re-assessment of the same target kSecAssessmentFlagLowPriority = 1 << 21, // run the assessment in low priority }; @@ -144,6 +143,8 @@ extern CFStringRef kSecAssessmentFeedbackProgress; // progress reporting feedba extern CFStringRef kSecAssessmentFeedbackInfoCurrent; // info key: current work progress extern CFStringRef kSecAssessmentFeedbackInfoTotal; // info key: total expected work +extern CFStringRef kSecAssessmentContextKeyPrimarySignature; // on document assessment, treat code signature as primary and return its status + extern CFStringRef kSecAssessmentAssessmentVerdict; // CFBooleanRef: master result - allow or deny extern CFStringRef kSecAssessmentAssessmentOriginator; // CFStringRef: describing the signature originator extern CFStringRef kSecAssessmentAssessmentAuthority; // CFDictionaryRef: authority used to arrive at result @@ -154,6 +155,7 @@ extern CFStringRef kSecAssessmentAssessmentCodeSigningError; // error code retur extern CFStringRef kSecAssessmentAssessmentAuthorityRow; // (internal) extern CFStringRef kSecAssessmentAssessmentAuthorityOverride; // (internal) extern CFStringRef kSecAssessmentAssessmentAuthorityOriginalVerdict; // (internal) +extern CFStringRef kSecAssessmentAssessmentAuthorityFlags; // (internal) extern CFStringRef kDisabledOverride; // AuthorityOverride value for "Gatekeeper is disabled" diff --git a/OSX/libsecurity_codesigning/lib/SecCode.cpp b/OSX/libsecurity_codesigning/lib/SecCode.cpp index 59587ce7..7f6708bf 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCode.cpp @@ -46,6 +46,7 @@ const CFStringRef kSecCFErrorResourceSeal = CFSTR("SecCSResourceSeal"); const CFStringRef kSecCFErrorResourceAdded = CFSTR("SecCSResourceAdded"); const CFStringRef kSecCFErrorResourceAltered = CFSTR("SecCSResourceAltered"); const CFStringRef kSecCFErrorResourceMissing = CFSTR("SecCSResourceMissing"); +const CFStringRef kSecCFErrorResourceSideband = CFSTR("SecCSResourceHasSidebandData"); const CFStringRef kSecCFErrorInfoPlist = CFSTR("SecCSInfoPlist"); const CFStringRef kSecCFErrorGuestAttributes = CFSTR("SecCSGuestAttributes"); const CFStringRef kSecCFErrorRequirementSyntax = CFSTR("SecRequirementSyntax"); @@ -152,8 +153,9 @@ const CFStringRef kSecGuestAttributeCanonical = CFSTR("canonical"); const CFStringRef kSecGuestAttributeHash = CFSTR("codedirectory-hash"); const CFStringRef kSecGuestAttributeMachPort = CFSTR("mach-port"); const CFStringRef kSecGuestAttributePid = CFSTR("pid"); -const CFStringRef kSecGuestAttributeDynamicCode = CFSTR("dynamicCode"); -const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInfoPlist"); +const CFStringRef kSecGuestAttributeAudit = CFSTR("audit"); +const CFStringRef kSecGuestAttributeDynamicCode = CFSTR("dynamicCode"); +const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist = CFSTR("dynamicCodeInfoPlist"); const CFStringRef kSecGuestAttributeArchitecture = CFSTR("architecture"); const CFStringRef kSecGuestAttributeSubarchitecture = CFSTR("subarchitecture"); @@ -204,12 +206,12 @@ OSStatus SecCodeCheckValidity(SecCodeRef codeRef, SecCSFlags flags, OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, SecRequirementRef requirementRef, CFErrorRef *errors) { -#if !SECTRUST_OSX BEGIN_CSAPI checkFlags(flags, kSecCSConsiderExpiration | kSecCSStrictValidate + | kSecCSRestrictSidebandData | kSecCSEnforceRevocationChecks); SecPointer code = SecCode::required(codeRef); code->checkValidity(flags); @@ -217,41 +219,6 @@ OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed); END_CSAPI_ERRORS -#else -#warning resolve before enabling SECTRUST_OSX: - OSStatus result = errSecSuccess; - const char *func = "SecCodeCheckValidity"; - CFErrorRef localErrors = NULL; - if (!errors) { errors = &localErrors; } - try { - checkFlags(flags, - kSecCSConsiderExpiration - | kSecCSEnforceRevocationChecks); - SecPointer code = SecCode::required(codeRef); - code->checkValidity(flags); - if (const SecRequirement *req = SecRequirement::optional(requirementRef)) - code->staticCode()->validateRequirement(req->requirement(), errSecCSReqFailed); - } - catch (...) { - // the actual error being thrown is not being caught by any of the - // type-specific blocks contained in the END_CSAPI_ERRORS macro, - // so we only have the catch-all block here for now. - result = errSecCSInternalError; - } - - if (errors && *errors) { - CFShow(errors); - CFRelease(errors); - *errors = NULL; - } - if (result == errSecCSInternalError) { - #if !NDEBUG - Security::Syslog::error("WARNING: %s ignored error %d", func, (int)result); - #endif - result = errSecSuccess; - } - return result; -#endif } @@ -292,8 +259,15 @@ const CFStringRef kSecCodeInfoCdHashes = CFSTR("cdhashes"); const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory"); const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset"); +const CFStringRef kSecCodeInfoDiskRepInfo = CFSTR("DiskRepInfo"); const CFStringRef kSecCodeInfoResourceDirectory = CFSTR("ResourceDirectory"); +/* DiskInfoRepInfo types */ +const CFStringRef kSecCodeInfoDiskRepOSPlatform = CFSTR("OSPlatform"); +const CFStringRef kSecCodeInfoDiskRepOSVersionMin = CFSTR("OSVersionMin"); +const CFStringRef kSecCodeInfoDiskRepOSSDKVersion = CFSTR("SDKVersion"); +const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation = CFSTR("NoLibraryValidation"); + OSStatus SecCodeCopySigningInformation(SecStaticCodeRef codeRef, SecCSFlags flags, CFDictionaryRef *infoRef) diff --git a/OSX/libsecurity_codesigning/lib/SecCode.h b/OSX/libsecurity_codesigning/lib/SecCode.h index a5c7dd0e..b636b9d5 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.h +++ b/OSX/libsecurity_codesigning/lib/SecCode.h @@ -111,7 +111,7 @@ OSStatus SecCodeCopyStaticCode(SecCodeRef code, SecCSFlags flags, SecStaticCodeR and is the ultimate authority on the its dynamic validity and status. The host relationship is securely established (absent reported errors). - @param code A valid SecCode object reference representing code running + @param guest A valid SecCode object reference representing code running on the system. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param host On successful return, a SecCode object reference identifying @@ -121,6 +121,16 @@ OSStatus SecCodeCopyStaticCode(SecCodeRef code, SecCSFlags flags, SecStaticCodeR */ OSStatus SecCodeCopyHost(SecCodeRef guest, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED host); +extern const CFStringRef kSecGuestAttributeCanonical; +extern const CFStringRef kSecGuestAttributeHash; +extern const CFStringRef kSecGuestAttributeMachPort; +extern const CFStringRef kSecGuestAttributePid; +extern const CFStringRef kSecGuestAttributeAudit; +extern const CFStringRef kSecGuestAttributeDynamicCode; +extern const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist; +extern const CFStringRef kSecGuestAttributeArchitecture; +extern const CFStringRef kSecGuestAttributeSubarchitecture; + /*! @function SecCodeCopyGuestWithAttributes This is the omnibus API function for obtaining dynamic code references. @@ -175,14 +185,6 @@ OSStatus SecCodeCopyHost(SecCodeRef guest, SecCSFlags flags, SecCodeRef * __nonn @error errSecCSMultipleGuests The attributes specified do not uniquely identify a guest (the specification is ambiguous). */ -extern const CFStringRef kSecGuestAttributeCanonical; -extern const CFStringRef kSecGuestAttributeHash; -extern const CFStringRef kSecGuestAttributeMachPort; -extern const CFStringRef kSecGuestAttributePid; -extern const CFStringRef kSecGuestAttributeDynamicCode; -extern const CFStringRef kSecGuestAttributeDynamicCodeInfoPlist; -extern const CFStringRef kSecGuestAttributeArchitecture; -extern const CFStringRef kSecGuestAttributeSubarchitecture; OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef __nullable host, CFDictionaryRef __nullable attributes, SecCSFlags flags, SecCodeRef * __nonnull CF_RETURNS_RETAINED guest); @@ -201,6 +203,30 @@ OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef __nullable host, This call is secure against attempts to modify the file system source of the SecCode. + @param code The code object to be validated. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param requirement An optional code requirement specifying additional conditions + the code object must satisfy to be considered valid. If NULL, no additional + requirements are imposed. + @result If validation passes, errSecSuccess. If validation fails, an OSStatus value + documented in CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecCodeCheckValidity(SecCodeRef code, SecCSFlags flags, + SecRequirementRef __nullable requirement); + +/*! + @function SecCodeCheckValidityWifErrors + 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 + dynamic validity status as reported by its host. It ensures that the SecCode's + host is in turn valid. Finally, it validates the code against a SecRequirement + if one is given. The call succeeds if all these conditions are satisfactory. + It fails otherwise. + + This call is secure against attempts to modify the file system source of the + SecCode. + @param code The code object to be validated. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param requirement An optional code requirement specifying additional conditions @@ -213,9 +239,6 @@ OSStatus SecCodeCopyGuestWithAttributes(SecCodeRef __nullable host, @result If validation passes, errSecSuccess. If validation fails, an OSStatus value documented in CSCommon.h or certain other Security framework headers. */ -OSStatus SecCodeCheckValidity(SecCodeRef code, SecCSFlags flags, - SecRequirementRef __nullable requirement); - OSStatus SecCodeCheckValidityWithErrors(SecCodeRef code, SecCSFlags flags, SecRequirementRef __nullable requirement, CFErrorRef *errors); @@ -226,10 +249,7 @@ OSStatus SecCodeCheckValidityWithErrors(SecCodeRef code, SecCSFlags flags, code object can be found. For single files, the URL points to that file. For bundles, it points to the directory containing the entire bundle. - This returns the same URL as the kSecCodeInfoMainExecutable key returned - by SecCodeCopySigningInformation. - - @param code The Code or StaticCode object to be located. For a Code + @param staticCode The Code or StaticCode object to be located. For a Code argument, its StaticCode is processed as per SecCodeCopyStaticCode. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param path On successful return, contains a CFURL identifying the location @@ -340,10 +360,12 @@ OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef code, SecCSFlags flag @constant kSecCodeInfoFormat A CFString characterizing the type and format of the code. Suitable for display to a (knowledeable) user. @constant kSecCodeInfoDigestAlgorithm A CFNumber indicating the kind of cryptographic - hash function actually used to establish integrity of the signature. + hash function chosen to establish integrity of the signature on this system, which + is the best supported algorithm from kSecCodeInfoDigestAlgorithms. @constant kSecCodeInfoDigestAlgorithms A CFArray of CFNumbers indicating the kinds of cryptographic hash functions available within the signature. The ordering of those items - has no significance. + has no significance in terms of priority, but determines the order in which + the hashes appear in kSecCodeInfoCdHashes. @constant kSecCodeInfoPlatformIdentifier If this code was signed as part of an operating system release, this value identifies that release. @constant kSecCodeInfoIdentifier A CFString with the actual signing identifier @@ -391,6 +413,11 @@ OSStatus SecCodeCopyDesignatedRequirement(SecStaticCodeRef code, SecCSFlags flag remains stable across (developer-approved) updates. The algorithm used may change from time to time. However, for any existing signature, the value is stable. + @constant kSecCodeInfoCdHashes An array containing the values of the kSecCodeInfoUnique + binary identifier for every digest algorithm supported in the signature, in the same + order as in the kSecCodeInfoDigestAlgorithms array. The kSecCodeInfoUnique value + will be contained in this array, and be the one corresponding to the + kSecCodeInfoDigestAlgorithm value. */ CF_ENUM(uint32_t) { kSecCSInternalInformation = 1 << 0, diff --git a/OSX/libsecurity_codesigning/lib/SecCodePriv.h b/OSX/libsecurity_codesigning/lib/SecCodePriv.h index 158121a9..86e1064b 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodePriv.h +++ b/OSX/libsecurity_codesigning/lib/SecCodePriv.h @@ -42,8 +42,13 @@ extern "C" { */ extern const CFStringRef kSecCodeInfoCodeDirectory; /* Internal */ extern const CFStringRef kSecCodeInfoCodeOffset; /* Internal */ +extern const CFStringRef kSecCodeInfoDiskRepInfo; /* Internal */ extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */ +extern const CFStringRef kSecCodeInfoDiskRepOSPlatform; /* Number */ +extern const CFStringRef kSecCodeInfoDiskRepOSVersionMin; /* Number */ +extern const CFStringRef kSecCodeInfoDiskRepOSSDKVersion; /* Number */ +extern const CFStringRef kSecCodeInfoDiskRepNoLibraryValidation; /* String */ /*! @function SecCodeGetStatus @@ -178,6 +183,39 @@ OSStatus SecCodeSetDetachedSignature(SecStaticCodeRef code, CFDataRef signature, SecCSFlags flags); + +/* + @function SecCodeCopyComponent + For a SecStaticCodeRef, directly retrieve the binary blob for a special slot, + optionally checking that its native hash is the one given. + + @param code A code or StaticCode object. + @param slot The (positive) special slot number requested. + @param hash A CFDataRef containing the native slot hash for the slot requested. + @result NULL if anything went wrong (including a missing slot), or a CFDataRef + containing the slot data. + */ +CFDataRef SecCodeCopyComponent(SecCodeRef code, int slot, CFDataRef hash); + + +/* + @funtion SecCodeValidateFileResource + For a SecStaticCodeRef, check that a given CFData object faithfully represents + a plain-file resource in its resource seal. + This call will fail if the file is missing in the bundle, even if it is optional. + + @param code A code or StaticCode object. + @param relativePath A CFStringRef containing the relative path to a sealed resource + file. This path is relative to the resource base, which is either Contents or + the bundle root, depending on bundle format. + @param fileData A CFDataRef containing the exact contents of that resource file. + @param flags Pass kSecCSDefaultFlags. + @result noErr if fileData is the exact content of the file at relativePath at the + time it was signed. Various error codes if it is different, there was no such file, + it was not a plain file, or anything is irregular. +*/ +OSStatus SecCodeValidateFileResource(SecStaticCodeRef code, CFStringRef relativePath, CFDataRef fileData, SecCSFlags flags); + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp b/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp index bae22bd5..7d83ce7a 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp @@ -60,6 +60,8 @@ const CFStringRef kSecCodeSignerPreserveMetadata = CFSTR("preserve-metadata"); const CFStringRef kSecCodeSignerTeamIdentifier = CFSTR("teamidentifier"); const CFStringRef kSecCodeSignerPlatformIdentifier = CFSTR("platform-identifier"); + + // // CF-standard type code functions // diff --git a/OSX/libsecurity_codesigning/lib/SecRequirement.h b/OSX/libsecurity_codesigning/lib/SecRequirement.h index 11cf0265..64d782f8 100644 --- a/OSX/libsecurity_codesigning/lib/SecRequirement.h +++ b/OSX/libsecurity_codesigning/lib/SecRequirement.h @@ -81,10 +81,6 @@ OSStatus SecRequirementCreateWithData(CFDataRef data, SecCSFlags flags, @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param requirement On successful return, contains a reference to a SecRequirement object that implements the conditions described in text. - @param errors An optional pointer to a CFErrorRef variable. If the call fails - (and something other than errSecSuccess is returned), and this argument is non-NULL, - a CFErrorRef is stored there further describing the nature and circumstances - of the failure. The caller must CFRelease() this error object when done with it. @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in CSCommon.h or certain other Security framework headers. */ diff --git a/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h b/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h index c7ad3683..d1bdfb4b 100644 --- a/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h +++ b/OSX/libsecurity_codesigning/lib/SecRequirementPriv.h @@ -87,7 +87,7 @@ OSStatus SecRequirementsCopyRequirements(CFDataRef requirementSet, SecCSFlags fl @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in CSCommon.h or certain other Security framework headers. */ -enum { +typedef CF_OPTIONS(uint32_t, SecCSFlagsPriv) { kSecCSParseRequirement = 0x0001, // accept single requirements kSecCSParseRequirementSet = 0x0002, // accept requirement sets }; @@ -110,7 +110,7 @@ OSStatus SecRequirementsCreateWithString(CFStringRef text, SecCSFlags flags, recompiling the text using SecRequirementCreateWithString will produce a SecRequirement object that behaves identically to the one you start with. - @param requirements A SecRequirementRef, or a CFDataRef containing a valid requirement set. + @param input A SecRequirementRef, or a CFDataRef containing a valid requirement set. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. @param text On successful return, contains a reference to a CFString object containing a text representation of the requirement. @@ -158,7 +158,9 @@ OSStatus SecRequirementCreateGroup(CFStringRef groupName, SecCertificateRef anch SecCSFlags flags, SecRequirementRef *requirement); - +extern CFStringRef kSecRequirementKeyInfoPlist; +extern CFStringRef kSecRequirementKeyEntitlements; +extern CFStringRef kSecRequirementKeyIdentifier; /*! @function SecRequirementEvaluate Explicitly evaluate a SecRequirementRef against context provided in the call. @@ -181,10 +183,6 @@ OSStatus SecRequirementCreateGroup(CFStringRef groupName, SecCertificateRef anch an entitlement dictionary. If this key is missing, all references to entitlements will fail. @constant kSecRequirementKeyIdentifier A context key providing the signing identifier as a CFString. */ -extern CFStringRef kSecRequirementKeyInfoPlist; -extern CFStringRef kSecRequirementKeyEntitlements; -extern CFStringRef kSecRequirementKeyIdentifier; - OSStatus SecRequirementEvaluate(SecRequirementRef requirement, CFArrayRef certificateChain, CFDictionaryRef context, SecCSFlags flags); diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp index 18625c27..f4889f69 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -105,7 +105,6 @@ OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCodeRef, SecCSFlags f OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, SecCSFlags flags, SecRequirementRef requirementRef, CFErrorRef *errors) { -#if !SECTRUST_OSX BEGIN_CSAPI checkFlags(flags, @@ -114,10 +113,11 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se | kSecCSDoNotValidateExecutable | kSecCSDoNotValidateResources | kSecCSConsiderExpiration - | kSecCSEnforceRevocationChecks + | kSecCSEnforceRevocationChecks | kSecCSNoNetworkAccess | kSecCSCheckNestedCode | kSecCSStrictValidate + | kSecCSRestrictSidebandData | kSecCSCheckGatekeeperArchitectures | kSecCSRestrictSymlinks | kSecCSRestrictToAppLike @@ -133,56 +133,6 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se code->staticValidate(flags, req); END_CSAPI_ERRORS -#else -#warning resolve before enabling SECTRUST_OSX: - OSStatus result = errSecSuccess; - const char *func = "SecStaticCodeCheckValidity"; - CFErrorRef localErrors = NULL; - if (!errors) { errors = &localErrors; } - try { - checkFlags(flags, - kSecCSReportProgress - | kSecCSCheckAllArchitectures - | kSecCSDoNotValidateExecutable - | kSecCSDoNotValidateResources - | kSecCSConsiderExpiration - | kSecCSEnforceRevocationChecks - | kSecCSNoNetworkAccess - | kSecCSCheckNestedCode - | kSecCSStrictValidate - | kSecCSCheckGatekeeperArchitectures - ); - - if (errors) - flags |= kSecCSFullReport; // internal-use flag - - 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); - } - catch (...) { - // the actual error being thrown is not being caught by any of the - // type-specific blocks contained in the END_CSAPI_ERRORS macro, - // so we only have the catch-all block here for now. - result = errSecCSInternalError; - } - - if (errors && *errors) { - CFShow(errors); - CFRelease(errors); - *errors = NULL; - } - if (result == errSecCSInternalError) { - #if !NDEBUG - Security::Syslog::error("WARNING: %s ignored error %d", func, (int)result); - #endif - result = errSecSuccess; - } - return result; - -#endif } @@ -323,3 +273,36 @@ OSStatus SecStaticCodeCancelValidation(SecStaticCodeRef codeRef, SecCSFlags flag END_CSAPI } + + +// +// Retrieve a component object for a special slot directly. +// +CFDataRef SecCodeCopyComponent(SecCodeRef codeRef, int slot, CFDataRef hash) +{ + BEGIN_CSAPI + + SecStaticCode* code = SecStaticCode::requiredStatic(codeRef); + return code->copyComponent(slot, hash); + + END_CSAPI1(NULL) +} + + +// +// Validate a single plain file's resource seal against a memory copy. +// This will fail for any other file type (symlink, directory, nested code, etc. etc.) +// +OSStatus SecCodeValidateFileResource(SecStaticCodeRef codeRef, CFStringRef relativePath, CFDataRef fileData, SecCSFlags flags) +{ + BEGIN_CSAPI + + checkFlags(0); + if (fileData == NULL) + MacOSError::throwMe(errSecCSObjectRequired); + SecStaticCode *code = SecStaticCode::requiredStatic(codeRef); + code->validatePlainMemoryResource(cfString(relativePath), fileData, flags); + + END_CSAPI + +} diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.h b/OSX/libsecurity_codesigning/lib/SecStaticCode.h index c8f9d40e..3e5a292d 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.h @@ -71,12 +71,42 @@ CFTypeID SecStaticCodeGetTypeID(void); may cause the bundle to be misconstrued. If you expect to submit such paths, first clean them with realpath(3) or equivalent. @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. - @param attributes A CFDictionary containing additional attributes of the code sought. @param staticCode On successful return, contains a reference to the StaticCode object representing the code at path. Unchanged on error. @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in CSCommon.h or certain other Security framework headers. +*/ +OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef * __nonnull CF_RETURNS_RETAINED staticCode); + +extern const CFStringRef kSecCodeAttributeArchitecture; +extern const CFStringRef kSecCodeAttributeSubarchitecture; +extern const CFStringRef kSecCodeAttributeUniversalFileOffset; +extern const CFStringRef kSecCodeAttributeBundleVersion; + +/*! + @function SecStaticCodeCreateWithPathAndAttributes + Given a path to a file system object, create a SecStaticCode object representing + the code at that location, if possible. Such a SecStaticCode is not inherently + linked to running code in the system. + It is possible to create a SecStaticCode object from an unsigned code object. + Most uses of such an object will return the errSecCSUnsigned error. However, + SecCodeCopyPath and SecCodeCopySigningInformation can be safely applied to such objects. + + @param path A path to a location in the file system. Only file:// URLs are + currently supported. For bundles, pass a URL to the root directory of the + bundle. For single files, pass a URL to the file. If you pass a URL to the + main executable of a bundle, the bundle as a whole will be generally recognized. + Caution: Paths containing embedded // or /../ within a bundle's directory + may cause the bundle to be misconstrued. If you expect to submit such paths, + first clean them with realpath(3) or equivalent. + @param flags Optional flags. Pass kSecCSDefaultFlags for standard behavior. + @param attributes A CFDictionary containing additional attributes of the code sought. + @param staticCode On successful return, contains a reference to the StaticCode object + representing the code at path. Unchanged on error. + @result Upon success, errSecSuccess. Upon error, an OSStatus value documented in + CSCommon.h or certain other Security framework headers. + @constant kSecCodeAttributeArchitecture Specifies the Mach-O architecture of code desired. This can be a CFString containing a canonical architecture name ("i386" etc.), or a CFNumber specifying an architecture numerically (see mach/machine.h). This key is ignored if the code @@ -88,13 +118,6 @@ CFTypeID SecStaticCodeGetTypeID(void); if the code is not in Mach-O form. @constant kSecCodeAttributeUniversalFileOffset The offset of a Mach-O specific slice of a universal Mach-O file. */ -extern const CFStringRef kSecCodeAttributeArchitecture; -extern const CFStringRef kSecCodeAttributeSubarchitecture; -extern const CFStringRef kSecCodeAttributeUniversalFileOffset; -extern const CFStringRef kSecCodeAttributeBundleVersion; - -OSStatus SecStaticCodeCreateWithPath(CFURLRef path, SecCSFlags flags, SecStaticCodeRef * __nonnull CF_RETURNS_RETAINED staticCode); - OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes, SecStaticCodeRef * __nonnull CF_RETURNS_RETAINED staticCode); @@ -152,6 +175,7 @@ CF_ENUM(uint32_t) { kSecCSCheckGatekeeperArchitectures = (1 << 6) | kSecCSCheckAllArchitectures, kSecCSRestrictSymlinks = 1 << 7, kSecCSRestrictToAppLike = 1 << 8, + kSecCSRestrictSidebandData = 1 << 9, }; OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, diff --git a/OSX/libsecurity_codesigning/lib/SecTask.c b/OSX/libsecurity_codesigning/lib/SecTask.c index c2b358e8..6639f459 100644 --- a/OSX/libsecurity_codesigning/lib/SecTask.c +++ b/OSX/libsecurity_codesigning/lib/SecTask.c @@ -217,9 +217,7 @@ static int SecTaskLoadEntitlements(SecTaskRef task, CFErrorRef *error) } if (errno != ERANGE) { // ERANGE means "your buffer is too small, it now tells you how much you need - // Everything else is a real error, so yell - syslog(LOG_NOTICE, "SecTaskLoadEntitlements failed error=%d", errno); // to ease diagnostics - // EINVAL is what the kernel says for unsigned code, so we'll have to let that pass + // EINVAL is what the kernel says for unsigned code AND broken code, so we'll have to let that pass if (errno == EINVAL) { task->entitlementsLoaded = true; return 0; @@ -314,3 +312,55 @@ Boolean SecTaskEntitlementsValidated(SecTaskRef task) { int rc = csops_task(task, CS_OPS_STATUS, &csflags, sizeof(csflags)); return rc != -1 && ((csflags & mask) == mask); } + +CFStringRef +SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error) +{ + CFStringRef signingId = NULL; + char *data = NULL; + struct csheader header; + uint32_t bufferlen; + int ret; + + ret = csops_task(task, CS_OPS_IDENTITY, &header, sizeof(header)); + if (ret != -1 || errno != ERANGE) + return NULL; + + bufferlen = ntohl(header.length); + /* check for insane values */ + if (bufferlen > 1024 * 1024 || bufferlen < 8) { + ret = EINVAL; + goto out; + } + data = malloc(bufferlen + 1); + if (data == NULL) { + ret = ENOMEM; + goto out; + } + ret = csops_task(task, CS_OPS_IDENTITY, data, bufferlen); + if (ret) { + ret = errno; + goto out; + } + data[bufferlen] = '\0'; + + signingId = CFStringCreateWithCString(NULL, data + 8, kCFStringEncodingUTF8); + +out: + if (data) + free(data); + if (ret && error) + *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ret, NULL); + + return signingId; +} + +uint32_t +SecTaskGetCodeSignStatus(SecTaskRef task) +{ + uint32_t flags = 0; + if (csops_task(task, CS_OPS_STATUS, &flags, sizeof(flags)) != 0) + return 0; + return flags; +} + diff --git a/OSX/libsecurity_codesigning/lib/SecTask.h b/OSX/libsecurity_codesigning/lib/SecTask.h index 90674a35..7ea6df93 100644 --- a/OSX/libsecurity_codesigning/lib/SecTask.h +++ b/OSX/libsecurity_codesigning/lib/SecTask.h @@ -103,6 +103,21 @@ CFTypeRef SecTaskCopyValueForEntitlement(SecTaskRef task, CFStringRef entitlemen __nullable CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef entitlements, CFErrorRef *error); + + +/*! + @function SecTaskCopySigningIdentifier + @abstract Return the value of the codesigning identifier. + @param task A previously created SecTask object + @param error On a NULL return, this will contain a CFError describing + the problem. This argument may be NULL if the caller is not interested in + detailed errors. The caller must CFRelease the returned value. + */ + +__nullable +CFStringRef +SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error); + CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_codesigning/lib/SecTaskPriv.h b/OSX/libsecurity_codesigning/lib/SecTaskPriv.h index 0190ee5b..8ab2469c 100644 --- a/OSX/libsecurity_codesigning/lib/SecTaskPriv.h +++ b/OSX/libsecurity_codesigning/lib/SecTaskPriv.h @@ -49,6 +49,16 @@ OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement) */ Boolean SecTaskEntitlementsValidated(SecTaskRef task); + +/*! + @function SecTaskGetCodeSignStatus + @abstract Get code signing flags + @param task A previously created SecTask object +*/ + +uint32_t +SecTaskGetCodeSignStatus(SecTaskRef task); + #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.cpp b/OSX/libsecurity_codesigning/lib/StaticCode.cpp index 0b993cc7..20c6d40a 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/StaticCode.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -378,11 +379,23 @@ const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) const { if (!mDir) { // pick our favorite CodeDirectory from the choices we've got - CodeDirectoryMap candidates; - if (loadCodeDirectories(candidates)) { - CodeDirectory::HashAlgorithm type = CodeDirectory::bestHashOf(mHashAlgorithms); - mDir = candidates[type]; // and the winner is... - candidates.swap(mCodeDirectories); + try { + CodeDirectoryMap candidates; + if (loadCodeDirectories(candidates)) { + CodeDirectory::HashAlgorithm type = CodeDirectory::bestHashOf(mHashAlgorithms); + mDir = candidates[type]; // and the winner is... + candidates.swap(mCodeDirectories); + } + } catch (...) { + if (check) + throw; + // We wanted a NON-checked peek and failed to safely decode the existing CodeDirectory. + // Pretend this is unsigned, but make sure we didn't somehow cache an invalid CodeDirectory. + if (mDir) { + assert(false); + Syslog::warning("code signing internal problem: mDir set despite exception exit"); + MacOSError::throwMe(errSecCSInternalError); + } } } if (mDir) @@ -400,6 +413,8 @@ const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) const bool SecStaticCode::loadCodeDirectories(CodeDirectoryMap& cdMap) const { __block CodeDirectoryMap candidates; + __block CodeDirectory::HashAlgorithms hashAlgorithms; + __block CFRef baseDir; auto add = ^bool (CodeDirectory::SpecialSlot slot){ CFRef cdData = diskRep()->component(slot); if (!cdData) @@ -410,10 +425,10 @@ bool SecStaticCode::loadCodeDirectories(CodeDirectoryMap& cdMap) const cd->checkIntegrity(); auto result = candidates.insert(make_pair(cd->hashType, cdData.get())); if (!result.second) - MacOSError::throwMe(errSecCSSignatureFailed); // duplicate hashType, go to heck - mHashAlgorithms.insert(cd->hashType); + MacOSError::throwMe(errSecCSSignatureInvalid); // duplicate hashType, go to heck + hashAlgorithms.insert(cd->hashType); if (slot == cdCodeDirectorySlot) - mBaseDir = cdData; + baseDir = cdData; return true; }; if (!add(cdCodeDirectorySlot)) @@ -423,7 +438,10 @@ bool SecStaticCode::loadCodeDirectories(CodeDirectoryMap& cdMap) const break; if (candidates.empty()) MacOSError::throwMe(errSecCSSignatureFailed); // no viable CodeDirectory in sight + // commit to cached values cdMap.swap(candidates); + mHashAlgorithms.swap(hashAlgorithms); + mBaseDir = baseDir; return true; } @@ -504,8 +522,9 @@ void SecStaticCode::validateDirectory() mValidationResult = err.osStatus(); throw; } catch (...) { - secdebug("staticCode", "%p validation threw non-common exception", this); + secinfo("staticCode", "%p validation threw non-common exception", this); mValidated = true; + Syslog::notice("code signing internal problem: unknown exception thrown by validation"); mValidationResult = errSecCSInternalError; throw; } @@ -613,11 +632,12 @@ bool SecStaticCode::verifySignature() MacOSError::check(CMSDecoderSetDetachedContent(cms, mBaseDir)); MacOSError::check(CMSDecoderFinalizeMessage(cms)); MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); - CFRef vf_policies = verificationPolicies(); - CFRef ts_policies = SecPolicyCreateAppleTimeStampingAndRevocationPolicies(vf_policies); - CMSSignerStatus status; - MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, - false, &status, &mTrust.aref(), NULL)); + CFRef vf_policies(verificationPolicies()); + CFRef ts_policies(SecPolicyCreateAppleTimeStampingAndRevocationPolicies(vf_policies)); + + CMSSignerStatus status; + MacOSError::check(CMSDecoderCopySignerStatus(cms, 0, vf_policies, + false, &status, &mTrust.aref(), NULL)); if (status != kCMSSignerValid) { const char *reason; @@ -633,7 +653,7 @@ bool SecStaticCode::verifySignature() reason, (int)status); MacOSError::throwMe(errSecCSSignatureFailed); } - + // retrieve auxiliary data bag and verify against current state CFRef hashBag; switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashBag.aref())) { @@ -678,13 +698,17 @@ bool SecStaticCode::verifySignature() if (mValidationFlags & kSecCSNoNetworkAccess) { MacOSError::check(SecTrustSetNetworkFetchAllowed(mTrust,false)); // no network? } +#if !SECTRUST_OSX MacOSError::check(SecTrustSetKeychains(mTrust, cfEmptyArray())); // no keychains - +#else + MacOSError::check(SecTrustSetKeychainsAllowed(mTrust, false)); +#endif + CSSM_APPLE_TP_ACTION_DATA actionData = { CSSM_APPLE_TP_ACTION_VERSION, // version of data structure 0 // action flags }; - + if (!(mValidationFlags & kSecCSCheckTrustedAnchors)) { /* no need to evaluate anchor trust when building cert chain */ MacOSError::check(SecTrustSetAnchorCertificates(mTrust, cfEmptyArray())); // no anchors @@ -713,12 +737,13 @@ bool SecStaticCode::verifySignature() CFRef teamIDFromCD = CFStringCreateWithCString(NULL, teamID(), kCFStringEncodingUTF8); if (!teamIDFromCD) { Security::Syslog::error("Could not get team identifier (%s)", teamID()); - MacOSError::throwMe(errSecCSInternalError); + 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(errSecCSSignatureInvalid); + 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); } } } @@ -784,6 +809,7 @@ bool SecStaticCode::verifySignature() // This may be a simple SecPolicyRef or a CFArray of policies. // The caller owns the return value. // +#if !SECTRUST_OSX static SecPolicyRef makeCRLPolicy() { CFRef policy; @@ -809,23 +835,35 @@ static SecPolicyRef makeOCSPPolicy() MacOSError::check(SecPolicySetValue(policy, &optData)); return policy.yield(); } +#else +static SecPolicyRef makeRevocationPolicy(CFOptionFlags flags) +{ + CFRef policy(SecPolicyCreateRevocation(flags)); + return policy.yield(); +} +#endif CFArrayRef SecStaticCode::verificationPolicies() { CFRef core; MacOSError::check(SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_CODE_SIGNING, &core.aref())); - if (mValidationFlags & kSecCSNoNetworkAccess) { - // Skips all revocation since they require network connectivity - // therefore annihilates kSecCSEnforceRevocationChecks if present - CFRef no_revoc = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); - return makeCFArray(2, core.get(), no_revoc.get()); - } + if (mValidationFlags & kSecCSNoNetworkAccess) { + // Skips all revocation since they require network connectivity + // therefore annihilates kSecCSEnforceRevocationChecks if present + CFRef no_revoc = makeRevocationPolicy(kSecRevocationNetworkAccessDisabled); + return makeCFArray(2, core.get(), no_revoc.get()); + } else if (mValidationFlags & kSecCSEnforceRevocationChecks) { - // Add CRL and OCSPPolicies + // Add CRL and OCSP policies +#if !SECTRUST_OSX CFRef crl = makeCRLPolicy(); CFRef ocsp = makeOCSPPolicy(); return makeCFArray(3, core.get(), crl.get(), ocsp.get()); +#else + CFRef revoc = makeRevocationPolicy(kSecRevocationUseAnyAvailableMethod); + return makeCFArray(2, core.get(), revoc.get()); +#endif } else { return makeCFArray(1, core.get()); } @@ -898,9 +936,10 @@ void SecStaticCode::validateExecutable() mExecutableValidResult = err.osStatus(); throw; } catch (...) { - secdebug("staticCode", "%p executable validation threw non-common exception", this); + secinfo("staticCode", "%p executable validation threw non-common exception", this); mExecutableValidated = true; mExecutableValidResult = errSecCSInternalError; + Syslog::notice("code signing internal problem: unknown exception thrown by validation"); throw; } } @@ -942,18 +981,11 @@ void SecStaticCode::validateResources(SecCSFlags flags) } try { - // sanity first - CFDictionaryRef sealedResources = resourceDictionary(); - if (this->resourceBase()) // disk has resources - if (sealedResources) - /* go to work below */; - else - MacOSError::throwMe(errSecCSResourcesNotFound); - else // disk has no resources - if (sealedResources) - MacOSError::throwMe(errSecCSResourcesNotFound); - else - return; // no resources, not sealed - fine (no work) + CFDictionaryRef rules; + CFDictionaryRef files; + uint32_t version; + if (!loadResources(rules, files, version)) + return; // validly no resources; nothing to do (ok) // found resources, and they are sealed DTRACK(CODESIGN_EVAL_STATIC_RESOURCES, this, @@ -962,22 +994,6 @@ void SecStaticCode::validateResources(SecCSFlags flags) // scan through the resources on disk, checking each against the resourceDirectory mResourcesValidContext = new CollectingContext(*this); // collect all failures in here - // use V2 resource seal if available, otherwise fall back to V1 - CFDictionaryRef rules; - CFDictionaryRef files; - uint32_t version; - if (CFDictionaryGetValue(sealedResources, CFSTR("files2"))) { // have V2 signature - rules = cfget(sealedResources, "rules2"); - files = cfget(sealedResources, "files2"); - version = 2; - } else { // only V1 available - rules = cfget(sealedResources, "rules"); - files = cfget(sealedResources, "files"); - version = 1; - } - if (!rules || !files) - MacOSError::throwMe(errSecCSResourcesInvalid); - // check for weak resource rules bool strict = flags & kSecCSStrictValidate; if (strict) { @@ -1014,7 +1030,7 @@ void SecStaticCode::validateResources(SecCSFlags flags) unsigned leftovers = unsigned(CFDictionaryGetCount(resourceMap)); if (leftovers > 0) { - secdebug("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); + secinfo("staticCode", "%d sealed resource(s) not found in code", int(leftovers)); CFDictionaryApplyFunction(resourceMap, SecStaticCode::checkOptionalResource, mResourcesValidContext); } @@ -1029,10 +1045,11 @@ void SecStaticCode::validateResources(SecCSFlags flags) mResourcesValidResult = err.osStatus(); throw; } catch (...) { - secdebug("staticCode", "%p executable validation threw non-common exception", this); + secinfo("staticCode", "%p executable validation threw non-common exception", this); mResourcesValidated = true; mResourcesDeep = flags & kSecCSCheckNestedCode; mResourcesValidResult = errSecCSInternalError; + Syslog::notice("code signing internal problem: unknown exception thrown by validation"); throw; } } @@ -1044,6 +1061,38 @@ void SecStaticCode::validateResources(SecCSFlags flags) } +bool SecStaticCode::loadResources(CFDictionaryRef& rules, CFDictionaryRef& files, uint32_t& version) +{ + // sanity first + CFDictionaryRef sealedResources = resourceDictionary(); + if (this->resourceBase()) { // disk has resources + if (sealedResources) + /* go to work below */; + else + MacOSError::throwMe(errSecCSResourcesNotFound); + } else { // disk has no resources + if (sealedResources) + MacOSError::throwMe(errSecCSResourcesNotFound); + else + return false; // no resources, not sealed - fine (no work) + } + + // use V2 resource seal if available, otherwise fall back to V1 + if (CFDictionaryGetValue(sealedResources, CFSTR("files2"))) { // have V2 signature + rules = cfget(sealedResources, "rules2"); + files = cfget(sealedResources, "files2"); + version = 2; + } else { // only V1 available + rules = cfget(sealedResources, "rules"); + files = cfget(sealedResources, "files"); + version = 1; + } + if (!rules || !files) + MacOSError::throwMe(errSecCSResourcesInvalid); + return true; +} + + void SecStaticCode::checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context) { ValidationContext *ctx = static_cast(context); @@ -1075,8 +1124,10 @@ bool SecStaticCode::hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t ver { // compute allowed omissions CFRef defaultOmissions = this->diskRep()->allowedResourceOmissions(); - if (!defaultOmissions) + if (!defaultOmissions) { + Syslog::notice("code signing internal problem: diskRep returned no allowedResourceOmissions"); MacOSError::throwMe(errSecCSInternalError); + } CFRef allowed = CFArrayCreateMutableCopy(NULL, 0, defaultOmissions); if (allowedOmissions) CFArrayAppendArray(allowed, allowedOmissions, CFRangeMake(0, CFArrayGetCount(allowedOmissions))); @@ -1109,7 +1160,7 @@ CFDictionaryRef SecStaticCode::infoDictionary() { if (!mInfoDict) { mInfoDict.take(getDictionary(cdInfoSlot, errSecCSInfoPlistFailed)); - secdebug("staticCode", "%p loaded InfoDict %p", this, mInfoDict.get()); + secinfo("staticCode", "%p loaded InfoDict %p", this, mInfoDict.get()); } return mInfoDict; } @@ -1123,7 +1174,7 @@ CFDictionaryRef SecStaticCode::entitlements() const EntitlementBlob *blob = reinterpret_cast(CFDataGetBytePtr(entitlementData)); if (blob->validateBlob()) { mEntitlements.take(blob->entitlements()); - secdebug("staticCode", "%p loaded Entitlements %p", this, mEntitlements.get()); + secinfo("staticCode", "%p loaded Entitlements %p", this, mEntitlements.get()); } // we do not consider a different blob type to be an error. We think it's a new format we don't understand } @@ -1137,13 +1188,31 @@ CFDictionaryRef SecStaticCode::resourceDictionary(bool check /* = true */) return mResourceDict; if (CFRef dict = getDictionary(cdResourceDirSlot, check)) if (cfscan(dict, "{rules=%Dn,files=%Dn}")) { - secdebug("staticCode", "%p loaded ResourceDict %p", + secinfo("staticCode", "%p loaded ResourceDict %p", this, mResourceDict.get()); return mResourceDict = dict; } // bad format return NULL; } + + +CFDataRef SecStaticCode::copyComponent(CodeDirectory::SpecialSlot slot, CFDataRef hash) +{ + const CodeDirectory* cd = this->codeDirectory(); + if (CFCopyRef component = this->component(slot)) { + if (hash) { + const void *slotHash = (*cd)[slot]; + if (cd->hashSize != CFDataGetLength(hash) || 0 != memcmp(slotHash, CFDataGetBytePtr(hash), cd->hashSize)) { + Syslog::notice("copyComponent hash mismatch slot %d length %d", slot, int(CFDataGetLength(hash))); + return NULL; // mismatch + } + } + return component.yield(); + } + return NULL; +} + // @@ -1181,64 +1250,25 @@ CFDictionaryRef SecStaticCode::getDictionary(CodeDirectory::SpecialSlot slot, bo return NULL; } - -// -// Load, validate, and return a sealed resource. -// The resource data (loaded in to memory as a blob) is returned and becomes -// the responsibility of the caller; it is NOT cached by SecStaticCode. // -// A resource that is not sealed will not be returned, and an error will be thrown. -// A missing resource will cause an error unless it's marked optional in the Directory. -// Under no circumstances will a corrupt resource be returned. -// NULL will only be returned for a resource that is neither sealed nor present -// (or that is sealed, absent, and marked optional). -// If the ResourceDictionary itself is not sealed, this function will always fail. // -// There is currently no interface for partial retrieval of the resource data. -// (Since the ResourceDirectory does not currently support segmentation, all the -// data would have to be read anyway, but it could be read into a reusable buffer.) // -CFDataRef SecStaticCode::resource(string path, ValidationContext &ctx) +CFDictionaryRef SecStaticCode::diskRepInformation() { - if (CFDictionaryRef rdict = resourceDictionary()) { - if (CFTypeRef file = cfget(rdict, "files.%s", path.c_str())) { - ResourceSeal seal(file); - if (!resourceBase()) // no resources in DiskRep - MacOSError::throwMe(errSecCSResourcesNotFound); - if (seal.nested()) - MacOSError::throwMe(errSecCSResourcesNotSealed); // (it's nested code) - CFRef fullpath = makeCFURL(path, false, resourceBase()); - if (CFRef data = cfLoadFile(fullpath)) { - MakeHash hasher(this->codeDirectory()); - hasher->update(CFDataGetBytePtr(data), CFDataGetLength(data)); - if (hasher->verify(seal.hash(hashAlgorithm()))) - return data.yield(); // good - else - ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // altered - } else { - if (!seal.optional()) - ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceMissing, fullpath); // was sealed but is now missing - else - return NULL; // validly missing - } - } else - ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAdded, CFTempURL(path, false, resourceBase())); - return NULL; - } else - MacOSError::throwMe(errSecCSResourcesNotSealed); + return mRep->diskRepInformation(); } -CFDataRef SecStaticCode::resource(string path) -{ - ValidationContext ctx(*this); - return resource(path, ctx); -} void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool isSymlink, ValidationContext &ctx, SecCSFlags flags, uint32_t version) { if (!resourceBase()) // no resources in DiskRep MacOSError::throwMe(errSecCSResourcesNotFound); CFRef fullpath = makeCFURL(path, false, resourceBase()); + if (version > 1 && ((flags & (kSecCSStrictValidate|kSecCSRestrictSidebandData)) == (kSecCSStrictValidate|kSecCSRestrictSidebandData))) { + AutoFileDesc fd(cfString(fullpath)); + if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME)) + ctx.reportProblem(errSecCSInvalidAssociatedFileData, kSecCFErrorResourceSideband, fullpath); + } if (CFTypeRef file = CFDictionaryGetValue(files, CFTempString(path))) { ResourceSeal seal(file); const ResourceSeal& rseal = seal; @@ -1283,6 +1313,24 @@ void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool is ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAdded, CFTempURL(path, false, resourceBase())); } +void SecStaticCode::validatePlainMemoryResource(string path, CFDataRef fileData, SecCSFlags flags) +{ + CFDictionaryRef rules; + CFDictionaryRef files; + uint32_t version; + if (!loadResources(rules, files, version)) + MacOSError::throwMe(errSecCSResourcesNotFound); // no resources sealed; this can't be right + if (CFTypeRef file = CFDictionaryGetValue(files, CFTempString(path))) { + ResourceSeal seal(file); + const Byte *sealHash = seal.hash(hashAlgorithm()); + if (sealHash) { + if (codeDirectory()->verifyMemoryContent(fileData, sealHash)) + return; // success + } + } + MacOSError::throwMe(errSecCSBadResource); +} + void SecStaticCode::validateSymlinkResource(std::string fullpath, std::string seal, ValidationContext &ctx, SecCSFlags flags) { static const char* const allowedDestinations[] = { @@ -1344,7 +1392,7 @@ void SecStaticCode::validateNestedCode(CFURLRef path, const ResourceSeal &seal, // recursively verify this nested code try { if (!(flags & kSecCSCheckNestedCode)) - flags |= kSecCSBasicValidateOnly; + flags |= kSecCSBasicValidateOnly | kSecCSQuickCheck; SecPointer code = new SecStaticCode(DiskRep::bestGuess(cfString(path))); code->initializeFromParent(*this); code->staticValidate(flags & ~kSecCSRestrictToAppLike, SecRequirement::required(req)); @@ -1397,10 +1445,7 @@ void SecStaticCode::validateOtherVersions(CFURLRef path, SecCSFlags flags, SecRe while ((entry = scanner.getNext()) != NULL) { std::ostringstream fullPath; - if (entry->d_type != DT_DIR || - strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0 || - strcmp(entry->d_name, "Current") == 0) + if (entry->d_type != DT_DIR || strcmp(entry->d_name, "Current") == 0) continue; fullPath << versionsPath.str() << entry->d_name; @@ -1532,9 +1577,6 @@ void SecStaticCode::validateRequirements(SecRequirementType type, SecStaticCode /* accept it */; } -/* Public Key Hash for root:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority */ -static const UInt8 retryRootBytes[] = {0x00,0xd8,0x5a,0x4c,0x25,0xc1,0x22,0xe5,0x8b,0x31,0xef,0x6d,0xba,0xf3,0xcc,0x5f,0x29,0xf1,0x0d,0x61}; - // // Validate this StaticCode against an external Requirement // @@ -1544,34 +1586,6 @@ bool SecStaticCode::satisfiesRequirement(const Requirement *req, OSStatus failur assert(req); validateDirectory(); result = req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(), codeDirectory()->identifier(), codeDirectory()), failure); - if (result == false) { - /* Fix for rdar://problem/21437632: Work around untrusted root in validation chain */ - CFArrayRef certs = certificates(); - if (!certs || ((int)CFArrayGetCount(certs) < 1)) { - return false; - } - SecCertificateRef root = cert((int)CFArrayGetCount(certs) - 1); - if (!root) { - return false; - } - CFDataRef rootHash = SecCertificateCopyPublicKeySHA1Digest(root); - if (!rootHash) { - return false; - } - - if ((CFDataGetLength(rootHash) == sizeof(retryRootBytes)) && - !memcmp(CFDataGetBytePtr(rootHash), retryRootBytes, sizeof(retryRootBytes))) { - // retry with a rebuilt certificate chain, this time evaluating anchor trust - Security::Syslog::debug("Requirements validation failed: retrying"); - mResourcesValidated = mValidated = false; - setValidationFlags(mValidationFlags | kSecCSCheckTrustedAnchors); - - validateDirectory(); - result = req->validates(Requirement::Context(mCertChain, infoDictionary(), entitlements(), codeDirectory()->identifier(), codeDirectory()), failure); - } - CFRelease(rootHash); - } - return result; } @@ -1712,14 +1726,17 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) // to reliably transmit through the API wall so that code outside the Security.framework // can use it without having to play nasty tricks to get it. // - if (flags & kSecCSInternalInformation) + if (flags & kSecCSInternalInformation) { try { if (mDir) CFDictionaryAddValue(dict, kSecCodeInfoCodeDirectory, mDir); CFDictionaryAddValue(dict, kSecCodeInfoCodeOffset, CFTempNumber(mRep->signingBase())); if (CFRef rdict = getDictionary(cdResourceDirSlot, false)) // suppress validation CFDictionaryAddValue(dict, kSecCodeInfoResourceDirectory, rdict); + if (CFRef ddict = diskRepInformation()) + CFDictionaryAddValue(dict, kSecCodeInfoDiskRepInfo, ddict); } catch (...) { } + } // @@ -1877,7 +1894,7 @@ void SecStaticCode::handleOtherArchitectures(void (^handle)(SecStaticCode* other for (Universal::Architectures::const_iterator arch = architectures.begin(); arch != architectures.end(); ++arch) { ctx.offset = fat->archOffset(*arch); if (ctx.offset > SIZE_MAX) - MacOSError::throwMe(errSecCSInternalError); + MacOSError::throwMe(errSecCSBadObjectFormat); ctx.size = fat->lengthOfSlice((size_t)ctx.offset); if (ctx.offset != activeOffset) { // inactive architecture; check it SecPointer subcode = new SecStaticCode(DiskRep::bestGuess(this->mainExecutablePath(), &ctx)); diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.h b/OSX/libsecurity_codesigning/lib/StaticCode.h index bb73341a..5f441e24 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.h +++ b/OSX/libsecurity_codesigning/lib/StaticCode.h @@ -136,13 +136,13 @@ public: std::string signatureSource(); virtual CFDataRef component(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); virtual CFDictionaryRef infoDictionary(); + CFDictionaryRef diskRepInformation(); CFDictionaryRef entitlements(); + CFDataRef copyComponent(CodeDirectory::SpecialSlot slot, CFDataRef hash); CFDictionaryRef resourceDictionary(bool check = true); CFURLRef resourceBase(); - CFDataRef resource(std::string path); - CFDataRef resource(std::string path, ValidationContext &ctx); void validateResource(CFDictionaryRef files, std::string path, bool isSymlink, ValidationContext &ctx, SecCSFlags flags, uint32_t version); void validateSymlinkResource(std::string fullpath, std::string seal, ValidationContext &ctx, SecCSFlags flags); @@ -177,6 +177,8 @@ public: void validateExecutable(); void validateNestedCode(CFURLRef path, const ResourceSeal &seal, SecCSFlags flags, bool isFramework); + void validatePlainMemoryResource(string path, CFDataRef fileData, SecCSFlags flags); + const Requirements *internalRequirements(); const Requirement *internalRequirement(SecRequirementType type); const Requirement *designatedRequirement(); @@ -193,7 +195,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 libraray validation + static bool isAppleDeveloperCert(CFArrayRef certs); // determines if this is an apple developer certificate for library validation public: void staticValidate(SecCSFlags flags, const SecRequirement *req); @@ -207,6 +209,9 @@ protected: CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary bool verifySignature(); CFArrayRef verificationPolicies(); + + // load preferred rules/files dictionaries (cached therein) + bool loadResources(CFDictionaryRef& rules, CFDictionaryRef& files, uint32_t& version); static void checkOptionalResource(CFTypeRef key, CFTypeRef value, void *context); bool hasWeakResourceRules(CFDictionaryRef rulesDict, uint32_t version, CFArrayRef allowedOmissions); diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp index 571c33e1..ca8f62da 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -47,7 +47,7 @@ static std::string findDistFile(const std::string &directory); // We make a CFBundleRef immediately, but everything else is lazy // BundleDiskRep::BundleDiskRep(const char *path, const Context *ctx) - : mBundle(CFBundleCreate(NULL, CFTempURL(path))) + : mBundle(_CFBundleCreateUnique(NULL, CFTempURL(path))) { if (!mBundle) MacOSError::throwMe(errSecCSBadBundleFormat); @@ -74,7 +74,7 @@ void BundleDiskRep::checkMoved(CFURLRef oldPath, CFURLRef newPath) // to their "Current" version binary in the main bundle if (realpath(cfString(oldPath).c_str(), cOld) == NULL || realpath(cfString(newPath).c_str(), cNew) == NULL) - MacOSError::throwMe(errSecCSInternalError); + MacOSError::throwMe(errSecCSAmbiguousBundleFormat); if (strcmp(cOld, cNew) != 0) recordStrictError(errSecCSAmbiguousBundleFormat); @@ -83,16 +83,19 @@ void BundleDiskRep::checkMoved(CFURLRef oldPath, CFURLRef newPath) // common construction code void BundleDiskRep::setup(const Context *ctx) { + mComponentsFromExecValid = false; // not yet known mInstallerPackage = false; // default mAppLike = false; // pessimism first bool appDisqualified = false; // found reason to disqualify as app - + // capture the path of the main executable before descending into a specific version CFRef mainExecBefore = CFBundleCopyExecutableURL(mBundle); CFRef infoPlistBefore = _CFBundleCopyInfoPlistURL(mBundle); // validate the bundle root; fish around for the desired framework version string root = cfStringRelease(copyCanonicalPath()); + if (filehasExtendedAttribute(root, XATTR_FINDERINFO_NAME)) + recordStrictError(errSecCSInvalidAssociatedFileData); string contents = root + "/Contents"; string supportFiles = root + "/Support Files"; string version = root + "/Versions/" @@ -111,7 +114,7 @@ void BundleDiskRep::setup(const Context *ctx) // treat like a shallow bundle; do not allow Versions arbitration appDisqualified = true; } else if (::access(version.c_str(), F_OK) == 0) { // versioned bundle - if (CFBundleRef versionBundle = CFBundleCreate(NULL, CFTempURL(version))) + if (CFBundleRef versionBundle = _CFBundleCreateUnique(NULL, CFTempURL(version))) mBundle.take(versionBundle); // replace top bundle ref else MacOSError::throwMe(errSecCSStaticCodeNotFound); @@ -145,8 +148,7 @@ void BundleDiskRep::setup(const Context *ctx) mMainExecutableURL = mainExec; mExecRep = DiskRep::bestFileGuess(this->mainExecutablePath(), ctx); - if (!mExecRep->fd().isPlainFile(this->mainExecutablePath())) - recordStrictError(errSecCSRegularFile); + checkPlainFile(mExecRep->fd(), this->mainExecutablePath()); CFDictionaryRef infoDict = CFBundleGetInfoDictionary(mBundle); bool isAppBundle = false; if (infoDict) @@ -169,8 +171,7 @@ void BundleDiskRep::setup(const Context *ctx) if (!mMainExecutableURL) MacOSError::throwMe(errSecCSBadBundleFormat); mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); - if (!mExecRep->fd().isPlainFile(this->mainExecutablePath())) - recordStrictError(errSecCSRegularFile); + checkPlainFile(mExecRep->fd(), this->mainExecutablePath()); mFormat = "widget bundle"; mAppLike = true; return; @@ -181,8 +182,7 @@ void BundleDiskRep::setup(const Context *ctx) // focus on the Info.plist (which we know exists) as the nominal "main executable" file mMainExecutableURL = infoURL; mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); - if (!mExecRep->fd().isPlainFile(this->mainExecutablePath())) - recordStrictError(errSecCSRegularFile); + checkPlainFile(mExecRep->fd(), this->mainExecutablePath()); if (packageVersion) { mInstallerPackage = true; mFormat = "installer package bundle"; @@ -197,8 +197,7 @@ void BundleDiskRep::setup(const Context *ctx) if (!distFile.empty()) { mMainExecutableURL = makeCFURL(distFile); mExecRep = new FileDiskRep(this->mainExecutablePath().c_str()); - if (!mExecRep->fd().isPlainFile(this->mainExecutablePath())) - recordStrictError(errSecCSRegularFile); + checkPlainFile(mExecRep->fd(), this->mainExecutablePath()); mInstallerPackage = true; mFormat = "installer package bundle"; return; @@ -244,27 +243,6 @@ static std::string findDistFile(const std::string &directory) } -// -// Create a path to a bundle signing resource, by name. -// If the BUNDLEDISKREP_DIRECTORY directory exists in the bundle's support directory, files -// will be read and written there. Otherwise, they go directly into the support directory. -// -string BundleDiskRep::metaPath(const char *name) -{ - if (mMetaPath.empty()) { - string support = cfStringRelease(CFBundleCopySupportFilesDirectoryURL(mBundle)); - mMetaPath = support + "/" BUNDLEDISKREP_DIRECTORY; - if (::access(mMetaPath.c_str(), F_OK) == 0) { - mMetaExists = true; - } else { - mMetaPath = support; - mMetaExists = false; - } - } - return mMetaPath + "/" + name; -} - - // // Try to create the meta-file directory in our bundle. // Does nothing if the directory already exists. @@ -272,7 +250,7 @@ string BundleDiskRep::metaPath(const char *name) // void BundleDiskRep::createMeta() { - string meta = metaPath(BUNDLEDISKREP_DIRECTORY); + string meta = metaPath(NULL); if (!mMetaExists) { if (::mkdir(meta.c_str(), 0755) == 0) { copyfile(cfStringRelease(copyCanonicalPath()).c_str(), meta.c_str(), NULL, COPYFILE_SECURITY); @@ -282,7 +260,40 @@ void BundleDiskRep::createMeta() UnixError::throwMe(); } } + + +// +// Create a path to a bundle signing resource, by name. +// This is in the BUNDLEDISKREP_DIRECTORY directory in the bundle's support directory. +// +string BundleDiskRep::metaPath(const char *name) +{ + if (mMetaPath.empty()) { + string support = cfStringRelease(CFBundleCopySupportFilesDirectoryURL(mBundle)); + mMetaPath = support + "/" BUNDLEDISKREP_DIRECTORY; + mMetaExists = ::access(mMetaPath.c_str(), F_OK) == 0; + } + if (name) + return mMetaPath + "/" + name; + else + return mMetaPath; +} + +CFDataRef BundleDiskRep::metaData(const char *name) +{ + return cfLoadFile(CFTempURL(metaPath(name))); +} +CFDataRef BundleDiskRep::metaData(CodeDirectory::SpecialSlot slot) +{ + if (const char *name = CodeDirectory::canonicalSlotName(slot)) + return metaData(name); + else + return NULL; +} + + + // // Load's a CFURL and makes sure that it is a regular file and not a symlink (or fifo, etc.) // @@ -296,14 +307,13 @@ CFDataRef BundleDiskRep::loadRegularFile(CFURLRef url) AutoFileDesc fd(path); - if (!fd.isPlainFile(path)) - recordStrictError(errSecCSRegularFile); + checkPlainFile(fd, path); data = cfLoadFile(fd, fd.fileSize()); if (!data) { - secdebug(__PRETTY_FUNCTION__, "failed to load %s", cfString(url).c_str()); - MacOSError::throwMe(errSecCSInternalError); + secinfo("bundlediskrep", "failed to load %s", cfString(url).c_str()); + MacOSError::throwMe(errSecCSInvalidSymlink); } return data; @@ -313,8 +323,10 @@ CFDataRef BundleDiskRep::loadRegularFile(CFURLRef url) // Load and return a component, by slot number. // Info.plist components come from the bundle, always (we don't look // for Mach-O embedded versions). +// ResourceDirectory always comes from bundle files. // Everything else comes from the embedded blobs of a Mach-O image, or from -// files located in the Contents directory of the bundle. +// files located in the Contents directory of the bundle; but we must be consistent +// (no half-and-half situations). // CFDataRef BundleDiskRep::component(CodeDirectory::SpecialSlot slot) { @@ -325,17 +337,36 @@ CFDataRef BundleDiskRep::component(CodeDirectory::SpecialSlot slot) return loadRegularFile(info); else return NULL; - // by default, we take components from the executable image or files - default: - if (CFDataRef data = mExecRep->component(slot)) - return data; - // falling through - // but the following always come from files case cdResourceDirSlot: - if (const char *name = CodeDirectory::canonicalSlotName(slot)) - return metaData(name); - else - return NULL; + mUsedComponents.insert(slot); + return metaData(slot); + // by default, we take components from the executable image or files (but not both) + default: + if (CFRef data = mExecRep->component(slot)) { + componentFromExec(true); + return data.yield(); + } + if (CFRef data = metaData(slot)) { + componentFromExec(false); + mUsedComponents.insert(slot); + return data.yield(); + } + return NULL; + } +} + + +// Check that all components of this BundleDiskRep come from either the main +// executable or the _CodeSignature directory (not mix-and-match). +void BundleDiskRep::componentFromExec(bool fromExec) +{ + if (!mComponentsFromExecValid) { + // first use; set latch + mComponentsFromExecValid = true; + mComponentsFromExec = fromExec; + } else if (mComponentsFromExec != fromExec) { + // subsequent use: check latch + MacOSError::throwMe(errSecCSSignatureFailed); } } @@ -451,6 +482,10 @@ void BundleDiskRep::flush() mExecRep->flush(); } +CFDictionaryRef BundleDiskRep::diskRepInformation() +{ + return mExecRep->diskRepInformation(); +} // // Defaults for signing operations @@ -531,6 +566,7 @@ CFDictionaryRef BundleDiskRep::defaultResourceRules(const SigningContext &ctx) "'^version.plist$' = #T" // include version.plist "%s = #T" // include Resources "%s = {optional=#T, weight=1000}" // make localizations optional + "%s = {weight=1010}" // ... except for Base.lproj which really isn't optional at all "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files "},rules2={" "'^.*' = #T" // include everything as a resource, with the following exceptions @@ -544,15 +580,18 @@ CFDictionaryRef BundleDiskRep::defaultResourceRules(const SigningContext &ctx) "'^PkgInfo$' = {omit=#T, weight=20}" // traditionally not included "%s = {weight=20}" // Resources override default nested (widgets) "%s = {optional=#T, weight=1000}" // make localizations optional + "%s = {weight=1010}" // ... except for Base.lproj which really isn't optional at all "%s = {omit=#T, weight=1100}" // exclude all locversion.plist files "}}", (string("^") + resources).c_str(), (string("^") + resources + ".*\\.lproj/").c_str(), + (string("^") + resources + "Base\\.lproj/").c_str(), (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str(), (string("^") + resources).c_str(), (string("^") + resources + ".*\\.lproj/").c_str(), + (string("^") + resources + "Base\\.lproj/").c_str(), (string("^") + resources + ".*\\.lproj/locversion.plist$").c_str() ); } @@ -588,6 +627,14 @@ size_t BundleDiskRep::pageSize(const SigningContext &ctx) // void BundleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { + // scan our metadirectory (_CodeSignature) for unwanted guests + if (!(flags & kSecCSQuickCheck)) + validateMetaDirectory(cd); + + // check accumulated strict errors and report them + if (!(flags & kSecCSRestrictSidebandData)) // tolerate resource forks etc. + mStrictErrors.erase(errSecCSInvalidAssociatedFileData); + std::vector fatalErrors; set_difference(mStrictErrors.begin(), mStrictErrors.end(), tolerated.begin(), tolerated.end(), back_inserter(fatalErrors)); if (!fatalErrors.empty()) @@ -609,6 +656,45 @@ void BundleDiskRep::recordStrictError(OSStatus error) } +void BundleDiskRep::validateMetaDirectory(const CodeDirectory* cd) +{ + // we know the resource directory will be checked after this call, so we'll give it a pass here + if (cd->slotIsPresent(-cdResourceDirSlot)) + mUsedComponents.insert(cdResourceDirSlot); + + // make a set of allowed (regular) filenames in this directory + std::set allowedFiles; + for (auto it = mUsedComponents.begin(); it != mUsedComponents.end(); ++it) { + switch (*it) { + case cdInfoSlot: + break; // always from Info.plist, not from here + default: + if (const char *name = CodeDirectory::canonicalSlotName(*it)) { + allowedFiles.insert(name); + } + break; + } + } + DirScanner scan(mMetaPath); + if (scan.initialized()) { + while (struct dirent* ent = scan.getNext()) { + if (!scan.isRegularFile(ent)) + MacOSError::throwMe(errSecCSUnsealedAppRoot); // only regular files allowed + if (allowedFiles.find(ent->d_name) == allowedFiles.end()) { // not in expected set of files + if (strcmp(ent->d_name, kSecCS_SIGNATUREFILE) == 0) { + // special case - might be empty and unused (adhoc signature) + AutoFileDesc fd(metaPath(kSecCS_SIGNATUREFILE)); + if (fd.fileSize() == 0) + continue; // that's okay, then + } + // not on list of needed files; it's a freeloading rogue! + recordStrictError(errSecCSUnsealedAppRoot); // funnel through strict set so GKOpaque can override it + } + } + } +} + + // // Check framework root for unsafe symlinks and unsealed content. // @@ -644,6 +730,23 @@ void BundleDiskRep::validateFrameworkRoot(string root) } } + +// +// Check a file descriptor for harmlessness. This is a strict check (only). +// +void BundleDiskRep::checkPlainFile(FileDesc fd, const std::string& path) +{ + if (!fd.isPlainFile(path)) + recordStrictError(errSecCSRegularFile); + checkForks(fd); +} + +void BundleDiskRep::checkForks(FileDesc fd) +{ + if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME)) + recordStrictError(errSecCSInvalidAssociatedFileData); +} + // // Writers @@ -679,6 +782,7 @@ void BundleDiskRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef string path = rep->metaPath(name); AutoFileDesc fd(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); fd.writeAll(CFDataGetBytePtr(data), CFDataGetLength(data)); + mWrittenFiles.insert(name); } else MacOSError::throwMe(errSecCSBadBundleFormat); } @@ -715,6 +819,24 @@ void BundleDiskRep::Writer::remove(CodeDirectory::SpecialSlot slot) void BundleDiskRep::Writer::flush() { execWriter->flush(); + purgeMetaDirectory(); +} + + +// purge _CodeSignature of all left-over files from any previous signature +void BundleDiskRep::Writer::purgeMetaDirectory() +{ + DirScanner scan(rep->mMetaPath); + if (scan.initialized()) { + while (struct dirent* ent = scan.getNext()) { + if (!scan.isRegularFile(ent)) + MacOSError::throwMe(errSecCSUnsealedAppRoot); // only regular files allowed + if (mWrittenFiles.find(ent->d_name) == mWrittenFiles.end()) { // we didn't write this! + scan.unlink(ent, 0); + } + } + } + } diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.h b/OSX/libsecurity_codesigning/lib/bundlediskrep.h index d0c5ee65..92269613 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.h @@ -68,7 +68,8 @@ public: CFArrayRef modifiedFiles(); UnixPlusPlus::FileDesc &fd(); void flush(); - + CFDictionaryRef diskRepInformation(); + std::string recommendedIdentifier(const SigningContext &ctx); CFDictionaryRef defaultResourceRules(const SigningContext &ctx); const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); @@ -86,16 +87,21 @@ public: protected: std::string metaPath(const char *name); - CFDataRef metaData(const char *name) { return cfLoadFile(CFTempURL(metaPath(name))); } void createMeta(); // (try to) create the meta-file directory + CFDataRef metaData(const char *name); + CFDataRef metaData(CodeDirectory::SpecialSlot slot); private: void setup(const Context *ctx); // shared init void checkModifiedFile(CFMutableArrayRef files, CodeDirectory::SpecialSlot slot); CFDataRef loadRegularFile(CFURLRef url); void recordStrictError(OSStatus error); + void validateMetaDirectory(const CodeDirectory* cd); void validateFrameworkRoot(std::string root); + void checkPlainFile(UnixPlusPlus::FileDesc fd, const std::string& path); + void checkForks(UnixPlusPlus::FileDesc fd); void checkMoved(CFURLRef oldPath, CFURLRef newPath); + void componentFromExec(bool fromExec); private: CFRef mBundle; @@ -106,6 +112,9 @@ private: bool mAppLike; // is some form of app string mFormat; // format description string RefPointer mExecRep; // DiskRep for main executable file + bool mComponentsFromExec; // components are drawn from main executable diskrep + bool mComponentsFromExecValid; // mComponentsFromExec is valid (tri-state) + std::set mUsedComponents; // remember what components we've retrieved std::set mStrictErrors; // strict validation errors encountered }; @@ -126,11 +135,13 @@ public: protected: DiskRep *execRep() { return rep->mExecRep; } void remove(CodeDirectory::SpecialSlot slot); + void purgeMetaDirectory(); protected: RefPointer rep; RefPointer execWriter; bool mMadeMetaDirectory; + std::set mWrittenFiles; }; diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.cpp b/OSX/libsecurity_codesigning/lib/codedirectory.cpp index f675c4b8..b14b58ec 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.cpp +++ b/OSX/libsecurity_codesigning/lib/codedirectory.cpp @@ -125,7 +125,7 @@ const char * const CodeDirectory::debugSlotName[] = { "info", "requirements", "resources", - "application", + "rep-specific", "entitlement" }; #endif //NDEBUG @@ -155,7 +155,7 @@ void CodeDirectory::checkIntegrity() const if (version < earliestVersion) MacOSError::throwMe(errSecCSSignatureUnsupported); // too old - can't support if (version > currentVersion) - secdebug("codedir", "%p version 0x%x newer than current 0x%x", + secinfo("codedir", "%p version 0x%x newer than current 0x%x", this, uint32_t(version), currentVersion); // now check interior offsets for validity @@ -199,7 +199,7 @@ void CodeDirectory::checkIntegrity() const // bool CodeDirectory::validateSlot(const void *data, size_t length, Slot slot) const { - secdebug("codedir", "%p validating slot %d", this, int(slot)); + secinfo("codedir", "%p validating slot %d", this, int(slot)); MakeHash hasher(this); Hashing::Byte digest[hasher->digestLength()]; generateHash(hasher, data, length, digest); @@ -309,6 +309,17 @@ void CodeDirectory::multipleHashFileData(FileDesc fd, size_t limit, CodeDirector action(*it, hashers[n]); } } + + + // + // Hash data in memory using our hashAlgorithm() + // +bool CodeDirectory::verifyMemoryContent(CFDataRef data, const Byte* digest) const +{ + RefPointer hasher = CodeDirectory::hashFor(this->hashType); + hasher->update(CFDataGetBytePtr(data), CFDataGetLength(data)); + return hasher->verify(digest); +} // diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.h b/OSX/libsecurity_codesigning/lib/codedirectory.h index 4b0bbbd9..381d6660 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.h +++ b/OSX/libsecurity_codesigning/lib/codedirectory.h @@ -271,7 +271,8 @@ public: CFDataRef cdhash() const; static void multipleHashFileData(UnixPlusPlus::FileDesc fd, size_t limit, HashAlgorithms types, void (^action)(HashAlgorithm type, DynamicHash* hasher)); - + bool verifyMemoryContent(CFDataRef data, const Byte* digest) const; + static bool viableHash(HashAlgorithm type); static HashAlgorithm bestHashOf(const HashAlgorithms& types); diff --git a/OSX/libsecurity_codesigning/lib/cs.h b/OSX/libsecurity_codesigning/lib/cs.h index 9e40ac8e..32f316f1 100644 --- a/OSX/libsecurity_codesigning/lib/cs.h +++ b/OSX/libsecurity_codesigning/lib/cs.h @@ -41,6 +41,7 @@ #include #include #include +#include namespace Security { @@ -92,7 +93,7 @@ OSStatus dbError(const SQLite3::Error &err); catch (const SQLite3::Error &err) { return dbError(err); } \ catch (const CommonError &err) { return SecKeychainErrFromOSStatus(err.osStatus()); } \ catch (const std::bad_alloc &) { return errSecAllocate; } \ - catch (...) { return errSecCSInternalError; } \ + catch (...) { Syslog::notice("unknown exception in CSAPI"); return errSecCSInternalError; } \ return errSecSuccess; #define END_CSAPI_ERRORS \ @@ -107,7 +108,7 @@ OSStatus dbError(const SQLite3::Error &err); catch (const SQLite3::Error &err) { return CSError::cfError(errors, dbError(err)); } \ catch (const CommonError &err) { return CSError::cfError(errors, SecKeychainErrFromOSStatus(err.osStatus())); } \ catch (const std::bad_alloc &) { return CSError::cfError(errors, errSecAllocate); } \ - catch (...) { return CSError::cfError(errors, errSecCSInternalError); } \ + catch (...) { Syslog::notice("unknown exception in CSAPI"); return CSError::cfError(errors, errSecCSInternalError); } \ return errSecSuccess; #define END_CSAPI1(bad) } catch (...) { return bad; } @@ -125,7 +126,7 @@ OSStatus dbError(const SQLite3::Error &err); catch (const SQLite3::Error &err) { CSError::cfError(errors, dbError(err)); } \ catch (const CommonError &err) { CSError::cfError(errors, SecKeychainErrFromOSStatus(err.osStatus())); } \ catch (const std::bad_alloc &) { CSError::cfError(errors, errSecAllocate); } \ - catch (...) { CSError::cfError(errors, errSecCSInternalError); } \ + catch (...) { Syslog::notice("unknown exception in CSAPI"); CSError::cfError(errors, errSecCSInternalError); } \ return bad; diff --git a/OSX/libsecurity_codesigning/lib/cskernel.cpp b/OSX/libsecurity_codesigning/lib/cskernel.cpp index 530fa722..c4d579f7 100644 --- a/OSX/libsecurity_codesigning/lib/cskernel.cpp +++ b/OSX/libsecurity_codesigning/lib/cskernel.cpp @@ -37,6 +37,8 @@ #include "machorep.h" #include #include +#include +#include #include // MAXPATHLEN namespace Security { @@ -67,33 +69,47 @@ KernelStaticCode::KernelStaticCode() // // Identify our guests (UNIX processes) by attribute. -// The only supported lookup attribute is currently the pid. (We could support -// task ports, but those can easily be mapped to pids.) +// We support either pid or audit token (which contains the pid). If we get both, +// we record them both and let the kernel sort them out. // Note that we don't actually validate the pid here; if it's invalid, we'll notice // when we try to ask the kernel about it later. // SecCode *KernelCode::locateGuest(CFDictionaryRef attributes) { - if (CFTypeRef attr = CFDictionaryGetValue(attributes, kSecGuestAttributePid)) { - RefPointer diskRep = NULL; - - if (CFGetTypeID(attr) != CFNumberGetTypeID()) - MacOSError::throwMe(errSecCSInvalidAttributeValues); - - pid_t pid = cfNumber(CFNumberRef(attr)); - - if (CFDictionaryGetValue(attributes, kSecGuestAttributeDynamicCode) != NULL) { - CFDataRef infoPlist = (CFDataRef)CFDictionaryGetValue(attributes, kSecGuestAttributeDynamicCodeInfoPlist); - if (infoPlist && CFGetTypeID(infoPlist) != CFDataGetTypeID()) - MacOSError::throwMe(errSecCSInvalidAttributeValues); - - try { - diskRep = new PidDiskRep(pid, infoPlist); - } catch (...) { } - } - return (new ProcessCode(cfNumber(CFNumberRef(attr)), diskRep))->retain(); - } else + CFNumberRef pidNumber = NULL; + CFDataRef auditData = NULL; + cfscan(attributes, "{%O=%NO}", kSecGuestAttributePid, &pidNumber); + cfscan(attributes, "{%O=%XO}", kSecGuestAttributeAudit, &auditData); + if (pidNumber == NULL && auditData == NULL) MacOSError::throwMe(errSecCSUnsupportedGuestAttributes); + + // Extract information from pid and audit token as presented. We need at least one. + // If both are specified, we pass them both to the kernel, which will fail if they + // don't agree. + if (auditData && CFDataGetLength(auditData) != sizeof(audit_token_t)) + MacOSError::throwMe(errSecCSInvalidAttributeValues); + pid_t pid = 0; + audit_token_t* audit = NULL; + if (pidNumber) + pid = cfNumber(pidNumber); + if (auditData) + audit = (audit_token_t*)CFDataGetBytePtr(auditData); + if (audit && pid == 0) + pid = audit_token_to_pid(*audit); + + // handle requests for server-based validation + RefPointer diskRep = NULL; + if (CFDictionaryGetValue(attributes, kSecGuestAttributeDynamicCode) != NULL) { + CFDataRef infoPlist = (CFDataRef)CFDictionaryGetValue(attributes, kSecGuestAttributeDynamicCodeInfoPlist); + if (infoPlist && CFGetTypeID(infoPlist) != CFDataGetTypeID()) + MacOSError::throwMe(errSecCSInvalidAttributeValues); + + try { + diskRep = new PidDiskRep(pid, infoPlist); + } catch (...) { } + } + + return (new ProcessCode(pid, audit, diskRep))->retain(); } @@ -109,9 +125,10 @@ SecStaticCode *KernelCode::identifyGuest(SecCode *iguest, CFDataRef *cdhash) if (guest->pidBased()) { SecPointer code = new ProcessDynamicCode(guest); + guest->pidBased()->setCredentials(code->codeDirectory()); SHA1::Digest kernelHash; - MacOSError::check(::csops(guest->pid(), CS_OPS_CDHASH, kernelHash, sizeof(kernelHash))); + MacOSError::check(guest->csops(CS_OPS_CDHASH, kernelHash, sizeof(kernelHash))); *cdhash = makeCFData(kernelHash, sizeof(kernelHash)); return code.yield(); @@ -125,7 +142,7 @@ SecStaticCode *KernelCode::identifyGuest(SecCode *iguest, CFDataRef *cdhash) CODESIGN_GUEST_IDENTIFY_PROCESS(guest, guest->pid(), code); if (cdhash) { SHA1::Digest kernelHash; - if (::csops(guest->pid(), CS_OPS_CDHASH, kernelHash, sizeof(kernelHash)) == -1) + if (guest->csops(CS_OPS_CDHASH, kernelHash, sizeof(kernelHash)) == -1) switch (errno) { case EBADEXEC: // means "no CodeDirectory hash for this program" *cdhash = NULL; @@ -155,7 +172,7 @@ SecCodeStatus KernelCode::getGuestStatus(SecCode *iguest) if (ProcessCode *guest = dynamic_cast(iguest)) { uint32_t pFlags; csops(guest, CS_OPS_STATUS, &pFlags); - secdebug("kcode", "guest %p(%d) kernel status 0x%x", guest, guest->pid(), pFlags); + secinfo("kcode", "guest %p(%d) kernel status 0x%x", guest, guest->pid(), pFlags); return pFlags; } else MacOSError::throwMe(errSecCSNoSuchCode); @@ -204,7 +221,7 @@ void KernelCode::identify() // void KernelCode::csops(ProcessCode *proc, unsigned int op, void *addr, size_t length) { - if (::csops(proc->pid(), op, addr, length) == -1) { + if (proc->csops(op, addr, length) == -1) { switch (errno) { case ESRCH: MacOSError::throwMe(errSecCSNoSuchCode); diff --git a/OSX/libsecurity_codesigning/lib/csprocess.cpp b/OSX/libsecurity_codesigning/lib/csprocess.cpp index bc406aa3..8e208c06 100644 --- a/OSX/libsecurity_codesigning/lib/csprocess.cpp +++ b/OSX/libsecurity_codesigning/lib/csprocess.cpp @@ -36,9 +36,13 @@ namespace CodeSigning { // // Construct a running process representation // -ProcessCode::ProcessCode(pid_t pid, PidDiskRep *pidDiskRep /*= NULL */) +ProcessCode::ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidDiskRep /*= NULL */) : GenericCode(KernelCode::active()), mPid(pid), mPidBased(pidDiskRep) { + if (token) + mAudit = new audit_token_t(*token); + else + mAudit = NULL; } @@ -46,6 +50,17 @@ mach_port_t ProcessCode::getHostingPort() { return SecurityServer::ClientSession().hostingPort(pid()); } + + +int ProcessCode::csops(unsigned int ops, void *addr, size_t size) +{ + // pass pid and audit token both if we have it, or just the pid if we don't + if (mAudit) + return ::csops_audittoken(mPid, ops, addr, size, mAudit); + else + return ::csops(mPid, ops, addr, size); +} + /* * diff --git a/OSX/libsecurity_codesigning/lib/csprocess.h b/OSX/libsecurity_codesigning/lib/csprocess.h index f98126bd..71ee505b 100644 --- a/OSX/libsecurity_codesigning/lib/csprocess.h +++ b/OSX/libsecurity_codesigning/lib/csprocess.h @@ -45,16 +45,21 @@ namespace CodeSigning { // class ProcessCode : public GenericCode { public: - ProcessCode(pid_t pid, PidDiskRep *pidDiskRep = NULL); - ~ProcessCode() throw () { } + ProcessCode(pid_t pid, const audit_token_t* token, PidDiskRep *pidDiskRep = NULL); + ~ProcessCode() throw () { delete mAudit; } pid_t pid() const { return mPid; } - PidDiskRep *pidBased() const { return mPidBased; } + const audit_token_t* audit() const { return mAudit; } + + PidDiskRep *pidBased() const { return mPidBased; } + + int csops(unsigned int ops, void *addr, size_t size); mach_port_t getHostingPort(); private: pid_t mPid; + audit_token_t* mAudit; RefPointer mPidBased; }; diff --git a/OSX/libsecurity_codesigning/lib/csutilities.h b/OSX/libsecurity_codesigning/lib/csutilities.h index 0cc63cb4..dcb0b130 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.h +++ b/OSX/libsecurity_codesigning/lib/csutilities.h @@ -153,7 +153,7 @@ private: class UidGuard { public: UidGuard() : mPrevious(-1) { } - UidGuard(uid_t uid) : mPrevious(-1) { seteuid(uid); } + UidGuard(uid_t uid) : mPrevious(-1) { (void)seteuid(uid); } ~UidGuard() { if (active()) diff --git a/OSX/libsecurity_codesigning/lib/dirscanner.cpp b/OSX/libsecurity_codesigning/lib/dirscanner.cpp index 0d16d74f..a0cb6361 100644 --- a/OSX/libsecurity_codesigning/lib/dirscanner.cpp +++ b/OSX/libsecurity_codesigning/lib/dirscanner.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "dirscanner.h" namespace Security { @@ -69,13 +70,41 @@ void DirScanner::initialize() struct dirent * DirScanner::getNext() { - return readdir(this->dp); + struct dirent* ent; + do { + int rc = readdir_r(this->dp, &this->entBuffer, &ent); + if (rc) + UnixError::throwMe(rc); + } while (ent && (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)); + return ent; } bool DirScanner::initialized() { return this->init; } + +void DirScanner::unlink(const struct dirent* ent, int flags) +{ + UnixError::check(::unlinkat(dirfd(this->dp), ent->d_name, flags)); +} + +bool DirScanner::isRegularFile(dirent* dp) +{ + switch (dp->d_type) { + case DT_REG: + return true; + default: + return false; + case DT_UNKNOWN: + { + struct stat st; + MacOSError::check(::stat((this->path + "/" + dp->d_name).c_str(), &st)); + return S_ISREG(st.st_mode); + } + } +} + DirValidator::~DirValidator() @@ -94,11 +123,11 @@ void DirValidator::validate(const string &root, OSStatus error) Rule *rule = NULL; switch (ent->fts_info) { case FTS_F: - secdebug("dirval", "file %s", ent->fts_path); + secinfo("dirval", "file %s", ent->fts_path); rule = match(relpath, file, executable); break; case FTS_SL: { - secdebug("dirval", "symlink %s", ent->fts_path); + secinfo("dirval", "symlink %s", ent->fts_path); char target[PATH_MAX]; ssize_t len = ::readlink(ent->fts_accpath, target, sizeof(target)-1); if (len < 0) @@ -108,7 +137,7 @@ void DirValidator::validate(const string &root, OSStatus error) break; } case FTS_D: - secdebug("dirval", "entering %s", ent->fts_path); + secinfo("dirval", "entering %s", ent->fts_path); if (ent->fts_level == FTS_ROOTLEVEL) continue; // skip root directory rule = match(relpath, directory, executable); @@ -116,10 +145,10 @@ void DirValidator::validate(const string &root, OSStatus error) fts_set(fts, ent, FTS_SKIP); // do not descend break; case FTS_DP: - secdebug("dirval", "leaving %s", ent->fts_path); + secinfo("dirval", "leaving %s", ent->fts_path); continue; default: - secdebug("dirval", "type %d (errno %d): %s", ent->fts_info, ent->fts_errno, ent->fts_path); + secinfo("dirval", "type %d (errno %d): %s", ent->fts_info, ent->fts_errno, ent->fts_path); MacOSError::throwMe(error); // not a file, symlink, or directory } if (!rule) @@ -128,7 +157,7 @@ void DirValidator::validate(const string &root, OSStatus error) reqMatched.insert(rule); } if (reqMatched.size() != mRequireCount) { - secdebug("dirval", "matched %d of %d required rules", reqMatched.size(), mRequireCount); + secinfo("dirval", "matched %lu of %d required rules", reqMatched.size(), mRequireCount); MacOSError::throwMe(error); // not all required rules were matched } } @@ -174,16 +203,20 @@ DirValidator::Rule::~Rule() bool DirValidator::Rule::matchTarget(const char *path, const char *target) const { - if (!mTargetBlock) + if (!mTargetBlock) { + Syslog::notice("code signing internal problem: !mTargetBlock"); MacOSError::throwMe(errSecCSInternalError); + } string pattern = mTargetBlock(path, target); if (pattern.empty()) return true; // always match empty pattern - secdebug("dirval", "%s: match target %s against %s", path, target, pattern.c_str()); + secinfo("dirval", "%s: match target %s against %s", path, target, pattern.c_str()); regex_t re; - if (::regcomp(&re, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) + if (::regcomp(&re, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) { + Syslog::notice("code signing internal problem: failed to compile internal RE"); MacOSError::throwMe(errSecCSInternalError); - int rv = ::regexec(&re, target, 0, NULL, 0); + } + int rv = ::regexec(&re, target, 0, NULL, 0); ::regfree(&re); switch (rv) { case 0: @@ -191,6 +224,7 @@ bool DirValidator::Rule::matchTarget(const char *path, const char *target) const case REG_NOMATCH: return false; default: + Syslog::notice("code signing internal error: regexec failed error=%d", rv); MacOSError::throwMe(errSecCSInternalError); } } diff --git a/OSX/libsecurity_codesigning/lib/dirscanner.h b/OSX/libsecurity_codesigning/lib/dirscanner.h index ddd5e56f..44d4d381 100644 --- a/OSX/libsecurity_codesigning/lib/dirscanner.h +++ b/OSX/libsecurity_codesigning/lib/dirscanner.h @@ -41,10 +41,14 @@ public: struct dirent *getNext(); // gets the next item out of this DirScanner bool initialized(); // returns false if the constructor failed to initialize the dirent + + void unlink(const struct dirent* ent, int flags); + bool isRegularFile(dirent* dp); private: string path; DIR *dp = NULL; + struct dirent entBuffer; void initialize(); bool init; }; diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp index 7bc89b48..a24b9e59 100644 --- a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp @@ -45,24 +45,6 @@ static const int32_t udifVersion = 4; // supported image file version // // Temporary hack to imply a fUDIFCryptosigFieldsset at the start of the "reserved" area of an UDIF header // -struct UDIFSigning { - uint64_t fCodeSignatureOffset; - uint64_t fCodeSignatureLength; -}; - -UDIFSigning& sigFields(UDIFFileHeader& header); -const UDIFSigning& sigFields(const UDIFFileHeader& header); - -UDIFSigning& sigFields(UDIFFileHeader& header) -{ - return *(UDIFSigning*)&header.fReserved; -} - -const UDIFSigning& sigFields(const UDIFFileHeader& header) -{ - return *(UDIFSigning*)&header.fReserved; -} - bool DiskImageRep::readHeader(FileDesc& fd, UDIFFileHeader& header) { // the UDIF "header" is in fact the last 512 bytes of the file, with no particular alignment @@ -100,12 +82,12 @@ void DiskImageRep::setup() UnixError::throwMe(errSecCSBadDiskImageFormat); mHeaderOffset = fd().fileSize() - sizeof(UDIFFileHeader); - size_t signatureOffset = size_t(n2h(sigFields(this->mHeader).fCodeSignatureOffset)); - size_t signatureLength = size_t(n2h(sigFields(this->mHeader).fCodeSignatureLength)); - sigFields(this->mHeader).fCodeSignatureLength = 0; // blind length (signature covers header) + size_t signatureOffset = size_t(n2h(this->mHeader.fUDIFCodeSignOffset)); + size_t signatureLength = size_t(n2h(this->mHeader.fUDIFCodeSignLength)); + this->mHeader.fUDIFCodeSignLength = 0; // blind length (signature covers header) if (signatureOffset == 0) { mEndOfDataOffset = mHeaderOffset; - sigFields(mHeader).fCodeSignatureOffset = h2n(mHeaderOffset); + mHeader.fUDIFCodeSignOffset = h2n(mHeaderOffset); return; // unsigned, header prepared for possible signing } else { mEndOfDataOffset = signatureOffset; @@ -114,7 +96,9 @@ void DiskImageRep::setup() // read the signature superblob const size_t frameLength = mHeaderOffset - signatureOffset; // room to following header if (EmbeddedSignatureBlob* blob = EmbeddedSignatureBlob::readBlob(fd(), signatureOffset, frameLength)) { - if (blob->length() != frameLength || frameLength != signatureLength) { + if (blob->length() != frameLength + || frameLength != signatureLength + || !blob->strictValidateBlob(frameLength)) { free(blob); MacOSError::throwMe(errSecCSBadDiskImageFormat); } @@ -237,9 +221,10 @@ void DiskImageRep::Writer::flush() // now (re)write disk image header after it UDIFFileHeader fullHeader = rep->mHeader; - sigFields(fullHeader).fCodeSignatureOffset = h2n(location); - sigFields(fullHeader).fCodeSignatureLength = h2n(mSigningData->length()); + fullHeader.fUDIFCodeSignOffset = h2n(location); + fullHeader.fUDIFCodeSignLength = h2n(mSigningData->length()); fd().writeAll(&fullHeader, sizeof(rep->mHeader)); + fd().truncate(fd().position()); } diff --git a/OSX/libsecurity_codesigning/lib/diskrep.cpp b/OSX/libsecurity_codesigning/lib/diskrep.cpp index 0501e377..7663919e 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskrep.cpp @@ -209,6 +209,10 @@ void DiskRep::flush() // nothing cached } +CFDictionaryRef DiskRep::diskRepInformation() +{ + return NULL; +} CFDictionaryRef DiskRep::defaultResourceRules(const SigningContext &) { diff --git a/OSX/libsecurity_codesigning/lib/diskrep.h b/OSX/libsecurity_codesigning/lib/diskrep.h index 21d2d5a8..78239ae9 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.h +++ b/OSX/libsecurity_codesigning/lib/diskrep.h @@ -74,6 +74,7 @@ public: virtual CFArrayRef modifiedFiles(); // list of files modified by signing [main execcutable only] virtual UnixPlusPlus::FileDesc &fd() = 0; // a cached file descriptor for main executable file virtual void flush(); // flush caches (refetch as needed) + virtual CFDictionaryRef diskRepInformation(); // information from diskrep // default values for signing operations virtual std::string recommendedIdentifier(const SigningContext &ctx) = 0; // default identifier diff --git a/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp b/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp index bb513fb3..e2c5cd42 100644 --- a/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp +++ b/OSX/libsecurity_codesigning/lib/evaluationmanager.cpp @@ -24,6 +24,8 @@ #include "evaluationmanager.h" #include "policyengine.h" #include +#include +#include #include #include #include @@ -34,8 +36,49 @@ namespace Security { namespace CodeSigning { +#pragma mark - + +static CFStringRef EvaluationTaskCreateKey(CFURLRef path, AuthorityType type) +{ + CFErrorRef errors = NULL; + + /* concatenate the type and the path before hashing */ + string pathString = std::to_string(type)+cfString(path); + CFRef data = makeCFData(pathString.c_str(), pathString.size()); + CFRef group = SecTransformCreateGroupTransform(); + CFRef sha1 = SecDigestTransformCreate(kSecDigestSHA2, 256, &errors); + if( errors ) + { + CFError::throwMe(); + } + + CFRef b64 = SecEncodeTransformCreate(kSecBase64Encoding, &errors); + if ( errors ) + { + CFError::throwMe(); + } + + SecTransformSetAttribute(sha1, kSecTransformInputAttributeName, data, &errors); + if ( errors ) + { + CFError::throwMe(); + } + + SecTransformConnectTransforms(sha1, kSecTransformOutputAttributeName, b64, kSecTransformInputAttributeName, group, &errors); + if ( errors ) + { + CFError::throwMe(); + } + + CFRef keyData = (CFDataRef)SecTransformExecute(group, &errors); + if ( errors ) + { + CFError::throwMe(); + } + return makeCFString(keyData); +} #pragma mark - EvaluationTask @@ -56,15 +99,21 @@ public: private: EvaluationTask(PolicyEngine *engine, CFURLRef path, AuthorityType type); virtual ~EvaluationTask(); + + // Tasks cannot be copied. + EvaluationTask(EvaluationTask const&) = delete; + EvaluationTask& operator=(EvaluationTask const&) = delete; + void performEvaluation(SecAssessmentFlags flags, CFDictionaryRef context); void waitForCompletion(SecAssessmentFlags flags, CFMutableDictionaryRef result); + void kick(); PolicyEngine *mPolicyEngine; AuthorityType mType; dispatch_queue_t mWorkQueue; dispatch_queue_t mFeedbackQueue; dispatch_semaphore_t mAssessmentLock; - __block dispatch_once_t mAssessmentKicked; + dispatch_once_t mAssessmentKicked; int32_t mReferenceCount; int32_t mEvalCount; // This whole thing is a pre-existing crutch and must be fixed soon. @@ -199,16 +248,14 @@ void EvaluationTask::performEvaluation(SecAssessmentFlags flags, CFDictionaryRef // This whole thing is a crutch and should be handled differently. // Maybe by having just one activity that just kicks off all remaining // background assessments, CTS determines that it's a good time. + + // Convert the evaluation path and type to a base64 encoded hash to use as a key + // Use that to generate an xpc_activity identifier. This identifier should be smaller + // than 128 characters due to rdar://problem/20094806 - // reduce the bundle path name to just the app component and generate an - // xpc_activity identifier from it. this identifier should be smaller than - // 128 characters due to rdar://problem/20094806 - string path = cfString(mPath); - size_t bundleNamePosition = path.rfind('/'); - const char *bundleName = "/default"; - if (bundleNamePosition != string::npos) - bundleName = path.c_str() + bundleNamePosition; - snprintf(mXpcActivityName, UNOFFICIAL_MAX_XPC_ID_LENGTH, "com.apple.security.assess%s", bundleName); + CFCopyRef cfKey(EvaluationTaskCreateKey(mPath, mType)); + string key = cfStringRelease(cfKey); + snprintf(mXpcActivityName, UNOFFICIAL_MAX_XPC_ID_LENGTH, "com.apple.security.assess/%s", key.c_str()); // schedule the assessment to be permitted to run (beyond start) -- this // will either happen once we're no longer on battery power, or @@ -222,9 +269,9 @@ void EvaluationTask::performEvaluation(SecAssessmentFlags flags, CFDictionaryRef xpc_dictionary_set_bool(criteria, XPC_ACTIVITY_ALLOW_BATTERY, false); xpc_activity_register(mXpcActivityName, criteria, ^(xpc_activity_t activity) { - dispatch_once(&mAssessmentKicked, ^{ - dispatch_semaphore_signal(mAssessmentLock); - }); + // We use the Evaluation Manager to get the task, as the task may be gone already + // (and with it, its mAssessmentKicked member). + EvaluationManager::globalManager()->kickTask(cfKey); }); xpc_release(criteria); } @@ -234,13 +281,15 @@ void EvaluationTask::performEvaluation(SecAssessmentFlags flags, CFDictionaryRef // with an existing task has been requested in the foreground, kick it // immediately. if (!lowPriority) { - dispatch_once(&mAssessmentKicked, ^{ - dispatch_semaphore_signal(mAssessmentLock); - }); + kick(); } } - +void EvaluationTask::kick() { + dispatch_once(&mAssessmentKicked, ^{ + dispatch_semaphore_signal(mAssessmentLock); + }); +} void EvaluationTask::waitForCompletion(SecAssessmentFlags flags, CFMutableDictionaryRef result) { @@ -319,15 +368,16 @@ EvaluationTask *EvaluationManager::evaluationTask(PolicyEngine *engine, CFURLRef __block EvaluationTask *evalTask = NULL; dispatch_sync(mListLockQueue, ^{ + CFRef key = EvaluationTaskCreateKey(path, type); // is path already being evaluated? if (!(flags & kSecAssessmentFlagIgnoreActiveAssessments)) - evalTask = (EvaluationTask *)CFDictionaryGetValue(mCurrentEvaluations.get(), path); + evalTask = (EvaluationTask *)CFDictionaryGetValue(mCurrentEvaluations.get(), key.get()); if (!evalTask) { // create a new task for the evaluation evalTask = new EvaluationTask(engine, path, type); if (flags & kSecAssessmentFlagIgnoreActiveAssessments) evalTask->setUnsharable(); - CFDictionaryAddValue(mCurrentEvaluations.get(), path, evalTask); + CFDictionaryAddValue(mCurrentEvaluations.get(), key.get(), evalTask); } evalTask->mReferenceCount++; }); @@ -354,16 +404,26 @@ void EvaluationManager::finalizeTask(EvaluationTask *task, SecAssessmentFlags fl void EvaluationManager::removeTask(EvaluationTask *task) { dispatch_sync(mListLockQueue, ^{ + CFRef key = EvaluationTaskCreateKey(task->path(), task->type()); // are we done with this evaluation task? if (--task->mReferenceCount == 0) { // yes -- remove it from our list and delete the object - CFDictionaryRemoveValue(mCurrentEvaluations.get(), task->path()); + CFDictionaryRemoveValue(mCurrentEvaluations.get(), key.get()); delete task; } }); } - +void EvaluationManager::kickTask(CFStringRef key) +{ + dispatch_sync(mListLockQueue, ^{ + EvaluationTask *evalTask = (EvaluationTask*)CFDictionaryGetValue(mCurrentEvaluations.get(), + key); + if (evalTask != NULL) { + evalTask->kick(); + } + }); +} } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/evaluationmanager.h b/OSX/libsecurity_codesigning/lib/evaluationmanager.h index 100fa2ea..beb46398 100644 --- a/OSX/libsecurity_codesigning/lib/evaluationmanager.h +++ b/OSX/libsecurity_codesigning/lib/evaluationmanager.h @@ -45,6 +45,8 @@ public: EvaluationTask *evaluationTask(PolicyEngine *engine, CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result); void finalizeTask(EvaluationTask *task, SecAssessmentFlags flags, CFMutableDictionaryRef result); + void kickTask(CFStringRef key); + private: CFCopyRef mCurrentEvaluations; diff --git a/OSX/libsecurity_codesigning/lib/filediskrep.cpp b/OSX/libsecurity_codesigning/lib/filediskrep.cpp index d0e294dc..e280fc13 100644 --- a/OSX/libsecurity_codesigning/lib/filediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/filediskrep.cpp @@ -110,7 +110,7 @@ const Requirements *FileDiskRep::defaultRequirements(const Architecture *, const buffer[length] = '\0'; char *cmd = buffer + 2; cmd[strcspn(cmd, " \t\n\r\f")] = '\0'; - secdebug("filediskrep", "looks like a script for %s", cmd); + secinfo("filediskrep", "looks like a script for %s", cmd); if (cmd[1]) try { // find path on disk, get designated requirement (if signed) @@ -125,7 +125,7 @@ const Requirements *FileDiskRep::defaultRequirements(const Architecture *, const return maker.make(); } } catch (...) { - secdebug("filediskrep", "exception getting host requirement (ignored)"); + secinfo("filediskrep", "exception getting host requirement (ignored)"); } } return NULL; @@ -137,7 +137,6 @@ string FileDiskRep::format() return "generic"; } - // // FileDiskRep::Writers // diff --git a/OSX/libsecurity_codesigning/lib/machorep.cpp b/OSX/libsecurity_codesigning/lib/machorep.cpp index de4b43a4..59a256b3 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.cpp +++ b/OSX/libsecurity_codesigning/lib/machorep.cpp @@ -27,6 +27,9 @@ #include "machorep.h" #include "StaticCode.h" #include "reqmaker.h" +#include +#include + namespace Security { @@ -105,7 +108,8 @@ Universal *MachORep::mainExecutableImage() void MachORep::prepareForSigning(SigningContext &context) { if (context.digestAlgorithms().empty()) { - MachO *macho = mainExecutableImage()->architecture(); + auto_ptr macho(mainExecutableImage()->architecture()); + if (const version_min_command *version = macho->findMinVersion()) { uint32_t limit = 0; switch (macho->flip(version->cmd)) { @@ -149,6 +153,12 @@ size_t MachORep::signingBase() { return mainExecutableImage()->archOffset(); } + +size_t MachORep::signingLimit() +{ + auto_ptr macho(mExecutable->architecture()); + return macho->signingExtent(); +} // @@ -223,11 +233,11 @@ CFDataRef MachORep::embeddedComponent(CodeDirectory::SpecialSlot slot) size_t offset = macho->flip(cs->dataoff); size_t length = macho->flip(cs->datasize); if ((mSigningData = EmbeddedSignatureBlob::readBlob(macho->fd(), macho->offset() + offset, length))) { - secdebug("machorep", "%zd signing bytes in %d blob(s) from %s(%s)", + secinfo("machorep", "%zd signing bytes in %d blob(s) from %s(%s)", mSigningData->length(), mSigningData->count(), mainExecutablePath().c_str(), macho->architecture().name()); } else { - secdebug("machorep", "failed to read signing bytes from %s(%s)", + secinfo("machorep", "failed to read signing bytes from %s(%s)", mainExecutablePath().c_str(), macho->architecture().name()); MacOSError::throwMe(errSecCSSignatureInvalid); } @@ -259,7 +269,7 @@ CFDataRef MachORep::infoPlist() } } } catch (...) { - secdebug("machorep", "exception reading embedded Info.plist"); + secinfo("machorep", "exception reading embedded Info.plist"); } return info.yield(); } @@ -306,6 +316,30 @@ void MachORep::flush() mExecutable = new Universal(fd(), offset, length); } +CFDictionaryRef MachORep::diskRepInformation() +{ + auto_ptr macho (mainExecutableImage()->architecture()); + CFRef info; + + if (const version_min_command *version = macho->findMinVersion()) { + + info.take(cfmake("{%O = %d,%O = %d,%O = %d}", + kSecCodeInfoDiskRepOSPlatform, macho->flip(version->cmd), + kSecCodeInfoDiskRepOSVersionMin, macho->flip(version->version), + kSecCodeInfoDiskRepOSSDKVersion, macho->flip(version->sdk))); + + if (macho->flip(version->cmd) == LC_VERSION_MIN_MACOSX && + macho->flip(version->sdk) < (10 << 16 | 9 << 8)) + { + info.take(cfmake("{+%O, %O = 'OS X SDK version before 10.9 does not support Library Validation'}", + info.get(), + kSecCodeInfoDiskRepNoLibraryValidation)); + } + } + + return info.yield(); +} + // // Return a recommended unique identifier. @@ -359,7 +393,7 @@ Requirement *MachORep::libraryRequirements(const Architecture *arch, const Signi size_t length = macho->flip(ldep->datasize); if (LibraryDependencyBlob *deplist = LibraryDependencyBlob::readBlob(macho->fd(), macho->offset() + offset, length)) { try { - secdebug("machorep", "%zd library dependency bytes in %d blob(s) from %s(%s)", + secinfo("machorep", "%zd library dependency bytes in %d blob(s) from %s(%s)", deplist->length(), deplist->count(), mainExecutablePath().c_str(), macho->architecture().name()); unsigned count = deplist->count(); @@ -378,13 +412,13 @@ Requirement *MachORep::libraryRequirements(const Architecture *arch, const Signi MacOSError::check(SecRequirementCopyData(areq, kSecCSDefaultFlags, &reqData.aref())); req = Requirement::specific((const BlobCore *)CFDataGetBytePtr(reqData)); } else { - secdebug("machorep", "unexpected blob type 0x%x in slot %d of binary dependencies", dep->magic(), n); + secinfo("machorep", "unexpected blob type 0x%x in slot %d of binary dependencies", dep->magic(), n); continue; } chain.add(); maker.copy(req); } else - secdebug("machorep", "missing DR info for library index %d", n); + secinfo("machorep", "missing DR info for library index %d", n); } ::free(deplist); } catch (...) { @@ -414,18 +448,11 @@ size_t MachORep::pageSize(const SigningContext &) // void MachORep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { - DiskRep::strictValidate(cd, tolerated, flags); + SingleDiskRep::strictValidate(cd, tolerated, flags); // if the constructor found suspicious issues, fail a struct validation now if (mExecutable->isSuspicious() && tolerated.find(errSecCSBadMainExecutable) == tolerated.end()) MacOSError::throwMe(errSecCSBadMainExecutable); - - // the signature's code extent must be what we would have picked (no funny hand editing) - if (cd) { - auto_ptr macho(mExecutable->architecture()); - if (cd->signingLimit() != macho->signingExtent()) - MacOSError::throwMe(errSecCSSignatureInvalid); - } } @@ -447,6 +474,7 @@ DiskRep::Writer *MachORep::writer() void MachORep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) { assert(false); + Syslog::notice("code signing internal error: trying to write Mach-O component directly"); MacOSError::throwMe(errSecCSInternalError); } diff --git a/OSX/libsecurity_codesigning/lib/machorep.h b/OSX/libsecurity_codesigning/lib/machorep.h index 214efb6a..7692fde1 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.h +++ b/OSX/libsecurity_codesigning/lib/machorep.h @@ -55,8 +55,10 @@ public: Universal *mainExecutableImage(); void prepareForSigning(SigningContext &context); size_t signingBase(); + size_t signingLimit(); std::string format(); - + CFDictionaryRef diskRepInformation(); + std::string recommendedIdentifier(const SigningContext &ctx); const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); size_t pageSize(const SigningContext &ctx); diff --git a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp index f3488088..3b54434a 100644 --- a/OSX/libsecurity_codesigning/lib/piddiskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/piddiskrep.cpp @@ -32,10 +32,23 @@ namespace Security { namespace CodeSigning { using namespace UnixPlusPlus; - + + +void +PidDiskRep::setCredentials(const Security::CodeSigning::CodeDirectory *cd) +{ + // save the Info.plist slot + if (cd->slotIsPresent(cdInfoSlot)) { + mInfoPlistHash.take(makeCFData((*cd)[cdInfoSlot], cd->hashSize)); + } +} + void PidDiskRep::fetchData(void) { + if (mDataFetched) // once + return; + xpc_connection_t conn = xpc_connection_create("com.apple.CodeSigningHelper", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); xpc_connection_set_event_handler(conn, ^(xpc_object_t object){ }); @@ -45,6 +58,7 @@ PidDiskRep::fetchData(void) assert(request != NULL); xpc_dictionary_set_string(request, "command", "fetchData"); xpc_dictionary_set_int64(request, "pid", mPid); + xpc_dictionary_set_data(request, "infohash", CFDataGetBytePtr(mInfoPlistHash), CFDataGetLength(mInfoPlistHash)); xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, request); if (reply && xpc_get_type(reply) == XPC_TYPE_DICTIONARY) { @@ -70,10 +84,13 @@ PidDiskRep::fetchData(void) if (!mBundleURL) MacOSError::throwMe(errSecCSNoSuchCode); + + mDataFetched = true; } PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) + : mDataFetched(false) { BlobCore header; CODESIGN_DISKREP_CREATE_KERNEL(this); @@ -81,7 +98,7 @@ PidDiskRep::PidDiskRep(pid_t pid, CFDataRef infoPlist) mPid = pid; mInfoPlist = infoPlist; - fetchData(); +// fetchData(); int rcent = ::csops(pid, CS_OPS_BLOB, &header, sizeof(header)); if (rcent == 0) @@ -112,17 +129,20 @@ PidDiskRep::~PidDiskRep() bool PidDiskRep::supportInfoPlist() { + fetchData(); return mInfoPlist; } CFDataRef PidDiskRep::component(CodeDirectory::SpecialSlot slot) { - if (slot == cdInfoSlot) - return mInfoPlist.retain(); + if (slot == cdInfoSlot) { + fetchData(); + return mInfoPlist.retain(); + } - EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob(); - return b->component(slot); + EmbeddedSignatureBlob *b = (EmbeddedSignatureBlob *)this->blob(); + return b->component(slot); } CFDataRef PidDiskRep::identification() @@ -133,7 +153,8 @@ CFDataRef PidDiskRep::identification() CFURLRef PidDiskRep::copyCanonicalPath() { - return mBundleURL.retain(); + fetchData(); + return mBundleURL.retain(); } string PidDiskRep::recommendedIdentifier(const SigningContext &) diff --git a/OSX/libsecurity_codesigning/lib/piddiskrep.h b/OSX/libsecurity_codesigning/lib/piddiskrep.h index fc1e3249..fddb34cf 100644 --- a/OSX/libsecurity_codesigning/lib/piddiskrep.h +++ b/OSX/libsecurity_codesigning/lib/piddiskrep.h @@ -50,17 +50,22 @@ public: size_t signingLimit(); std::string format(); UnixPlusPlus::FileDesc &fd(); - + std::string recommendedIdentifier(const SigningContext &ctx); bool supportInfoPlist(); + + void setCredentials(const CodeDirectory* cd); + private: const BlobCore *blob() { return (const BlobCore *)mBuffer; } void fetchData(void); pid_t mPid; uint8_t *mBuffer; + CFRef mInfoPlistHash; CFRef mInfoPlist; CFRef mBundleURL; + bool mDataFetched; }; diff --git a/OSX/libsecurity_codesigning/lib/policydb.cpp b/OSX/libsecurity_codesigning/lib/policydb.cpp index af49aa9e..94d1bbc8 100644 --- a/OSX/libsecurity_codesigning/lib/policydb.cpp +++ b/OSX/libsecurity_codesigning/lib/policydb.cpp @@ -282,6 +282,10 @@ void PolicyDatabase::upgradeDatabase() "INSERT INTO authority (type, allow, flags, label, requirement) VALUES (3, 1, 2, 'Developer ID', 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and certificate leaf[field.1.2.840.113635.100.6.1.13] exists')"); addDevID.execute(); }); + + simpleFeature("root_only", ^{ + UnixError::check(::chmod(dbPath(), S_IRUSR | S_IWUSR)); + }); } @@ -303,7 +307,7 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil CFDictionaryRef content = auth.get(CFSTR("authority")); std::string authUUID = cfString(auth.get(CFSTR("uuid"))); if (authUUID.empty()) { - secdebug("gkupgrade", "no uuid in auth file; ignoring gke.auth"); + secinfo("gkupgrade", "no uuid in auth file; ignoring gke.auth"); return; } std::string dbUUID; @@ -311,7 +315,7 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil if (uuidQuery.nextRow()) dbUUID = (const char *)uuidQuery[0]; if (dbUUID == authUUID) { - secdebug("gkupgrade", "gke.auth already present, ignoring"); + secinfo("gkupgrade", "gke.auth already present, ignoring"); return; } Syslog::notice("loading GKE %s (replacing %s)", authUUID.c_str(), dbUUID.empty() ? "nothing" : dbUUID.c_str()); @@ -325,7 +329,7 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil db.storeCode(blob, ""); count++; } - secdebug("gkupgrade", "%d detached signature(s) loaded from override data", count); + secinfo("gkupgrade", "%d detached signature(s) loaded from override data", count); fclose(sigs); } @@ -350,8 +354,12 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil uint32_t flags = kAuthorityFlagWhitelist; if (CFNumberRef versionRef = info.get("version")) { int version = cfNumber(versionRef); - if (version >= 2) + if (version >= 2) { flags |= kAuthorityFlagWhitelistV2; + if (version >= 3) { + flags |= kAuthorityFlagWhitelistSHA256; + } + } } insert.reset(); insert.bind(":type") = cfString(info.get(CFSTR("type"))); @@ -368,9 +376,25 @@ void PolicyDatabase::installExplicitSet(const char *authfile, const char *sigfil // update version and commit addFeature("gke", authUUID.c_str(), "gke loaded"); loadAuth.commit(); + /* now that we have moved to a bundle for gke files, delete any old style files we find + This is really just a best effort cleanup, so we don't care about errors. */ + if (access(gkeAuthFile_old, F_OK) == 0) + { + if (unlink(gkeAuthFile_old) == 0) + { + Syslog::notice("Deleted old style gke file (%s)", gkeAuthFile_old); + } + } + if (access(gkeSigsFile_old, F_OK) == 0) + { + if (unlink(gkeSigsFile_old) == 0) + { + Syslog::notice("Deleted old style gke file (%s)", gkeSigsFile_old); + } + } } } catch (...) { - secdebug("gkupgrade", "exception during GKE upgrade"); + secinfo("gkupgrade", "exception during GKE upgrade"); } } diff --git a/OSX/libsecurity_codesigning/lib/policydb.h b/OSX/libsecurity_codesigning/lib/policydb.h index 65dded83..a4c58920 100644 --- a/OSX/libsecurity_codesigning/lib/policydb.h +++ b/OSX/libsecurity_codesigning/lib/policydb.h @@ -43,8 +43,11 @@ static const char lastRejectFile[] = "/var/db/.LastGKReject"; static const char lastApprovedFile[] = "/var/db/.LastGKApp"; static const char rearmTimerFile[] = "/var/db/.GKRearmTimer"; -static const char gkeAuthFile[] = "/var/db/gke.auth"; -static const char gkeSigsFile[] = "/var/db/gke.sigs"; +static const char gkeAuthFile_old[] = "/var/db/gke.auth"; +static const char gkeSigsFile_old[] = "/var/db/gke.sigs"; +static const char gkeAuthFile[] = "/var/db/gke.bundle/Contents/Resources/gke.auth"; +static const char gkeSigsFile[] = "/var/db/gke.bundle/Contents/Resources/gke.sigs"; + static const unsigned int gkeCheckInterval = 60; // seconds diff --git a/OSX/libsecurity_codesigning/lib/policyengine.cpp b/OSX/libsecurity_codesigning/lib/policyengine.cpp index 3f49aebd..f9fc17ed 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.cpp +++ b/OSX/libsecurity_codesigning/lib/policyengine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -100,6 +100,15 @@ void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlag } +// +// Create GKE whitelist filter screens. +// These are strings that are used to determine quickly whether unsigned code may +// have a GKE-style whitelist entry in the authority database. The idea is to make +// up a decent hash quickly. +// +// Note: We continue to use SHA1 here for compatibility of existing GKE entries. +// These are a prescreen, backed up by code signature checks later on. Use of SHA1 here is not a security problem. +// static std::string createWhitelistScreen(char type, const Byte *digest, size_t length) { char buffer[2*length + 2]; @@ -109,6 +118,38 @@ static std::string createWhitelistScreen(char type, const Byte *digest, size_t l return buffer; } +static std::string createWhitelistScreen(SecStaticCodeRef code) +{ + DiskRep *rep = SecStaticCode::requiredStatic(code)->diskRep(); + std::string screen; + if (CFRef info = rep->component(cdInfoSlot)) { + // has an Info.plist - hash it + SHA1 hash; + hash.update(CFDataGetBytePtr(info), CFDataGetLength(info)); + SHA1::Digest digest; + hash.finish(digest); + return createWhitelistScreen('I', digest, sizeof(digest)); + } else if (CFRef repSpecific = rep->component(cdRepSpecificSlot)) { + // has a rep-specific slot - hash that (this catches disk images cheaply) + // got invented after SHA-1 deprecation, so we'll use SHA256, which is the new default + CCHashInstance hash(kCCDigestSHA256); + hash.update(CFDataGetBytePtr(repSpecific), CFDataGetLength(repSpecific)); + Byte digest[256/8]; + hash.finish(digest); + return createWhitelistScreen('R', digest, sizeof(digest)); + } else if (rep->mainExecutableImage()) { + // stand-alone Mach-O executables are always candidates + return "N"; + } else { + // if everything else fails, hash the (single) file + SHA1 hash; + hashFileData(rep->mainExecutablePath().c_str(), &hash); + SHA1::Digest digest; + hash.finish(digest); + return createWhitelistScreen('M', digest, sizeof(digest)); + } +} + void PolicyEngine::evaluateCodeItem(SecStaticCodeRef code, CFURLRef path, AuthorityType type, SecAssessmentFlags flags, bool nested, CFMutableDictionaryRef result) { @@ -154,7 +195,7 @@ void PolicyEngine::evaluateCodeItem(SecStaticCodeRef code, CFURLRef path, Author } // current rule is first rule (in priority order) that matched. Apply it - if (nested) // success, nothing to record + if (nested && allow) // success, nothing to record return; CFRef info; // as needed @@ -194,7 +235,7 @@ void PolicyEngine::evaluateCodeItem(SecStaticCodeRef code, CFURLRef path, Author } } cfadd(result, "{%O=%B}", kSecAssessmentAssessmentVerdict, allow); - addAuthority(flags, result, label, id); + addAuthority(flags, result, label, id, NULL, false, ruleFlags); return; } @@ -229,30 +270,7 @@ void PolicyEngine::adjustValidation(SecStaticCodeRef code) bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, CFURLRef path, SecAssessmentFlags matchFlags) { if (matchFlags == 0) { // playback; consult authority table for matches - DiskRep *rep = SecStaticCode::requiredStatic(code)->diskRep(); - std::string screen; - if (CFRef info = rep->component(cdInfoSlot)) { - SHA1 hash; - hash.update(CFDataGetBytePtr(info), CFDataGetLength(info)); - SHA1::Digest digest; - hash.finish(digest); - screen = createWhitelistScreen('I', digest, sizeof(digest)); - } else if (CFRef repSpecific = rep->component(cdRepSpecificSlot)) { - // got invented after SHA-1 deprecation, so we'll use SHA256, which is the new default - CCHashInstance hash(kCCDigestSHA256); - hash.update(CFDataGetBytePtr(repSpecific), CFDataGetLength(repSpecific)); - Byte digest[256/8]; - hash.finish(digest); - screen = createWhitelistScreen('R', digest, sizeof(digest)); - } else if (rep->mainExecutableImage()) { - screen = "N"; - } else { - SHA1 hash; - hashFileData(rep->mainExecutablePath().c_str(), &hash); - SHA1::Digest digest; - hash.finish(digest); - screen = createWhitelistScreen('M', digest, sizeof(digest)); - } + std::string screen = createWhitelistScreen(code); SQLite::Statement query(*this, "SELECT flags FROM authority " "WHERE type = :type" @@ -272,6 +290,9 @@ bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, C CFRef signature = CFDataCreateMutable(NULL, 0); CFTemp arguments("{%O=%O, %O=#N, %O=%d}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity, kSecCodeSignerDigestAlgorithm, (matchFlags & kAuthorityFlagWhitelistSHA256) ? kSecCodeSignatureHashSHA256 : kSecCodeSignatureHashSHA1); + // for modern whitelist entries, neuter the identifier since it may be derived from the filename + if (matchFlags & kAuthorityFlagWhitelistSHA256) + CFDictionaryAddValue(arguments, kSecCodeSignerIdentifier, CFSTR("ADHOC")); CFRef signer; MacOSError::check(SecCodeSignerCreate(arguments, (matchFlags & kAuthorityFlagWhitelistV2) ? kSecCSSignOpaque : kSecCSSignV1, &signer.aref())); MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); @@ -318,9 +339,11 @@ bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, C void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result, bool handleUnsigned) { // not really a Gatekeeper function... but reject all "hard quarantined" files because they were made from sandboxed sources without download privilege - FileQuarantine qtn(cfString(path).c_str()); - if (qtn.flag(QTN_FLAG_HARD)) - MacOSError::throwMe(errSecCSFileHardQuarantined); + if (type == kAuthorityExecute) { + FileQuarantine qtn(cfString(path).c_str()); + if (qtn.flag(QTN_FLAG_HARD)) + MacOSError::throwMe(errSecCSFileHardQuarantined); + } // hack: if caller passed a UTI, use that to turn off app-only checks for some well-known ones bool appOk = false; @@ -354,8 +377,10 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment } // ad-hoc sign unsigned code + bool wasAdhocSigned = false; if (rc == errSecCSUnsigned && handleUnsigned && (!overrideAssessment(flags) || SYSPOLICY_RECORDER_MODE_ENABLED())) { if (temporarySigning(code, type, path, 0)) { + wasAdhocSigned = true; rc = errSecSuccess; // clear unsigned; we are now well-signed validationFlags |= kSecCSBasicValidateOnly; // no need to re-validate deep contents } @@ -363,6 +388,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment // prepare for deep traversal of (hopefully) good signatures SecAssessmentFeedback feedback = SecAssessmentFeedback(CFDictionaryGetValue(context, kSecAssessmentContextKeyFeedback)); + __block CFRef nestedFailure = NULL; // save a nested failure for later MacOSError::check(SecStaticCodeSetCallback(code, kSecCSDefaultFlags, NULL, ^CFTypeRef (SecStaticCodeRef item, CFStringRef cfStage, CFDictionaryRef info) { string stage = cfString(cfStage); if (stage == "prepared") { @@ -378,8 +404,15 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment SecStaticCodeSetCallback(item, kSecCSDefaultFlags, NULL, NULL); // clear callback to avoid unwanted recursion evaluateCodeItem(item, path, type, flags, item != code, result); if (CFTypeRef verdict = CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict)) - if (CFEqual(verdict, kCFBooleanFalse)) - return makeCFNumber(OSStatus(errSecCSVetoed)); // (signal nested-code policy failure, picked up below) + if (CFEqual(verdict, kCFBooleanFalse)) { + if (item == code) + return makeCFNumber(OSStatus(errSecCSVetoed)); // (signal nested-code policy failure, picked up below) + // nested code policy failure; save, reset, and continue + if (!nestedFailure) + nestedFailure = CFMutableDictionaryRef(CFDictionaryGetValue(result, kSecAssessmentAssessmentAuthority)); + CFDictionaryRemoveValue(result, kSecAssessmentAssessmentAuthority); + CFDictionaryRemoveValue(result, kSecAssessmentAssessmentVerdict); + } } return NULL; })); @@ -396,6 +429,8 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment addAuthority(flags, result, "no usable signature"); return; case errSecCSVetoed: // nested code rejected by rule book; result was filled out there + if (wasAdhocSigned) + addToAuthority(result, kSecAssessmentAssessmentSource, CFSTR("no usable signature")); // ad-hoc signature proved useless return; case errSecCSWeakResourceRules: case errSecCSWeakResourceEnvelope: @@ -437,6 +472,17 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment default: MacOSError::throwMe(rc); } + + if (nestedFailure && CFEqual(CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict), kCFBooleanTrue)) { + // structure intact, top level approved, nested code failed policy + CFMutableDictionaryRef authority = CFMutableDictionaryRef(CFDictionaryGetValue(result, kSecAssessmentAssessmentAuthority)); + uint64_t ruleFlags = cfNumber(CFNumberRef(CFDictionaryGetValue(authority, kSecAssessmentAssessmentAuthorityFlags))); + if (ruleFlags & kAuthorityFlagDefault) { + // default rule requires positive match at each nested code - reinstate failure + CFDictionaryReplaceValue(result, kSecAssessmentAssessmentVerdict, kCFBooleanFalse); + CFDictionaryReplaceValue(result, kSecAssessmentAssessmentAuthority, nestedFailure); + } + } } @@ -570,6 +616,7 @@ void PolicyEngine::evaluateInstall(CFURLRef path, SecAssessmentFlags flags, CFDi // // Create a suitable policy array for verification of installer signatures. // +#if !SECTRUST_OSX static SecPolicyRef makeCRLPolicy() { CFRef policy; @@ -595,13 +642,24 @@ static SecPolicyRef makeOCSPPolicy() MacOSError::check(SecPolicySetValue(policy, &optData)); return policy.yield(); } +#else +static SecPolicyRef makeRevocationPolicy() +{ + CFRef policy(SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod)); + return policy.yield(); +} +#endif static CFTypeRef installerPolicy() { CFRef base = SecPolicyCreateBasicX509(); +#if !SECTRUST_OSX CFRef crl = makeCRLPolicy(); CFRef ocsp = makeOCSPPolicy(); - return makeCFArray(3, base.get(), crl.get(), ocsp.get()); +#else + CFRef revoc = makeRevocationPolicy(); +#endif + return makeCFArray(2, base.get(), revoc.get()); } @@ -612,8 +670,21 @@ static CFTypeRef installerPolicy() void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) { if (context) { + FileQuarantine qtn(cfString(path).c_str()); + if (CFDictionaryGetValue(context, kSecAssessmentContextKeyPrimarySignature) == kCFBooleanTrue) { + // Client requests that we focus on the code signature on this document and report on that. + // On this path, we care about the (code) signature on the document, not its risk assessment, + // and any exception is reported as a primary error. + if (qtn.flag(QTN_FLAG_ASSESSMENT_OK)) { + // previously added by user - hacked to say no/no usable signature to trigger proper DMG processing in XProtect + cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict); + addAuthority(flags, result, "no usable signature"); + return; + } + evaluateCode(path, kAuthorityOpenDoc, flags, context, result, true); + return; + } if (CFStringRef riskCategory = CFStringRef(CFDictionaryGetValue(context, kLSDownloadRiskCategoryKey))) { - FileQuarantine qtn(cfString(path).c_str()); if (CFEqual(riskCategory, kLSRiskCategorySafe) || CFEqual(riskCategory, kLSRiskCategoryNeutral) @@ -624,6 +695,7 @@ void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDi } else if (qtn.flag(QTN_FLAG_HARD)) { MacOSError::throwMe(errSecCSFileHardQuarantined); } else if (qtn.flag(QTN_FLAG_ASSESSMENT_OK)) { + // previously added by user cfadd(result, "{%O=#T}", kSecAssessmentAssessmentVerdict); addAuthority(flags, result, "Prior Assessment"); } else if (!overrideAssessment(flags)) { // no need to do more work if we're off @@ -650,7 +722,7 @@ void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDi // // Result-creation helpers // -void PolicyEngine::addAuthority(SecAssessmentFlags flags, CFMutableDictionaryRef parent, const char *label, SQLite::int64 row, CFTypeRef cacheInfo, bool weak) +void PolicyEngine::addAuthority(SecAssessmentFlags flags, CFMutableDictionaryRef parent, const char *label, SQLite::int64 row, CFTypeRef cacheInfo, bool weak, uint64_t ruleFlags) { CFRef auth = makeCFMutableDictionary(); if (label && label[0]) @@ -661,6 +733,7 @@ void PolicyEngine::addAuthority(SecAssessmentFlags flags, CFMutableDictionaryRef CFDictionaryAddValue(auth, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride); if (cacheInfo) CFDictionaryAddValue(auth, kSecAssessmentAssessmentFromCache, cacheInfo); + CFDictionaryAddValue(auth, kSecAssessmentAssessmentAuthorityFlags, CFTempNumber(ruleFlags)); if (weak) { CFDictionaryAddValue(auth, kSecAssessmentAssessmentWeakSignature, kCFBooleanTrue); CFDictionaryReplaceValue(parent, kSecAssessmentAssessmentAuthority, auth); @@ -813,6 +886,9 @@ CFDictionaryRef PolicyEngine::disable(CFTypeRef target, AuthorityType type, SecA CFDictionaryRef PolicyEngine::find(CFTypeRef target, AuthorityType type, SecAssessmentFlags flags, CFDictionaryRef context) { + //for privacy reasons we only want to allow the admin to list the database + authorizeUpdate(flags, context); + SQLite::Statement query(*this); selectRules(query, "SELECT scan_authority.id, scan_authority.type, scan_authority.requirement, scan_authority.allow, scan_authority.label, scan_authority.priority, scan_authority.remarks, scan_authority.expires, scan_authority.disabled, bookmarkhints.bookmark FROM scan_authority LEFT OUTER JOIN bookmarkhints ON scan_authority.id = bookmarkhints.authority", "scan_authority", target, type, flags, context, @@ -1062,10 +1138,7 @@ void PolicyEngine::normalizeTarget(CFRef &target, AuthorityType type, case errSecCSUnsigned: if (signUnsigned && temporarySigning(code, type, path, kAuthorityFlagWhitelistV2 | kAuthorityFlagWhitelistSHA256)) { // ad-hoc sign the code temporarily MacOSError::check(SecCodeCopyDesignatedRequirement(code, kSecCSDefaultFlags, (SecRequirementRef *)&target.aref())); - CFRef info; - MacOSError::check(SecCodeCopySigningInformation(code, kSecCSInternalInformation, &info.aref())); - if (CFDataRef cdData = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoCodeDirectory))) - *signUnsigned = ((const CodeDirectory *)CFDataGetBytePtr(cdData))->screeningCode(); + *signUnsigned = createWhitelistScreen(code); break; } MacOSError::check(rc); @@ -1108,17 +1181,15 @@ void PolicyEngine::normalizeTarget(CFRef &target, AuthorityType type, // static bool codeInvalidityExceptions(SecStaticCodeRef code, CFMutableDictionaryRef result) { - if (OSAIsRecognizedExecutableURL) { - CFRef info; - MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); - if (CFURLRef executable = CFURLRef(CFDictionaryGetValue(info, kSecCodeInfoMainExecutable))) { - SInt32 error; - if (OSAIsRecognizedExecutableURL(executable, &error)) { - if (result) - CFDictionaryAddValue(result, - kSecAssessmentAssessmentAuthorityOverride, CFSTR("ignoring known invalid applet signature")); - return true; - } + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(code, kSecCSDefaultFlags, &info.aref())); + if (CFURLRef executable = CFURLRef(CFDictionaryGetValue(info, kSecCodeInfoMainExecutable))) { + SInt32 error; + if (OSAIsRecognizedExecutableURL(executable, &error)) { + if (result) + CFDictionaryAddValue(result, + kSecAssessmentAssessmentAuthorityOverride, CFSTR("ignoring known invalid applet signature")); + return true; } } return false; diff --git a/OSX/libsecurity_codesigning/lib/policyengine.h b/OSX/libsecurity_codesigning/lib/policyengine.h index 46083083..9ba82dc2 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.h +++ b/OSX/libsecurity_codesigning/lib/policyengine.h @@ -65,7 +65,7 @@ public: void recordFailure(CFDictionaryRef info); public: - static void addAuthority(SecAssessmentFlags flags, CFMutableDictionaryRef parent, const char *label, SQLite::int64 row = 0, CFTypeRef cacheInfo = NULL, bool weak = false); + static void addAuthority(SecAssessmentFlags flags, CFMutableDictionaryRef parent, const char *label, SQLite::int64 row = 0, CFTypeRef cacheInfo = NULL, bool weak = false, uint64_t ruleFlags = 0); static void addToAuthority(CFMutableDictionaryRef parent, CFStringRef key, CFTypeRef value); private: diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index 3837d426..3215df48 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.cpp +++ b/OSX/libsecurity_codesigning/lib/reqinterp.cpp @@ -190,7 +190,7 @@ bool Requirement::Interpreter::eval(int depth) } } // unrecognized opcode and no way to interpret it - secdebug("csinterp", "opcode 0x%x cannot be handled; aborting", op); + secinfo("csinterp", "opcode 0x%x cannot be handled; aborting", op); MacOSError::throwMe(errSecCSUnimplemented); } } @@ -247,13 +247,14 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma { "subject.UID", &CSSMOID_UserID }, { NULL, NULL } }; - + // DN-component single-value match for (const CertField *cf = certFields; cf->name; cf++) if (cf->name == key) { CFRef value; - if (OSStatus rc = SecCertificateCopySubjectComponent(cert, cf->oid, &value.aref())) { - secdebug("csinterp", "cert %p lookup for DN.%s failed rc=%d", cert, key.c_str(), (int)rc); + 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); return false; } return match(value); @@ -262,15 +263,16 @@ bool Requirement::Interpreter::certFieldValue(const string &key, const Match &ma // email multi-valued match (any of...) if (key == "email") { CFRef value; - if (OSStatus rc = SecCertificateCopyEmailAddresses(cert, &value.aref())) { - secdebug("csinterp", "cert %p lookup for email failed rc=%d", cert, (int)rc); + OSStatus rc = SecCertificateCopyEmailAddresses(cert, &value.aref()); + if (rc) { + secinfo("csinterp", "cert %p lookup for email failed rc=%d", cert, (int)rc); return false; } return match(value); } // unrecognized key. Fail but do not abort to promote backward compatibility down the road - secdebug("csinterp", "cert field notation \"%s\" not understood", key.c_str()); + secinfo("csinterp", "cert field notation \"%s\" not understood", key.c_str()); return false; } @@ -327,7 +329,9 @@ CFArrayRef Requirement::Interpreter::getAdditionalTrustedAnchors() if (!configData) return NULL; - CFRef configDict = CFDictionaryRef(IOCFUnserialize((const char *)CFDataGetBytePtr(configData), kCFAllocatorDefault, 0, NULL)); + CFRef configDict = CFDictionaryRef(IOCFUnserializeWithSize((const char *)CFDataGetBytePtr(configData), + (size_t)CFDataGetLength(configData), + kCFAllocatorDefault, 0, NULL)); if (!configDict) return NULL; diff --git a/OSX/libsecurity_codesigning/lib/reqparser.cpp b/OSX/libsecurity_codesigning/lib/reqparser.cpp index 8a0c370a..e3657a19 100644 --- a/OSX/libsecurity_codesigning/lib/reqparser.cpp +++ b/OSX/libsecurity_codesigning/lib/reqparser.cpp @@ -30,6 +30,7 @@ #include "codesigning_dtrace.h" #include #include +#include namespace Security { namespace CodeSigning { @@ -61,6 +62,7 @@ PluginHost::PluginHost() } // can't load plugin - fail + Syslog::warning("code signing problem: unable to load csparser plug-in"); MacOSError::throwMe(errSecCSInternalError); } diff --git a/OSX/libsecurity_codesigning/lib/resources.cpp b/OSX/libsecurity_codesigning/lib/resources.cpp index c1efa959..4c36a387 100644 --- a/OSX/libsecurity_codesigning/lib/resources.cpp +++ b/OSX/libsecurity_codesigning/lib/resources.cpp @@ -74,7 +74,7 @@ ResourceBuilder::ResourceBuilder(const std::string &root, const std::string &rel UnixError::throwMe(); mRelBase = realroot; if (mRoot != mRelBase && mRelBase != mRoot + "/Contents") - MacOSError::throwMe(errSecCSInternalError); + MacOSError::throwMe(errSecCSBadBundleFormat); const char * paths[2] = { mRoot.c_str(), NULL }; mFTS = fts_open((char * const *)paths, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL); if (!mFTS) @@ -152,7 +152,7 @@ void ResourceBuilder::scan(Scanner next) } switch (ent->fts_info) { case FTS_F: - secdebug("rdirenum", "file %s", ent->fts_path); + secinfo("rdirenum", "file %s", ent->fts_path); GKBIS_Num_files++; // These are checks for the gatekeeper collection @@ -169,7 +169,7 @@ void ResourceBuilder::scan(Scanner next) break; case FTS_SL: // symlinks cannot ever be nested code, so quietly convert to resource file - secdebug("rdirenum", "symlink %s", ent->fts_path); + secinfo("rdirenum", "symlink %s", ent->fts_path); GKBIS_Num_symlinks++; if (strcasecmp(ent->fts_name, ds_store) == 0) @@ -180,7 +180,7 @@ void ResourceBuilder::scan(Scanner next) next(ent, rule->flags & ~nested, string(relpath), rule); break; case FTS_D: - secdebug("rdirenum", "entering %s", ent->fts_path); + secinfo("rdirenum", "entering %s", ent->fts_path); GKBIS_Num_dirs++; if (!first) { // skip root directory (relpath invalid) @@ -203,15 +203,15 @@ void ResourceBuilder::scan(Scanner next) break; case FTS_DP: - secdebug("rdirenum", "leaving %s", ent->fts_path); + secinfo("rdirenum", "leaving %s", ent->fts_path); break; case FTS_DNR: - secdebug("rdirenum", "cannot read directory %s", ent->fts_path); + secinfo("rdirenum", "cannot read directory %s", ent->fts_path); if (mCheckUnreadable) MacOSError::throwMe(errSecCSSignatureNotVerifiable); break; default: - secdebug("rdirenum", "type %d (errno %d): %s", + secinfo("rdirenum", "type %d (errno %d): %s", ent->fts_info, ent->fts_errno, ent->fts_path); if (mCheckUnknownType) MacOSError::throwMe(errSecCSResourceNotSupported); @@ -248,21 +248,21 @@ bool ResourceBuilder::includes(string path) const ResourceBuilder::Rule *ResourceBuilder::findRule(string path) const { Rule *bestRule = NULL; - secdebug("rscan", "test %s", path.c_str()); + secinfo("rscan", "test %s", path.c_str()); for (Rules::const_iterator it = mRules.begin(); it != mRules.end(); ++it) { Rule *rule = *it; - secdebug("rscan", "try %s", rule->source.c_str()); + secinfo("rscan", "try %s", rule->source.c_str()); if (rule->match(path.c_str())) { - secdebug("rscan", "match"); + secinfo("rscan", "match"); if (rule->flags & exclusion) { - secdebug("rscan", "excluded"); + secinfo("rscan", "excluded"); return rule; } if (!bestRule || rule->weight > bestRule->weight) bestRule = rule; } } - secdebug("rscan", "choosing %s (%d,0x%x)", + secinfo("rscan", "choosing %s (%d,0x%x)", bestRule ? bestRule->source.c_str() : "NOTHING", bestRule ? bestRule->weight : 0, bestRule ? bestRule->flags : 0); @@ -288,10 +288,13 @@ CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorit // // Hash a file to multiple hash types and return a dictionary suitable to form a resource seal // -CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithms types) +CFMutableDictionaryRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithms types, bool strictCheck) { UnixPlusPlus::AutoFileDesc fd(path); fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) + if (strictCheck) + if (fd.hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd.hasExtendedAttribute(XATTR_FINDERINFO_NAME)) + MacOSError::throwMe(errSecCSInvalidAssociatedFileData); CFRef result = makeCFMutableDictionary(); CFMutableDictionaryRef resultRef = result; CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { @@ -325,7 +328,7 @@ ResourceBuilder::Rule::Rule(const std::string &pattern, unsigned w, uint32_t f) { if (::regcomp(this, pattern.c_str(), REG_EXTENDED | REG_NOSUB)) //@@@ REG_ICASE? MacOSError::throwMe(errSecCSResourceRulesInvalid); - secdebug("csresource", "%p rule %s added (weight %d, flags 0x%x)", + secinfo("csresource", "%p rule %s added (weight %d, flags 0x%x)", this, pattern.c_str(), w, f); } @@ -352,7 +355,7 @@ std::string ResourceBuilder::escapeRE(const std::string &s) string r; for (string::const_iterator it = s.begin(); it != s.end(); ++it) { char c = *it; - if (strchr("\\[]{}().+*?", c)) + if (strchr("\\[]{}().+*?^$|", c)) r.push_back('\\'); r.push_back(c); } diff --git a/OSX/libsecurity_codesigning/lib/resources.h b/OSX/libsecurity_codesigning/lib/resources.h index 8d68314b..7e122587 100644 --- a/OSX/libsecurity_codesigning/lib/resources.h +++ b/OSX/libsecurity_codesigning/lib/resources.h @@ -88,7 +88,7 @@ public: Rule *findRule(string path) const; static CFDataRef hashFile(const char *path, CodeDirectory::HashAlgorithm type); - static CFMutableDictionaryRef hashFile(const char *path, CodeDirectory::HashAlgorithms types); + static CFMutableDictionaryRef hashFile(const char *path, CodeDirectory::HashAlgorithms types, bool strictCheck); static std::string hashName(CodeDirectory::HashAlgorithm type); diff --git a/OSX/libsecurity_codesigning/lib/security_codesigning.exp b/OSX/libsecurity_codesigning/lib/security_codesigning.exp index 160559fa..f5909556 100644 --- a/OSX/libsecurity_codesigning/lib/security_codesigning.exp +++ b/OSX/libsecurity_codesigning/lib/security_codesigning.exp @@ -111,6 +111,11 @@ _kSecCodeInfoUnique _kSecCodeInfoCdHashes _kSecCodeInfoCodeDirectory _kSecCodeInfoCodeOffset +_kSecCodeInfoDiskRepInfo +_kSecCodeInfoDiskRepOSPlatform +_kSecCodeInfoDiskRepOSVersionMin +_kSecCodeInfoDiskRepOSSDKVersion +_kSecCodeInfoDiskRepNoLibraryValidation _kSecCodeInfoResourceDirectory _kSecGuestAttributeCanonical _kSecGuestAttributeHash @@ -124,6 +129,7 @@ _kSecCFErrorResourceSeal _kSecCFErrorResourceAdded _kSecCFErrorResourceAltered _kSecCFErrorResourceMissing +_kSecCFErrorResourceSideband _kSecCFErrorInfoPlist _kSecCFErrorGuestAttributes _kSecCFErrorRequirementSyntax @@ -167,6 +173,7 @@ _kSecAssessmentAssessmentSource _kSecAssessmentAssessmentVerdict _kSecAssessmentAssessmentWeakSignature _kSecAssessmentAssessmentCodeSigningError +_kSecAssessmentContextKeyPrimarySignature # gatekeeper logging diff --git a/OSX/libsecurity_codesigning/lib/signer.cpp b/OSX/libsecurity_codesigning/lib/signer.cpp index b0e14edb..b9d4ba9f 100644 --- a/OSX/libsecurity_codesigning/lib/signer.cpp +++ b/OSX/libsecurity_codesigning/lib/signer.cpp @@ -127,7 +127,7 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) { // make sure the rep passes strict validation if (strict) - rep->strictValidate(NULL, MacOSErrorSet(), flags); + rep->strictValidate(NULL, MacOSErrorSet(), flags | (kSecCSQuickCheck|kSecCSRestrictSidebandData)); // initialize progress/cancellation state code->prepareProgress(0); // totally fake workload - we don't know how many files we'll encounter @@ -149,9 +149,9 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) identifier = state.mIdentifierPrefix + identifier; if (identifier.find('.') == string::npos && isAdhoc()) identifier = identifier + "-" + uniqueName(); - secdebug("signer", "using default identifier=%s", identifier.c_str()); + secinfo("signer", "using default identifier=%s", identifier.c_str()); } else - secdebug("signer", "using explicit identifier=%s", identifier.c_str()); + secinfo("signer", "using explicit identifier=%s", identifier.c_str()); teamID = state.mTeamID; if (teamID.empty() && (inherit & kSecCodeSignerPreserveTeamIdentifier)) { @@ -173,7 +173,7 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) bool haveCdFlags = false; if (!haveCdFlags && state.mCdFlagsGiven) { cdFlags = state.mCdFlags; - secdebug("signer", "using explicit cdFlags=0x%x", cdFlags); + secinfo("signer", "using explicit cdFlags=0x%x", cdFlags); haveCdFlags = true; } if (!haveCdFlags) { @@ -182,10 +182,10 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) if (CFTypeRef csflags = CFDictionaryGetValue(infoDict, CFSTR("CSFlags"))) { if (CFGetTypeID(csflags) == CFNumberGetTypeID()) { cdFlags = cfNumber(CFNumberRef(csflags)); - secdebug("signer", "using numeric cdFlags=0x%x from Info.plist", cdFlags); + secinfo("signer", "using numeric cdFlags=0x%x from Info.plist", cdFlags); } else if (CFGetTypeID(csflags) == CFStringGetTypeID()) { cdFlags = cdTextFlags(cfString(CFStringRef(csflags))); - secdebug("signer", "using text cdFlags=0x%x from Info.plist", cdFlags); + secinfo("signer", "using text cdFlags=0x%x from Info.plist", cdFlags); } else MacOSError::throwMe(errSecCSBadDictionaryFormat); haveCdFlags = true; @@ -193,7 +193,7 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) } if (!haveCdFlags && (inherit & kSecCodeSignerPreserveFlags)) { cdFlags = code->codeDirectory(false)->flags & ~kSecCodeSignatureAdhoc; - secdebug("signer", "using inherited cdFlags=0x%x", cdFlags); + secinfo("signer", "using inherited cdFlags=0x%x", cdFlags); haveCdFlags = true; } if (!haveCdFlags) @@ -263,15 +263,16 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) } // screen and set the signing time - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); if (state.mSigningTime == CFDateRef(kCFNull)) { - signingTime = 0; // no time at all + emitSigningTime = false; // no time at all } else if (!state.mSigningTime) { - signingTime = now; // default + emitSigningTime = true; + signingTime = 0; // wall clock, established later } else { CFAbsoluteTime time = CFDateGetAbsoluteTime(state.mSigningTime); - if (time > now) // not allowed to post-date a signature + if (time > CFAbsoluteTimeGetCurrent()) // not allowed to post-date a signature MacOSError::throwMe(errSecCSBadDictionaryFormat); + emitSigningTime = true; signingTime = time; } @@ -301,7 +302,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase { typedef ResourceBuilder::Rule Rule; - secdebug("codesign", "start building resource directory"); + secinfo("codesign", "start building resource directory"); __block CFRef result = makeCFMutableDictionary(); CFDictionaryRef rules = cfget(rulesDict, "rules"); @@ -352,7 +353,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase target[len] = '\0'; seal.take(cfmake("{symlink=%s}", target)); } else { - seal.take(resources.hashFile(accpath.c_str(), digestAlgorithms())); + seal.take(resources.hashFile(accpath.c_str(), digestAlgorithms(), signingFlags() & kSecCSSignStrictPreflight)); } if (ruleFlags & ResourceBuilder::optional) CFDictionaryAddValue(seal, CFSTR("optional"), kCFBooleanTrue); @@ -392,11 +393,11 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase hash.take(resources.hashFile(ent->fts_accpath, kSecCodeSignatureHashSHA1)); if (ruleFlags == 0) { // default case - plain hash cfadd(files, "{%s=%O}", relpath.c_str(), hash.get()); - secdebug("csresource", "%s added simple (rule %p)", relpath.c_str(), rule); + secinfo("csresource", "%s added simple (rule %p)", relpath.c_str(), rule); } else { // more complicated - use a sub-dictionary cfadd(files, "{%s={hash=%O,optional=%B}}", relpath.c_str(), hash.get(), ruleFlags & ResourceBuilder::optional); - secdebug("csresource", "%s added complex (rule %p)", relpath.c_str(), rule); + secinfo("csresource", "%s added complex (rule %p)", relpath.c_str(), rule); } } }); @@ -419,9 +420,11 @@ CFMutableDictionaryRef SecCodeSigner::Signer::signNested(const std::string &path if (signingFlags() & kSecCSSignNestedCode) this->state.sign(code, signingFlags()); std::string dr = Dumper::dump(code->designatedRequirement()); - return cfmake("{requirement=%s,cdhash=%O}", - Dumper::dump(code->designatedRequirement()).c_str(), - code->cdHash()); + if (CFDataRef hash = code->cdHash()) + return cfmake("{requirement=%s,cdhash=%O}", + Dumper::dump(code->designatedRequirement()).c_str(), + hash); + MacOSError::throwMe(errSecCSUnsigned); } catch (const CommonError &err) { CSError::throwMe(err.osStatus(), kSecCFErrorPath, CFTempURL(relpath, false, this->code->resourceBase())); } @@ -437,9 +440,10 @@ CFMutableDictionaryRef SecCodeSigner::Signer::signNested(const std::string &path void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context &context) { // Mach-O executable at the core - perform multi-architecture signing + RefPointer writer = rep->writer(); auto_ptr editor(state.mDetached ? static_cast(new BlobEditor(*fat, *this)) - : new MachOEditor(rep->writer(), *fat, this->digestAlgorithms(), rep->mainExecutablePath())); + : new MachOEditor(writer, *fat, this->digestAlgorithms(), rep->mainExecutablePath())); assert(editor->count() > 0); if (!editor->attribute(writerNoGlobal)) // can store architecture-common components populate(*editor); @@ -510,8 +514,9 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context } // done: write edit copy back over the original - if (!state.mDryRun) + if (!state.mDryRun) { editor->commit(); + } } @@ -644,9 +649,10 @@ CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd, CFDa CMSEncoderSetSignerAlgorithm(cms, kCMSEncoderDigestAlgorithmSHA256); MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true)); - if (signingTime) { + if (emitSigningTime) { MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrSigningTime)); - MacOSError::check(CMSEncoderSetSigningTime(cms, signingTime)); + CFAbsoluteTime time = signingTime ? signingTime : CFAbsoluteTimeGetCurrent(); + MacOSError::check(CMSEncoderSetSigningTime(cms, time)); } if (hashBag) { diff --git a/OSX/libsecurity_codesigning/lib/signer.h b/OSX/libsecurity_codesigning/lib/signer.h index fafa3fe3..1e92a9c7 100644 --- a/OSX/libsecurity_codesigning/lib/signer.h +++ b/OSX/libsecurity_codesigning/lib/signer.h @@ -101,7 +101,8 @@ private: uint32_t cdFlags; // CodeDirectory flags const Requirements *requirements; // internal requirements ready-to-use size_t pagesize; // size of main executable pages - CFAbsoluteTime signingTime; // signing time for CMS signature (0 => none) + CFAbsoluteTime signingTime; // signing time for CMS signature (0 => now) + bool emitSigningTime; // emit signing time as a signed CMS attribute bool strict; // strict validation private: diff --git a/OSX/libsecurity_codesigning/lib/signerutils.cpp b/OSX/libsecurity_codesigning/lib/signerutils.cpp index 25a327ba..855d1949 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.cpp +++ b/OSX/libsecurity_codesigning/lib/signerutils.cpp @@ -33,6 +33,7 @@ #include "csutilities.h" #include "drmaker.h" #include +#include #include #include @@ -244,7 +245,7 @@ void MachOEditor::childAction() if (mHelperOverridden) ::csops(0, CS_OPS_MARKKILL, NULL, 0); // force code integrity - ::seteuid(0); // activate privilege if caller has it; ignore error if not + (void)::seteuid(0); // activate privilege if caller has it; ignore error if not execv(mHelperPath, (char * const *)&arguments[0]); } @@ -275,7 +276,7 @@ void MachOEditor::write(Arch &arch, EmbeddedSignatureBlob *blob) arch.source->writeAll(*blob); ::free(blob); // done with it } else { - secdebug("signer", "%p cannot find CODESIGNING section", this); + secinfo("signer", "%p cannot find CODESIGNING data in Mach-O", this); MacOSError::throwMe(errSecCSInternalError); } } @@ -301,7 +302,7 @@ void MachOEditor::commit() // perform copy under root or file-owner privileges if available UidGuard guard; if (!guard.seteuid(0)) - guard.seteuid(st.st_uid); + (void)guard.seteuid(st.st_uid); // copy metadata from original file... copy(sourcePath.c_str(), NULL, COPYFILE_SECURITY | COPYFILE_METADATA); @@ -315,6 +316,7 @@ void MachOEditor::commit() UnixError::check(::rename(tempPath.c_str(), sourcePath.c_str())); mTempMayExist = false; // we renamed it away } + this->writer->flush(); } diff --git a/OSX/libsecurity_codesigning/lib/singlediskrep.cpp b/OSX/libsecurity_codesigning/lib/singlediskrep.cpp index 84c5a781..0e63bde8 100644 --- a/OSX/libsecurity_codesigning/lib/singlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/singlediskrep.cpp @@ -89,7 +89,6 @@ FileDesc &SingleDiskRep::fd() { if (!mFd) mFd.open(mPath, O_RDONLY); - return mFd; } @@ -101,7 +100,6 @@ void SingleDiskRep::flush() mFd.close(); } - // // The recommended identifier of a SingleDiskRep is, absent any better clue, // the basename of its path. @@ -118,6 +116,11 @@ string SingleDiskRep::recommendedIdentifier(const SigningContext &) void SingleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { DiskRep::strictValidate(cd, tolerated, flags); + + if (flags & kSecCSRestrictSidebandData) + if (fd().hasExtendedAttribute(XATTR_RESOURCEFORK_NAME) || fd().hasExtendedAttribute(XATTR_FINDERINFO_NAME)) + if (tolerated.find(errSecCSInvalidAssociatedFileData) == tolerated.end()) + MacOSError::throwMe(errSecCSInvalidAssociatedFileData); // code limit must cover (exactly) the entire file if (cd && cd->signingLimit() != signingLimit()) diff --git a/OSX/libsecurity_codesigning/lib/singlediskrep.h b/OSX/libsecurity_codesigning/lib/singlediskrep.h index cc15854c..8e9a8df3 100644 --- a/OSX/libsecurity_codesigning/lib/singlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/singlediskrep.h @@ -49,7 +49,7 @@ public: CFDataRef identification(); // partial file hash std::string mainExecutablePath(); // base path CFURLRef copyCanonicalPath(); // base path - virtual size_t signingLimit(); // size of file + size_t signingLimit(); // size of file UnixPlusPlus::FileDesc &fd(); // readable fd for this file void flush(); // close cached fd diff --git a/OSX/libsecurity_codesigning/lib/syspolicy.sql b/OSX/libsecurity_codesigning/lib/syspolicy.sql index 23b5df15..9a9b8598 100644 --- a/OSX/libsecurity_codesigning/lib/syspolicy.sql +++ b/OSX/libsecurity_codesigning/lib/syspolicy.sql @@ -119,6 +119,8 @@ INSERT INTO feature (name, value, remarks) VALUES ('filter_unsigned', 'present', 'builtin'); INSERT INTO feature (name, value, remarks) VALUES ('document rules', 'present', 'builtin'); +INSERT INTO feature (name, value, remarks) +VALUES ('root_only', 'present', 'builtin'); -- diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.cpp b/OSX/libsecurity_codesigning/lib/xpcengine.cpp index 6e415298..eb246dd8 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.cpp +++ b/OSX/libsecurity_codesigning/lib/xpcengine.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -96,8 +97,9 @@ public: } else if (type == XPC_TYPE_ERROR) { const char *s = xpc_copy_description(reply); printf("Error returned: %s\n", s); + Syslog::notice("code signing internal problem: unexpected error from xpc: %s", s); free((char*)s); - MacOSError::throwMe(errSecCSInternalError); + MacOSError::throwMe(errSecCSInternalError); } else { const char *s = xpc_copy_description(reply); printf("Unexpected type of return object: %s\n", s); @@ -122,18 +124,21 @@ static void copyCFDictionary(const void *key, const void *value, void *ctx) } -static void precheckAccess(CFURLRef path, CFDictionaryRef context) +static bool precheckAccess(CFURLRef path, CFDictionaryRef context) { CFTypeRef type = CFDictionaryGetValue(context, kSecAssessmentContextKeyOperation); if (type == NULL || CFEqual(type, kSecAssessmentOperationTypeExecute)) { CFRef code; - MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref())); + OSStatus rc = SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref()); + if (rc == errSecCSBadBundleFormat) // work around + return false; CFRef exec; MacOSError::check(SecCodeCopyPath(code, kSecCSDefaultFlags, &exec.aref())); UnixError::check(::access(cfString(exec).c_str(), R_OK)); } else { UnixError::check(access(cfString(path).c_str(), R_OK)); } + return true; } @@ -189,7 +194,9 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi if (CFGetTypeID(target) == CFNumberGetTypeID()) xpc_dictionary_set_uint64(msg, "rule", cfNumber(CFNumberRef(target))); else if (CFGetTypeID(target) == CFURLGetTypeID()) { - precheckAccess(CFURLRef(target), context); + bool good = precheckAccess(CFURLRef(target), context); + if (!good) // work around + return makeCFDictionary(0); // pretend this worked xpc_dictionary_set_string(msg, "url", cfString(CFURLRef(target)).c_str()); } else if (CFGetTypeID(target) == SecRequirementGetTypeID()) { CFRef data; @@ -217,8 +224,8 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi 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); @@ -244,6 +251,19 @@ void xpcEngineRecord(CFDictionaryRef info) msg.send(); } +void xpcEngineCheckDevID(CFBooleanRef* result) +{ + Message msg("check-dev-id"); + + msg.send(); + + if (int64_t error = xpc_dictionary_get_int64(msg, "error")) { + MacOSError::throwMe((int)error); + } + + *result = xpc_dictionary_get_bool(msg,"result") ? kCFBooleanTrue : kCFBooleanFalse; +} + } // end namespace CodeSigning } // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.h b/OSX/libsecurity_codesigning/lib/xpcengine.h index cd70387d..4e1d485e 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.h +++ b/OSX/libsecurity_codesigning/lib/xpcengine.h @@ -37,6 +37,7 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi CF_RETURNS_RETAINED; bool xpcEngineControl(const char *name); void xpcEngineRecord(CFDictionaryRef info); +void xpcEngineCheckDevID(CFBooleanRef* result); } // end namespace CodeSigning diff --git a/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj b/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj index edb3cacb..ff45f46c 100644 --- a/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj @@ -12,7 +12,7 @@ buildConfigurationList = C26AC0EC143BCF01001C98CE /* Build configuration list for PBXAggregateTarget "SystemPolicy" */; buildPhases = ( C26AC0F0143BCF18001C98CE /* ShellScript */, - C26AC0F4143BD1C4001C98CE /* CopyFiles */, + 1F9152F01C7255BD009351BD /* ShellScript */, C2F24DFE14BCBBF200309FCD /* ShellScript */, C2578CB11579627200D4FE48 /* CopyFiles */, C25C18CD15CB0C470007A2DE /* CopyFiles */, @@ -98,7 +98,6 @@ C25C18D115CB0FC30007A2DE /* com.apple.gkreport.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = C25C18CF15CB0FA00007A2DE /* com.apple.gkreport.plist */; }; C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C26763D514FD9EBE00A46EDF /* drmaker.cpp */; }; C26763D814FD9EBE00A46EDF /* drmaker.h in Headers */ = {isa = PBXBuildFile; fileRef = C26763D614FD9EBE00A46EDF /* drmaker.h */; }; - C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */ = {isa = PBXBuildFile; fileRef = C26AC0F3143BD1B3001C98CE /* SystemPolicy */; }; C26B45C10B8A9C0A003C0ACA /* ucspc in Frameworks */ = {isa = PBXBuildFile; fileRef = C26B45C00B8A9C00003C0ACA /* ucspc */; }; C26FF62D0E5B375A00F640A0 /* SecIntegrityLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2CC31040B8523AD005FA59D /* SecIntegrityLib.h */; settings = {ATTRIBUTES = (); }; }; C26FF62E0E5B375A00F640A0 /* SecCodeHostLib.h in Headers */ = {isa = PBXBuildFile; fileRef = C2BC1F340B580DA7003EC9DC /* SecCodeHostLib.h */; settings = {ATTRIBUTES = (); }; }; @@ -134,8 +133,8 @@ C2C3BCD30BA1E47E00E869D1 /* singlediskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */; }; C2C931B40AB8BA1200F83950 /* SecCodeHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2C931B30AB8BA1200F83950 /* SecCodeHost.cpp */; }; C2CC310F0B852424005FA59D /* SecIntegrityLib.c in Sources */ = {isa = PBXBuildFile; fileRef = C2CC310E0B852424005FA59D /* SecIntegrityLib.c */; }; - C2D2967A1BCF16C000B0A29B /* diskimagerep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D296781BCF16C000B0A29B /* diskimagerep.cpp */; settings = {ASSET_TAGS = (); }; }; - C2D2967B1BCF16C000B0A29B /* diskimagerep.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D296791BCF16C000B0A29B /* diskimagerep.h */; settings = {ASSET_TAGS = (); }; }; + C2D2967A1BCF16C000B0A29B /* diskimagerep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D296781BCF16C000B0A29B /* diskimagerep.cpp */; }; + C2D2967B1BCF16C000B0A29B /* diskimagerep.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D296791BCF16C000B0A29B /* diskimagerep.h */; }; C2D3833C0A237F47005C63A2 /* bundlediskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383120A237F47005C63A2 /* bundlediskrep.cpp */; }; C2D3833E0A237F47005C63A2 /* cdbuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383140A237F47005C63A2 /* cdbuilder.cpp */; }; C2D383400A237F47005C63A2 /* codedirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383160A237F47005C63A2 /* codedirectory.cpp */; }; @@ -152,6 +151,9 @@ C2D3835B0A237F47005C63A2 /* StaticCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383310A237F47005C63A2 /* StaticCode.cpp */; }; C2D3835D0A237F47005C63A2 /* reqparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383330A237F47005C63A2 /* reqparser.cpp */; }; C2D383610A237F47005C63A2 /* Requirements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D383370A237F47005C63A2 /* Requirements.cpp */; }; + C2D6EA3F1C8F5158009B586F /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2D6EA3E1C8F5158009B586F /* main.cpp */; }; + C2D6EA451C8F5257009B586F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2D6EA441C8F5257009B586F /* Security.framework */; }; + C2D6EA481C8F5281009B586F /* libsecurity_utilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C2D6EA461C8F5265009B586F /* libsecurity_utilities.a */; }; C2DC2DCA145F594000AD2A3A /* xar++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2353410145F1B110073F964 /* xar++.cpp */; }; C2DC2DCB145F5CD000AD2A3A /* policyengine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C27360201432A61900A9A5FF /* policyengine.cpp */; }; C2E2873D0B5D8D80009336A0 /* SecCodeHostLib.c in Sources */ = {isa = PBXBuildFile; fileRef = C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */; }; @@ -159,6 +161,7 @@ C2F4439A14C626D4000A01E6 /* quarantine++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F4439814C626D4000A01E6 /* quarantine++.cpp */; }; C2F4439B14C626D4000A01E6 /* quarantine++.h in Headers */ = {isa = PBXBuildFile; fileRef = C2F4439914C626D4000A01E6 /* quarantine++.h */; }; C2F6566E0BCBFB250078779E /* cserror.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2F6566C0BCBFB250078779E /* cserror.cpp */; }; + DC1418651CCEE2EC00CFD769 /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1418641CCEE2EC00CFD769 /* libutilities.a */; }; EB68B111150DAEEA00B4013D /* RequirementLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */; }; EB68B112150DAEEA00B4013D /* RequirementParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB68B10D150DAEBB00B4013D /* RequirementParser.cpp */; }; EB68B133150DB04400B4013D /* RequirementKeywords.h in Headers */ = {isa = PBXBuildFile; fileRef = EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */; }; @@ -193,7 +196,6 @@ EB976FD21684D7C500A68EE6 /* TokenStreamRewriteEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB41684D77600A68EE6 /* TokenStreamRewriteEngine.cpp */; }; EB976FD31684D7C500A68EE6 /* TokenStreamSelector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB51684D77600A68EE6 /* TokenStreamSelector.cpp */; }; EB976FD41684D7C500A68EE6 /* TreeParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB976FB61684D77600A68EE6 /* TreeParser.cpp */; }; - EBB9FF7A1682E51300FF9774 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = EBB9FF791682E51300FF9774 /* main.c */; }; EBB9FF7F1682E5A200FF9774 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBB9FF7E1682E5A200FF9774 /* CoreFoundation.framework */; }; EBB9FFE21682E83600FF9774 /* com.apple.CodeSigningHelper.sb in CopyFiles */ = {isa = PBXBuildFile; fileRef = EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */; }; EBDAF04F166D65FA0042CDCE /* piddiskrep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */; }; @@ -322,16 +324,6 @@ ); runOnlyForDeploymentPostprocessing = 1; }; - C26AC0F4143BD1C4001C98CE /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = private/var/db; - dstSubfolderSpec = 0; - files = ( - C26AC0F5143BD1C8001C98CE /* SystemPolicy in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; EBB9FFE11682E80A00FF9774 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -495,6 +487,9 @@ C2D383380A237F47005C63A2 /* Requirements.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Requirements.h; sourceTree = ""; }; C2D383390A237F47005C63A2 /* security_codesigning.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_codesigning.exp; sourceTree = ""; }; C2D50CDF0E155A4F0059A195 /* CSCommonPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSCommonPriv.h; sourceTree = ""; }; + C2D6EA3E1C8F5158009B586F /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + C2D6EA441C8F5257009B586F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = ../../../d/workspaces/Build/Debug/Security.framework; sourceTree = ""; }; + C2D6EA461C8F5265009B586F /* libsecurity_utilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsecurity_utilities.a; path = ../../../d/workspaces/Build/Debug/libsecurity_utilities.a; sourceTree = ""; }; C2E2873C0B5D8D80009336A0 /* SecCodeHostLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecCodeHostLib.c; sourceTree = ""; }; C2E8AF240DE25CA7000F6D3B /* SecCodePriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCodePriv.h; sourceTree = ""; }; C2E8AF250DE25CA7000F6D3B /* SecRequirementPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecRequirementPriv.h; sourceTree = ""; }; @@ -507,6 +502,7 @@ C2F6566C0BCBFB250078779E /* cserror.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cserror.cpp; sourceTree = ""; }; C2F6566D0BCBFB250078779E /* cserror.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cserror.h; sourceTree = ""; }; CDCBE8941A1A96E8002CB2B7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.Internal.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + DC1418641CCEE2EC00CFD769 /* libutilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libutilities.a; path = "../../../Users/kmowery/Library/Developer/Xcode/DerivedData/Security-fkwwcnddijtngfaslvsedvgyzbou/Build/Products/Debug/libutilities.a"; sourceTree = ""; }; EB68B10A150DAEBB00B4013D /* RequirementKeywords.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RequirementKeywords.h; sourceTree = ""; }; EB68B10B150DAEBB00B4013D /* RequirementLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RequirementLexer.cpp; sourceTree = ""; }; EB68B10C150DAEBB00B4013D /* RequirementLexer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RequirementLexer.hpp; sourceTree = ""; }; @@ -638,6 +634,7 @@ files = ( C200424D15D425D9004AE0A1 /* libsecurity_codesigning.a in Frameworks */, C200424E15D425D9004AE0A1 /* libsecurity_utilities.a in Frameworks */, + DC1418651CCEE2EC00CFD769 /* libutilities.a in Frameworks */, 7ACF261219958B6F00849B25 /* CoreFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -661,6 +658,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C2D6EA481C8F5281009B586F /* libsecurity_utilities.a in Frameworks */, + C2D6EA451C8F5257009B586F /* Security.framework in Frameworks */, EBB9FF7F1682E5A200FF9774 /* CoreFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -871,8 +870,8 @@ C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */, C28342EC0E36719D00E54360 /* detachedrep.h */, C28342EB0E36719D00E54360 /* detachedrep.cpp */, - EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */, EBDAF04E166D65FA0042CDCE /* piddiskrep.h */, + EBDAF04D166D65FA0042CDCE /* piddiskrep.cpp */, ); name = "Disk Representations"; sourceTree = ""; @@ -933,6 +932,9 @@ C2CC30EF0B8519CF005FA59D /* Frameworks */ = { isa = PBXGroup; children = ( + DC1418641CCEE2EC00CFD769 /* libutilities.a */, + C2D6EA461C8F5265009B586F /* libsecurity_utilities.a */, + C2D6EA441C8F5257009B586F /* Security.framework */, CDCBE8941A1A96E8002CB2B7 /* Security.framework */, C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */, C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */, @@ -1138,6 +1140,7 @@ isa = PBXGroup; children = ( EBB9FF791682E51300FF9774 /* main.c */, + C2D6EA3E1C8F5158009B586F /* main.cpp */, EBB9FF801682E65700FF9774 /* com.apple.CodeSigningHelper.sb */, EBB9FF731682E51300FF9774 /* Supporting Files */, ); @@ -1325,7 +1328,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_codesigning" */; compatibilityVersion = "Xcode 3.2"; @@ -1393,12 +1396,38 @@ files = ( ); inputPaths = ( + "$(SRCROOT)/", + "$(SRCROOT)/lib/", + "$(SRCROOT)/gke/", + "$(SRCROOT)/dtrace/", + "$(SRCROOT)/antlr2/", + "$(SRCROOT)/antlr2/contrib/", + "$(SRCROOT)/antlr2/contrib/bcb4/", + "$(SRCROOT)/antlr2/scripts/", + "$(SRCROOT)/antlr2/src/", ); outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "ranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + shellScript = "# with our source directories as input files, Xcode will only re-run this phase if there's been a source change. Also, xcode doesn't believe in recursive directory.\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + }; + 1F9152F01C7255BD009351BD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + "$(TEMPDIR)/SystemPolicy", + ); + outputPaths = ( + "$(DSTROOT)/private/var/db/SystemPolicy", + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/bash; + shellScript = "cp \"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\nchmod 600 \"$SCRIPT_OUTPUT_FILE_0\""; + showEnvVarsInLog = 0; }; C26AC0F0143BCF18001C98CE /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -1478,7 +1507,7 @@ ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/bash; - shellScript = "cp \"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\nchmod 444 \"$SCRIPT_OUTPUT_FILE_0\""; + shellScript = "cp \"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\nchmod 400 \"$SCRIPT_OUTPUT_FILE_0\""; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -1600,7 +1629,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - EBB9FF7A1682E51300FF9774 /* main.c in Sources */, + C2D6EA3F1C8F5158009B586F /* main.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1733,14 +1762,23 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "SECTRUST_OSX=1"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = ( "$(PROJECT_DIR)/../include", "$(PROJECT_DIR)/../utilities", @@ -1749,6 +1787,7 @@ "$(PROJECT_DIR)/lib", /usr/local/include, ); + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; TEMPDIR = "$(BUILT_PRODUCTS_DIR)/cstemp"; WARNING_CFLAGS = ( @@ -1764,14 +1803,22 @@ isa = XCBuildConfiguration; baseConfigurationReference = 184461A1146E9AD100B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "SECTRUST_OSX=1"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; HEADER_SEARCH_PATHS = ( "$(PROJECT_DIR)/../include", "$(PROJECT_DIR)/../utilities", @@ -1901,8 +1948,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; @@ -1927,6 +1972,7 @@ INSTALL_PATH = /System/Library/Frameworks/Security.framework/Versions/A/XPCServices; MACH_O_TYPE = mh_execute; ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = "${PRODUCT_NAME}"; PRODUCT_NAME = "com.apple.$(TARGET_NAME:rfc1034identifier)"; SKIP_INSTALL = NO; WRAPPER_EXTENSION = xpc; @@ -1937,8 +1983,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; @@ -1956,6 +2000,7 @@ INFOPLIST_FILE = "CodeSigningHelper/CodeSigningHelper-Info.plist"; INSTALL_PATH = /System/Library/Frameworks/Security.framework/Versions/A/XPCServices; MACH_O_TYPE = mh_execute; + PRODUCT_BUNDLE_IDENTIFIER = "${PRODUCT_NAME}"; PRODUCT_NAME = "com.apple.$(TARGET_NAME:rfc1034identifier)"; SKIP_INSTALL = NO; WRAPPER_EXTENSION = xpc; diff --git a/OSX/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj b/OSX/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj index 71ed1f54..98200d4d 100644 --- a/OSX/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_comcryption/libsecurity_comcryption.xcodeproj/project.pbxproj @@ -113,7 +113,7 @@ 0FD07C9DFE8A174411CD283A /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3240987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_comcryption" */; compatibilityVersion = "Xcode 3.2"; @@ -165,6 +165,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB1F4146EF7C1000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -172,6 +187,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB1F4146EF7C1000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_cryptkit/lib/ckutilities.c b/OSX/libsecurity_cryptkit/lib/ckutilities.c index bbbe252b..7ed0beea 100644 --- a/OSX/libsecurity_cryptkit/lib/ckutilities.c +++ b/OSX/libsecurity_cryptkit/lib/ckutilities.c @@ -154,7 +154,7 @@ void printGiant(const giant x) printf("sign=%d cap=%d n[]=", x->sign, x->capacity); for(i=0; isign); i++) { - printf("%u:", x->n[i]); + printf("%lu:", (unsigned long)x->n[i]); } printf("\n"); } @@ -165,7 +165,7 @@ void printGiantHex(const giant x) printf("sign=%d cap=%d n[]=", x->sign, x->capacity); for(i=0; isign); i++) { - printf("%x:", x->n[i]); + printf("%lx:", (unsigned long)x->n[i]); } printf("\n"); } @@ -181,7 +181,7 @@ void printGiantExp(const giant x) printf("sign=%d cap=%d n[]=", x->sign, x->capacity); for(i=0; in[i]); + printf("%lu ", (unsigned long)x->n[i]); if(i > 0) { printf("* w^%d ", i); } diff --git a/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c b/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c index 77851ade..c2499709 100644 --- a/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c +++ b/OSX/libsecurity_cryptkit/lib/feeDigitalSignature.c @@ -166,12 +166,15 @@ feeSig feeSigNewWithKey( returnGiant(pt0.z); } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" if(SIG_CURVE == CURVE_PLUS) { gtog(cp->x1Plus, sinst->PmX); } else { gtog(cp->x1Minus, sinst->PmX); } +#pragma clang diagnostic pop elliptic_simple(sinst->PmX, sinst->randGiant, cp); } #else /* CRYPTKIT_ELL_PROJ_ENABLE */ @@ -582,6 +585,8 @@ feeReturn feeSigVerifyNoProj(feeSig sig, * pick a key (+/-) * Q := P1 */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" if(SIG_CURVE == CURVE_PLUS) { origKey = feePubKeyPlusCurve(pubKey); gtog(cp->x1Plus, Q); @@ -590,6 +595,7 @@ feeReturn feeSigVerifyNoProj(feeSig sig, origKey = feePubKeyMinusCurve(pubKey); gtog(cp->x1Minus, Q); } +#pragma clang diagnostic pop messageGiant = giant_with_data(data, dataLen); // M(ciphertext) diff --git a/OSX/libsecurity_cryptkit/lib/feeECDSA.c b/OSX/libsecurity_cryptkit/lib/feeECDSA.c index cbed7a4e..57736073 100644 --- a/OSX/libsecurity_cryptkit/lib/feeECDSA.c +++ b/OSX/libsecurity_cryptkit/lib/feeECDSA.c @@ -460,7 +460,10 @@ feeReturn feeECDSAVerify(const unsigned char *sigData, * Verify that c and d are within [1,group_order-1] */ if((gcompg(cp->cOrderPlus, c) != 1) || (gcompg(cp->cOrderPlus, d) != 1) || - isZero(c) || isZero(d)) { + isZero(c) || isZero(d)) + { + returnGiant(c); + returnGiant(d); return FR_InvalidSignature; } diff --git a/OSX/libsecurity_cryptkit/lib/giantIntegers.c b/OSX/libsecurity_cryptkit/lib/giantIntegers.c index e7872b58..734ab60e 100644 --- a/OSX/libsecurity_cryptkit/lib/giantIntegers.c +++ b/OSX/libsecurity_cryptkit/lib/giantIntegers.c @@ -493,7 +493,7 @@ giant copyGiant(giant x) unsigned bitlen(giant n) { unsigned b = GIANT_BITS_PER_DIGIT; - giantDigit c = 1 << (GIANT_BITS_PER_DIGIT - 1); + giantDigit c = ((giantDigit)1) << (GIANT_BITS_PER_DIGIT - 1); giantDigit w; if (isZero(n)) { @@ -512,9 +512,9 @@ unsigned bitlen(giant n) { int bitval(giant n, int pos) { int i = abs(pos) >> GIANT_LOG2_BITS_PER_DIGIT; - giantDigit c = 1 << (pos & (GIANT_BITS_PER_DIGIT - 1)); + giantDigit c = ((giantDigit)1) << (pos & (GIANT_BITS_PER_DIGIT - 1)); - return((n->n[i]) & c); + return ((0!=((n->n[i]) & c))?1:0); } int gsign(giant g) diff --git a/OSX/libsecurity_cryptkit/lib/giantIntegers.h b/OSX/libsecurity_cryptkit/lib/giantIntegers.h index 2352a368..34acf764 100644 --- a/OSX/libsecurity_cryptkit/lib/giantIntegers.h +++ b/OSX/libsecurity_cryptkit/lib/giantIntegers.h @@ -31,7 +31,7 @@ extern "C" { /* * Size of giant digit. */ -#if NeXT || __i386__ || __i486__ +#if NeXT || __i386__ || __i486__ || __x86_64__ typedef unsigned int giantDigit; diff --git a/OSX/libsecurity_cryptkit/lib/giantPort_Generic.h b/OSX/libsecurity_cryptkit/lib/giantPort_Generic.h index 7062b406..5f4e4cd3 100644 --- a/OSX/libsecurity_cryptkit/lib/giantPort_Generic.h +++ b/OSX/libsecurity_cryptkit/lib/giantPort_Generic.h @@ -113,10 +113,14 @@ static inline void giantMulDigits( giantDigit *lowProduct, /* RETURNED, low digit */ giantDigit *hiProduct) /* RETURNED, high digit */ { +#if GIANT_LOG2_BITS_PER_DIGIT>5 +#error "dprod is too small to represent the full result of the multiplication" +#else unsigned long long dprod; +#endif dprod = (unsigned long long)dig1 * (unsigned long long)dig2; - *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); + *hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT); *lowProduct = (giantDigit)dprod; } diff --git a/OSX/libsecurity_cryptkit/lib/platform.c b/OSX/libsecurity_cryptkit/lib/platform.c index fa6c1b2e..b34746e9 100644 --- a/OSX/libsecurity_cryptkit/lib/platform.c +++ b/OSX/libsecurity_cryptkit/lib/platform.c @@ -28,7 +28,7 @@ void CKRaise(const char *reason) { #if FEE_DEBUG printf("CryptKit fatal error: %s\n", reason); #endif - exit(1); + abort(); } #import "feeDebug.h" @@ -83,7 +83,7 @@ void CKRaise(const char *reason) { #if FEE_DEBUG printf("CryptKit fatal error: %s\n", reason); #endif - exit(1); + abort(); } extern void time(unsigned *tp); @@ -106,12 +106,19 @@ unsigned createRandomSeed() */ #include #include +#include void CKRaise(const char *reason) { #if FEE_DEBUG printf("CryptKit fatal error: %s\n", reason); #endif - exit(1); + char * msg = NULL; + if(asprintf(&msg, "CryptKit fatal error: %s", reason)) { + CRSetCrashLogMessage(msg); + } else { + CRSetCrashLogMessage("CryptKit fatal error"); + } + abort(); } /* for X, this isn't used except for testing when SecurityServer when @@ -170,7 +177,7 @@ void CKRaise(const char *reason) { #if FEE_DEBUG printf("CryptKit fatal error: %s\n", reason); #endif - exit(1); + abort(); } #include diff --git a/OSX/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj b/OSX/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj index 53a83f0d..6625cb52 100644 --- a/OSX/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cryptkit/libsecurity_cryptkit.xcodeproj/project.pbxproj @@ -534,7 +534,7 @@ 0FD07C9DFE8A174411CD283A /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD33A0987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cryptkit" */; compatibilityVersion = "Xcode 3.2"; @@ -713,12 +713,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB1FA146EF983000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -726,12 +735,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB1FA146EF983000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_cssm/lib/attachment.cpp b/OSX/libsecurity_cssm/lib/attachment.cpp index de8aae2e..59ab540c 100644 --- a/OSX/libsecurity_cssm/lib/attachment.cpp +++ b/OSX/libsecurity_cssm/lib/attachment.cpp @@ -81,7 +81,7 @@ Attachment::Attachment(Module *parent, &upcalls, &spiFunctionTable)) { // attach rejected by module - secdebug("cssm", "attach of module %p(%s) failed", + secinfo("cssm", "attach of module %p(%s) failed", &module, module.name().c_str()); CssmError::throwMe(err); } @@ -89,7 +89,7 @@ Attachment::Attachment(Module *parent, if (spiFunctionTable == NULL || spiFunctionTable->ServiceType != subserviceType()) CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE); mIsActive = true; // now officially attached to plugin - secdebug("cssm", "%p attached module %p(%s) (ssid %ld type %ld)", + secinfo("cssm", "%p attached module %p(%s) (ssid %ld type %ld)", this, parent, parent->name().c_str(), (long)ssId, (long)ssType); // subclass is responsible for taking spiFunctionTable and build // whatever dispatch is needed @@ -116,7 +116,7 @@ void Attachment::detach(bool isLocked) CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); //@#attachment busy if (CSSM_RETURN error = module.plugin->detach(handle())) CssmError::throwMe(error); // I'm sorry Dave, ... - secdebug("cssm", "%p detach module %p(%s)", this, + secinfo("cssm", "%p detach module %p(%s)", this, &module, module.name().c_str()); mIsActive = false; module.detach(this); @@ -175,7 +175,6 @@ CSSM_RETURN Attachment::upcallCcToHandle(CSSM_CC_HANDLE handle, CSSM_MODULE_HANDLE *modHandle) { BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE Required(modHandle) = HandleObject::find((CSSM_HANDLE)handle, CSSMERR_CSSM_INVALID_ADDIN_HANDLE).attachment.handle(); END_API(CSP) } diff --git a/OSX/libsecurity_cssm/lib/certextensions.h b/OSX/libsecurity_cssm/lib/certextensions.h index 39dc1a0c..d215836b 100644 --- a/OSX/libsecurity_cssm/lib/certextensions.h +++ b/OSX/libsecurity_cssm/lib/certextensions.h @@ -28,6 +28,9 @@ #include +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + /*** *** Structs for declaring extension-specific data. ***/ @@ -637,4 +640,6 @@ typedef struct __CE_DataAndType { CSSM_BOOL critical; } CE_DataAndType DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #endif /* _CERT_EXTENSIONS_H_ */ diff --git a/OSX/libsecurity_cssm/lib/cssmaci.h b/OSX/libsecurity_cssm/lib/cssmaci.h index f71dd4b8..f1535aef 100644 --- a/OSX/libsecurity_cssm/lib/cssmaci.h +++ b/OSX/libsecurity_cssm/lib/cssmaci.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef struct cssm_spi_ac_funcs { CSSM_RETURN (CSSMACI *AuthCompute) (CSSM_AC_HANDLE ACHandle, @@ -53,6 +56,8 @@ typedef struct cssm_spi_ac_funcs { void **OutputParams); } CSSM_SPI_AC_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_AC_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmapple.h b/OSX/libsecurity_cssm/lib/cssmapple.h index 23f383ad..632b308d 100644 --- a/OSX/libsecurity_cssm/lib/cssmapple.h +++ b/OSX/libsecurity_cssm/lib/cssmapple.h @@ -37,6 +37,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + /* Guids for standard Apple addin modules. */ /* CSSM itself: {87191ca0-0fc9-11d4-849a-000502b52122} */ @@ -389,6 +392,12 @@ enum { // Make a backup of this database in a new file CSSM_APPLEFILEDL_MAKE_BACKUP, + + // Make a copy of this database + CSSM_APPLEFILEDL_MAKE_COPY, + + // Delete this database + CSSM_APPLEFILEDL_DELETE_FILE, }; /* UNLOCK_REFERRAL "type" attribute values */ @@ -701,6 +710,10 @@ enum CSSM_APPLE_PRIVATE_CSPDL_CODE_21 = 21, CSSM_APPLE_PRIVATE_CSPDL_CODE_22 = 22, CSSM_APPLE_PRIVATE_CSPDL_CODE_23 = 23, + CSSM_APPLE_PRIVATE_CSPDL_CODE_24 = 24, + CSSM_APPLE_PRIVATE_CSPDL_CODE_25 = 25, + CSSM_APPLE_PRIVATE_CSPDL_CODE_26 = 26, + CSSM_APPLE_PRIVATE_CSPDL_CODE_27 = 27, /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the * associated key blob. @@ -949,7 +962,7 @@ enum { CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT = 0x00000001, // enable fetch from network CSSM_TP_ACTION_FETCH_CRL_FROM_NET = 0x00000002, - // if set and positive OCSP verify for given cert, no further revocation + // if set and positive CRL verify for given cert, no further revocation // checking need be done on that cert CSSM_TP_ACTION_CRL_SUFFICIENT = 0x00000004, // require CRL verification for certs which claim a CRL provider @@ -1151,6 +1164,7 @@ typedef struct { * (included here for lack of a better place) */ #define kKeychainSuffix ".keychain" +#define kKeychainDbSuffix ".keychain-db" #define kSystemKeychainName "System.keychain" #define kSystemKeychainDir "/Library/Keychains/" #define kSystemUnlockFile "/var/db/SystemKey" @@ -1177,6 +1191,8 @@ const CSSM_OID *cssmAlgToOid(CSSM_ALGORITHMS algId); #define errSecErrnoBase 100000 #define errSecErrnoLimit 100255 +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif // __cplusplus diff --git a/OSX/libsecurity_cssm/lib/cssmapplePriv.h b/OSX/libsecurity_cssm/lib/cssmapplePriv.h index e3c013a2..9bf4e472 100644 --- a/OSX/libsecurity_cssm/lib/cssmapplePriv.h +++ b/OSX/libsecurity_cssm/lib/cssmapplePriv.h @@ -116,6 +116,18 @@ enum // Make a backup of this database on the filesystem CSSM_APPLECSPDL_DB_MAKE_BACKUP = CSSM_APPLE_PRIVATE_CSPDL_CODE_23, + + // Make a copy of this database on the filesystem + CSSM_APPLECSPDL_DB_MAKE_COPY = CSSM_APPLE_PRIVATE_CSPDL_CODE_24, + + // Make a clone of this database on the filesystem, and tell securityd about it + CSSM_APPLECSPDL_DB_CLONE = CSSM_APPLE_PRIVATE_CSPDL_CODE_25, + + // Delete the file underlying this database + CSSM_APPLECSPDL_DB_DELETE_FILE = CSSM_APPLE_PRIVATE_CSPDL_CODE_26, + + // Recoding of this database is complete + CSSM_APPLECSPDL_DB_RECODE_FINISHED = CSSM_APPLE_PRIVATE_CSPDL_CODE_27, }; /* AppleCSPDL passthrough parameters */ diff --git a/OSX/libsecurity_cssm/lib/cssmcli.h b/OSX/libsecurity_cssm/lib/cssmcli.h index 61c02bd6..504c9d7f 100644 --- a/OSX/libsecurity_cssm/lib/cssmcli.h +++ b/OSX/libsecurity_cssm/lib/cssmcli.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef struct cssm_spi_cl_funcs { CSSM_RETURN (CSSMCLI *CertCreateTemplate) (CSSM_CL_HANDLE CLHandle, @@ -235,6 +238,8 @@ typedef struct cssm_spi_cl_funcs { void **OutputParams); } CSSM_SPI_CL_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_CL_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmcspi.h b/OSX/libsecurity_cssm/lib/cssmcspi.h index 44c9ecee..16535953 100644 --- a/OSX/libsecurity_cssm/lib/cssmcspi.h +++ b/OSX/libsecurity_cssm/lib/cssmcspi.h @@ -33,6 +33,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef struct cssm_spi_csp_funcs { CSSM_RETURN (CSSMCSPI *EventNotify) (CSSM_CSP_HANDLE CSPHandle, @@ -360,6 +363,8 @@ typedef struct cssm_spi_csp_funcs { const CSSM_ACL_OWNER_PROTOTYPE *NewOwner); } CSSM_SPI_CSP_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_CSP_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmdli.h b/OSX/libsecurity_cssm/lib/cssmdli.h index 14848fd5..b755d0ad 100644 --- a/OSX/libsecurity_cssm/lib/cssmdli.h +++ b/OSX/libsecurity_cssm/lib/cssmdli.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef struct cssm_spi_dl_funcs { CSSM_RETURN (CSSMDLI *DbOpen) (CSSM_DL_HANDLE DLHandle, @@ -144,6 +147,8 @@ typedef struct cssm_spi_dl_funcs { void **OutputParams); } CSSM_SPI_DL_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_DL_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmkrapi.h b/OSX/libsecurity_cssm/lib/cssmkrapi.h index 984f2f4f..06adece6 100644 --- a/OSX/libsecurity_cssm/lib/cssmkrapi.h +++ b/OSX/libsecurity_cssm/lib/cssmkrapi.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef uint32 CSSM_KRSP_HANDLE; /* Key Recovery Service Provider Handle */ typedef struct cssm_kr_name { @@ -236,6 +239,8 @@ CSSM_KR_PassThrough (CSSM_KRSP_HANDLE KRSPHandle, void **OutputParams) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmkrspi.h b/OSX/libsecurity_cssm/lib/cssmkrspi.h index e27c165f..5c2cf0f6 100644 --- a/OSX/libsecurity_cssm/lib/cssmkrspi.h +++ b/OSX/libsecurity_cssm/lib/cssmkrspi.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + /* Data types for Key Recovery SPI */ typedef struct cssm_spi_kr_funcs { @@ -104,6 +107,8 @@ typedef struct cssm_spi_kr_funcs { void **OutputParams); } CSSM_SPI_KR_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_KR_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmspi.h b/OSX/libsecurity_cssm/lib/cssmspi.h index 35e8ea91..69765f8a 100644 --- a/OSX/libsecurity_cssm/lib/cssmspi.h +++ b/OSX/libsecurity_cssm/lib/cssmspi.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef CSSM_RETURN (CSSMAPI *CSSM_SPI_ModuleEventHandler) (const CSSM_GUID *ModuleGuid, void *CssmNotifyCallbackCtx, @@ -124,6 +127,7 @@ CSSM_RETURN CSSMSPI CSSM_SPI_ModuleDetach (CSSM_MODULE_HANDLE ModuleHandle) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop #ifdef __cplusplus } diff --git a/OSX/libsecurity_cssm/lib/cssmtpi.h b/OSX/libsecurity_cssm/lib/cssmtpi.h index 701a5ebd..ad92b112 100644 --- a/OSX/libsecurity_cssm/lib/cssmtpi.h +++ b/OSX/libsecurity_cssm/lib/cssmtpi.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef struct cssm_spi_tp_funcs { CSSM_RETURN (CSSMTPI *SubmitCredRequest) (CSSM_TP_HANDLE TPHandle, @@ -195,6 +198,8 @@ typedef struct cssm_spi_tp_funcs { void **OutputParams); } CSSM_SPI_TP_FUNCS DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_SPI_TP_FUNCS_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/cssmtype.h b/OSX/libsecurity_cssm/lib/cssmtype.h index f9aba2af..1cddc3e4 100644 --- a/OSX/libsecurity_cssm/lib/cssmtype.h +++ b/OSX/libsecurity_cssm/lib/cssmtype.h @@ -38,6 +38,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + /* Handle types. */ typedef CSSM_INTPTR CSSM_HANDLE, *CSSM_HANDLE_PTR; @@ -2073,6 +2076,8 @@ typedef struct cssm_db_schema_index_info { CSSM_DB_INDEXED_DATA_LOCATION IndexedDataLocation; } CSSM_DB_SCHEMA_INDEX_INFO DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_DB_SCHEMA_INDEX_INFO_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/emmspi.h b/OSX/libsecurity_cssm/lib/emmspi.h index f986952d..0981c581 100644 --- a/OSX/libsecurity_cssm/lib/emmspi.h +++ b/OSX/libsecurity_cssm/lib/emmspi.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef struct cssm_state_funcs { CSSM_RETURN (CSSMAPI *cssm_GetAttachFunctions) (CSSM_MODULE_HANDLE hAddIn, @@ -87,6 +90,8 @@ ModuleManagerAuthenticate (CSSM_KEY_HIERARCHY KeyHierarchy, CSSM_MANAGER_REGISTRATION_INFO_PTR FunctionTable) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/emmtype.h b/OSX/libsecurity_cssm/lib/emmtype.h index 2fb04a5e..1f3c18f1 100644 --- a/OSX/libsecurity_cssm/lib/emmtype.h +++ b/OSX/libsecurity_cssm/lib/emmtype.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #define CSSM_HINT_CALLBACK (1) typedef uint32 CSSM_MANAGER_EVENT_TYPES; @@ -46,6 +49,8 @@ typedef struct cssm_manager_event_notification { CSSM_DATA EventData; } CSSM_MANAGER_EVENT_NOTIFICATION DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_MANAGER_EVENT_NOTIFICATION_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/lib/manager.cpp b/OSX/libsecurity_cssm/lib/manager.cpp index 28511ed0..c98737a2 100644 --- a/OSX/libsecurity_cssm/lib/manager.cpp +++ b/OSX/libsecurity_cssm/lib/manager.cpp @@ -42,7 +42,7 @@ CssmManager::CssmManager() CssmManager::~CssmManager() { if (initCount > 0) - secdebug("cssm", "CSSM forcibly shutting down"); + secinfo("cssm", "CSSM forcibly shutting down"); } @@ -68,7 +68,7 @@ void CssmManager::initialize (const CSSM_VERSION &version, CssmError::throwMe(CSSMERR_CSSM_PVC_ALREADY_CONFIGURED); } initCount++; - secdebug("cssm", "re-initializing CSSM (%d levels)", initCount); + secinfo("cssm", "re-initializing CSSM (%d levels)", initCount); return; } @@ -84,7 +84,7 @@ void CssmManager::initialize (const CSSM_VERSION &version, // we are ready now initCount = 1; - secdebug("cssm", "CSSM initialized"); + secinfo("cssm", "CSSM initialized"); } @@ -99,14 +99,14 @@ bool CssmManager::terminate() case 0: CssmError::throwMe(CSSMERR_CSSM_NOT_INITIALIZED); case 1: - secdebug("cssm", "Terminating CSSM"); + secinfo("cssm", "Terminating CSSM"); if (!moduleMap.empty()) CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); // @#can't terminate with modules loaded initCount = 0; // mark uninitialized return true; default: initCount--; // nested INIT, just count down - secdebug("cssm", "CSSM nested termination (%d remaining)", initCount); + secinfo("cssm", "CSSM nested termination (%d remaining)", initCount); return false; } } @@ -144,13 +144,13 @@ void CssmManager::loadModule(const Guid &guid, allowed: ; } #endif - secdebug("cssm", "loading module %s(%s) from %s", + secinfo("cssm", "loading module %s(%s) from %s", info.name().c_str(), info.description().c_str(), info.path().c_str()); module = new Module(this, info, loader(info.path())); moduleMap[guid] = module; } else { module = it->second; - secdebug("cssm", "%p reloaded module %s(%s) at %s", + secinfo("cssm", "%p reloaded module %s(%s) at %s", module, module->name().c_str(), module->description().c_str(), module->path().c_str()); } @@ -172,12 +172,12 @@ void CssmManager::unloadModule(const Guid &guid, StLock _(mLock); Module *module = getModule(guid); if (module->unload(callback)) { - secdebug("cssm", "%p module %s(%s) final unload", + secinfo("cssm", "%p module %s(%s) final unload", module, module->name().c_str(), module->description().c_str()); moduleMap.erase(guid); delete module; } else - secdebug("cssm", "%p module %s(%s) load count now %u", module, + secinfo("cssm", "%p module %s(%s) load count now %u", module, module->name().c_str(), module->description().c_str(), module->callbackCount()); } diff --git a/OSX/libsecurity_cssm/lib/modload_plugin.cpp b/OSX/libsecurity_cssm/lib/modload_plugin.cpp index 14ab1293..350af350 100644 --- a/OSX/libsecurity_cssm/lib/modload_plugin.cpp +++ b/OSX/libsecurity_cssm/lib/modload_plugin.cpp @@ -26,6 +26,7 @@ // modload_plugin - loader interface for dynamically loaded plugin modules // #include "modload_plugin.h" +#include namespace Security { @@ -37,7 +38,11 @@ namespace Security { // LoadablePlugin::LoadablePlugin(const char *path) : LoadableBundle(path) { - secdebug("cssm", "LoadablePlugin(%s)", path); + secinfo("cssm", "LoadablePlugin(%s)", path); + if (!allowableModulePath(path)) { + secinfo("cssm", "LoadablePlugin(): not loaded; plugin in non-standard location: %s", path); + CssmError::throwMe(CSSMERR_CSSM_ADDIN_AUTHENTICATE_FAILED); + } load(); } @@ -47,7 +52,7 @@ LoadablePlugin::LoadablePlugin(const char *path) : LoadableBundle(path) // void LoadablePlugin::load() { - secdebug("cssm", "LoadablePlugin::load() path %s", path().c_str()); + secinfo("cssm", "LoadablePlugin::load() path %s", path().c_str()); LoadableBundle::load(); findFunction(mFunctions.load, "CSSM_SPI_ModuleLoad"); findFunction(mFunctions.attach, "CSSM_SPI_ModuleAttach"); @@ -57,7 +62,7 @@ void LoadablePlugin::load() void LoadablePlugin::unload() { - secdebug("cssm", "LoadablePlugin::unload() path %s", path().c_str()); + secinfo("cssm", "LoadablePlugin::unload() path %s", path().c_str()); /* skipping for workaround for radar 3774226 LoadableBundle::unload(); */ } @@ -76,7 +81,7 @@ CSSM_RETURN LoadablePlugin::load(const CSSM_GUID *CssmGuid, CSSM_SPI_ModuleEventHandler CssmNotifyCallback, void *CssmNotifyCallbackCtx) { - secdebug("cssm", "LoadablePlugin::load(guid,...) path %s", path().c_str()); + secinfo("cssm", "LoadablePlugin::load(guid,...) path %s", path().c_str()); return mFunctions.load(CssmGuid, ModuleGuid, CssmNotifyCallback, CssmNotifyCallbackCtx); } @@ -86,7 +91,7 @@ CSSM_RETURN LoadablePlugin::unload(const CSSM_GUID *CssmGuid, CSSM_SPI_ModuleEventHandler CssmNotifyCallback, void *CssmNotifyCallbackCtx) { - secdebug("cssm", "LoadablePlugin::unload(guid,...) path %s", path().c_str()); + secinfo("cssm", "LoadablePlugin::unload(guid,...) path %s", path().c_str()); return mFunctions.unload(CssmGuid, ModuleGuid, CssmNotifyCallback, CssmNotifyCallbackCtx); } @@ -114,5 +119,10 @@ CSSM_RETURN LoadablePlugin::detach(CSSM_MODULE_HANDLE ModuleHandle) return mFunctions.detach(ModuleHandle); } +bool LoadablePlugin::allowableModulePath(const char *path) { + // True if module path is in default location + const char *loadablePrefix="/System/Library/Security/"; + return (strncmp(loadablePrefix,path,strlen(loadablePrefix)) == 0); +} } // end namespace Security diff --git a/OSX/libsecurity_cssm/lib/modload_plugin.h b/OSX/libsecurity_cssm/lib/modload_plugin.h index 9d131dff..7e74ca03 100644 --- a/OSX/libsecurity_cssm/lib/modload_plugin.h +++ b/OSX/libsecurity_cssm/lib/modload_plugin.h @@ -56,6 +56,8 @@ private: template void findFunction(FunctionType * &func, const char *name) { func = (FunctionType *)lookupSymbol(name); } + + bool allowableModulePath(const char *path); }; diff --git a/OSX/libsecurity_cssm/lib/modloader.cpp b/OSX/libsecurity_cssm/lib/modloader.cpp index bf99d6d1..e495f5ba 100644 --- a/OSX/libsecurity_cssm/lib/modloader.cpp +++ b/OSX/libsecurity_cssm/lib/modloader.cpp @@ -88,11 +88,11 @@ Plugin *ModuleLoader::operator () (const string &path) { Plugin * &plugin = mPlugins[path]; if (!plugin) { - secdebug("cssm", "ModuleLoader(): creating plugin %s", path.c_str()); + secinfo("cssm", "ModuleLoader(): creating plugin %s", path.c_str()); plugin = new LoadablePlugin(path.c_str()); } else { - secdebug("cssm", "ModuleLoader(): FOUND plugin %s, isLoaded %s", + secinfo("cssm", "ModuleLoader(): FOUND plugin %s, isLoaded %s", path.c_str(), plugin->isLoaded() ? "TRUE" : "FALSE"); if(!plugin->isLoaded()) { plugin->load(); diff --git a/OSX/libsecurity_cssm/lib/transition.cpp b/OSX/libsecurity_cssm/lib/transition.cpp index 99c81b06..8f78be84 100644 --- a/OSX/libsecurity_cssm/lib/transition.cpp +++ b/OSX/libsecurity_cssm/lib/transition.cpp @@ -291,7 +291,6 @@ CSSM_GetContext (CSSM_CC_HANDLE CCHandle, CSSM_CONTEXT_PTR *ContextP) { BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); Context *newContext = new(context.attachment) Context(context.type(), context.algorithm()); try { @@ -326,7 +325,6 @@ CSSM_SetContext (CSSM_CC_HANDLE CCHandle, { BEGIN_API const Context &source = Context::required(ContextP); -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); CSSM_CONTEXT_ATTRIBUTE *oldAttributes = context.ContextAttributes; @@ -392,7 +390,6 @@ CSSM_UpdateContextAttributes (CSSM_CC_HANDLE CCHandle, const CSSM_CONTEXT_ATTRIBUTE *ContextAttributes) { BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); context.mergeAttributes(ContextAttributes, NumberAttributes); END_API(CSSM) @@ -408,7 +405,6 @@ CSSM_DeleteContextAttributes (CSSM_CC_HANDLE CCHandle, if (NumberOfAttributes == 0) return CSSM_OK; // I suppose Required(ContextAttributes); // preflight -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE HandleContext &context = HandleObject::find((CSSM_HANDLE)CCHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); for (uint32 n = 0; n < NumberOfAttributes; n++) context.deleteAttribute(ContextAttributes[n].AttributeType); @@ -425,7 +421,6 @@ CSSM_DigestDataClone (CSSM_CC_HANDLE ccHandle, CSSM_CC_HANDLE *newCCHandle) { BEGIN_API -#warning Cast from CSSM_CC_HANDLE to CSSM_HANDLE HandleContext &context = HandleObject::findAndLock((CSSM_HANDLE)ccHandle, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); TransitLock _(context.attachment); HandleContext *newContext = diff --git a/OSX/libsecurity_cssm/lib/x509defs.h b/OSX/libsecurity_cssm/lib/x509defs.h index 398cbc67..1affad44 100644 --- a/OSX/libsecurity_cssm/lib/x509defs.h +++ b/OSX/libsecurity_cssm/lib/x509defs.h @@ -32,6 +32,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef uint8 CSSM_BER_TAG; #define BER_TAG_UNKNOWN 0 #define BER_TAG_BOOLEAN 1 @@ -223,6 +226,8 @@ typedef struct cssm_x509_signed_crl { CSSM_X509_SIGNATURE signature; } CSSM_X509_SIGNED_CRL DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER, *CSSM_X509_SIGNED_CRL_PTR DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj b/OSX/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj index 4c04ddc0..462aded3 100644 --- a/OSX/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cssm/libsecurity_cssm.xcodeproj/project.pbxproj @@ -340,7 +340,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3480987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_cssm" */; compatibilityVersion = "Xcode 3.2"; @@ -465,12 +465,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1879B4A3146DAE33007E536C /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -478,12 +487,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1879B4A3146DAE33007E536C /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp index aa307033..6155d798 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp @@ -1687,7 +1687,7 @@ DbModifier::commit() return; try { - secdebugfunc("integrity", "committing to %s", mAtomicFile.path().c_str()); + secnotice("integrity", "committing to %s", mAtomicFile.path().c_str()); WriteSection aHeaderSection(Allocator::standard(), size_t(HeaderSize)); // Set aHeaderSection to the correct size. @@ -2550,6 +2550,14 @@ AppleDatabase::passThrough(DbContext &dbContext, dbMakeBackup(); break; + case CSSM_APPLEFILEDL_MAKE_COPY: + dbMakeCopy((const char *) inputParams); + break; + + case CSSM_APPLEFILEDL_DELETE_FILE: + dbDeleteFile(); + break; + case CSSM_APPLECSPDL_DB_RELATION_EXISTS: { CSSM_BOOL returnValue; @@ -2581,11 +2589,20 @@ AppleDatabase::dbMakeBackup() { string filename_temp(filename_temp_cstr); filename_temp += "_backup"; - const char * dstFilename = filename_temp.c_str(); free(filename_temp_cstr); - if(copyfile(mAtomicFile.path().c_str(), dstFilename, NULL, COPYFILE_ALL) < 0) { + dbMakeCopy(filename_temp.c_str()); +} + +void +AppleDatabase::dbMakeCopy(const char* path) { + if(copyfile(mAtomicFile.path().c_str(), path, NULL, COPYFILE_UNLINK | COPYFILE_ALL) < 0) { UnixError::throwMe(errno); } } +void AppleDatabase::dbDeleteFile() { + if(unlink(mAtomicFile.path().c_str()) < 0) { + UnixError::throwMe(errno); + } +} diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.h b/OSX/libsecurity_filedb/lib/AppleDatabase.h index c5f429d9..1ad330fd 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.h +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.h @@ -635,7 +635,12 @@ public: const AccessCredentials *inAccessCred, const void *inOpenParameters); + // These two methods will throw an exception on error virtual void dbMakeBackup(); + virtual void dbMakeCopy(const char * path); + + // Delete the file under this database + virtual void dbDeleteFile(); const CssmDbRecordAttributeInfo schemaRelations; const CssmDbRecordAttributeInfo schemaAttributes; diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.cpp b/OSX/libsecurity_filedb/lib/AtomicFile.cpp index 60c98f46..6095fb0f 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.cpp +++ b/OSX/libsecurity_filedb/lib/AtomicFile.cpp @@ -98,7 +98,7 @@ AtomicFile::performDelete() if (::unlink(mPath.c_str()) != 0) { int error = errno; - secdebug("atomicfile", "unlink %s: %s", mPath.c_str(), strerror(error)); + secnotice("atomicfile", "unlink %s: %s", mPath.c_str(), strerror(error)); if (error == ENOENT) CssmError::throwMe(CSSMERR_DL_DATASTORE_DOESNOT_EXIST); else @@ -121,7 +121,7 @@ AtomicFile::rename(const std::string &inNewPath) if (::rename(path, newPath) != 0) { int error = errno; - secdebug("atomicfile", "rename(%s, %s): %s", path, newPath, strerror(error)); + secnotice("atomicfile", "rename(%s, %s): %s", path, newPath, strerror(error)); UnixError::throwMe(error); } } @@ -140,7 +140,7 @@ AtomicFile::create(mode_t mode) if (fileRef == -1) { int error = errno; - secdebug("atomicfile", "open %s: %s", path, strerror(error)); + secnotice("atomicfile", "open %s: %s", path, strerror(error)); // Do the obvious error code translations here. // @@@ Consider moving these up a level. @@ -158,7 +158,7 @@ AtomicFile::create(mode_t mode) // Now that we have created the lock and the new db file create a tempfile // object. RefPointer temp(new AtomicTempFile(*this, lock, mode)); - secdebug("atomicfile", "%p created %s", this, path); + secnotice("atomicfile", "%p created %s", this, path); return temp; } catch (...) @@ -166,7 +166,7 @@ AtomicFile::create(mode_t mode) // Creating the temp file failed so remove the db file we just created too. if (::unlink(path) == -1) { - secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + secnotice("atomicfile", "unlink %s: %s", path, strerror(errno)); } throw; } @@ -202,7 +202,7 @@ AtomicFile::mode() const if (::stat(path, &st) == -1) { int error = errno; - secdebug("atomicfile", "stat %s: %s", path, strerror(error)); + secnotice("atomicfile", "stat %s: %s", path, strerror(error)); UnixError::throwMe(error); } return st.st_mode; @@ -381,8 +381,7 @@ AtomicBufferedFile::AtomicBufferedFile(const std::string &inPath, bool isLocal) mPath(inPath), mFileRef(-1), mBuffer(NULL), - mLength(0), - mIsMapped(isLocal) + mLength(0) { } @@ -393,12 +392,12 @@ AtomicBufferedFile::~AtomicBufferedFile() // In release mode, the assert() is compiled out so rv may be unused. __unused int rv = AtomicFile::rclose(mFileRef); assert(rv == 0); - secdebug("atomicfile", "%p closed %s", this, mPath.c_str()); + secnotice("atomicfile", "%p closed %s", this, mPath.c_str()); } if (mBuffer) { - secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer); + secnotice("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer); unloadBuffer(); } } @@ -412,7 +411,7 @@ AtomicBufferedFile::open() const char *path = mPath.c_str(); if (mFileRef >= 0) { - secdebug("atomicfile", "open %s: already open, closing and reopening", path); + secnotice("atomicfile", "open %s: already open, closing and reopening", path); close(); } @@ -420,7 +419,7 @@ AtomicBufferedFile::open() if (mFileRef == -1) { int error = errno; - secdebug("atomicfile", "open %s: %s", path, strerror(error)); + secnotice("atomicfile", "open %s: %s", path, strerror(error)); // Do the obvious error code translations here. // @@@ Consider moving these up a level. @@ -441,13 +440,13 @@ AtomicBufferedFile::open() else { int error = errno; - secdebug("atomicfile", "lseek(%s, END): %s", path, strerror(error)); + secnotice("atomicfile", "lseek(%s, END): %s", path, strerror(error)); AtomicFile::rclose(mFileRef); mFileRef = -1; UnixError::throwMe(error); } - secdebug("atomicfile", "%p opened %s: %qd bytes", this, path, mLength); + secnotice("atomicfile", "%p opened %s: %qd bytes", this, path, mLength); return mLength; } @@ -458,69 +457,48 @@ AtomicBufferedFile::open() void AtomicBufferedFile::unloadBuffer() { - if (!mIsMapped) - { - delete [] mBuffer; - } - else - { - munmap(mBuffer, (size_t)mLength); - } + if(mBuffer) { + delete [] mBuffer; + } } // // Load the contents of the file into memory. -// If we are on a local file system, we mmap the file. Otherwise, we -// read it all into memory void AtomicBufferedFile::loadBuffer() { - if (!mIsMapped) - { - // make a buffer big enough to hold the entire file - mBuffer = new uint8[mLength]; - lseek(mFileRef, 0, SEEK_SET); - ssize_t pos = 0; - - ssize_t bytesToRead = (ssize_t)mLength; - while (bytesToRead > 0) - { - ssize_t bytesRead = ::read(mFileRef, mBuffer + pos, bytesToRead); - if (bytesRead == -1) - { - if (errno != EINTR) - { - int error = errno; - secdebug("atomicfile", "lseek(%s, END): %s", mPath.c_str(), strerror(error)); - if (mFileRef >= 0) { - AtomicFile::rclose(mFileRef); - mFileRef = -1; - } - UnixError::throwMe(error); - } - } - else - { - bytesToRead -= bytesRead; - pos += bytesRead; - } - } - } - else - { - // mmap the buffer into place - mBuffer = (uint8*) mmap(NULL, (size_t)mLength, PROT_READ, MAP_PRIVATE, mFileRef, 0); - if (mBuffer == (uint8*) -1) - { - int error = errno; - secdebug("atomicfile", "lseek(%s, END): %s", mPath.c_str(), strerror(error)); - if (mFileRef >= 0) { - AtomicFile::rclose(mFileRef); - mFileRef = -1; - } - UnixError::throwMe(error); - } - } + // make a buffer big enough to hold the entire file + mBuffer = new uint8[mLength]; + if(lseek(mFileRef, 0, SEEK_SET) < 0) { + int error = errno; + secnotice("atomicfile", "lseek(%s, BEGINNING): %s", mPath.c_str(), strerror(error)); + UnixError::throwMe(error); + } + ssize_t pos = 0; + + ssize_t bytesToRead = (ssize_t)mLength; + while (bytesToRead > 0) + { + ssize_t bytesRead = ::read(mFileRef, mBuffer + pos, bytesToRead); + if (bytesRead == -1) + { + if (errno != EINTR) + { + int error = errno; + secnotice("atomicfile", "read(%s, %zd): %s", mPath.c_str(), bytesToRead, strerror(error)); + if (mFileRef >= 0) { + AtomicFile::rclose(mFileRef); + mFileRef = -1; + } + UnixError::throwMe(error); + } + } + else + { + bytesToRead -= bytesRead; + pos += bytesRead; + } + } } @@ -536,20 +514,20 @@ AtomicBufferedFile::read(off_t inOffset, off_t inLength, off_t &outLength) { if (mFileRef < 0) { - secdebug("atomicfile", "read %s: file yet not opened, opening", mPath.c_str()); + secnotice("atomicfile", "read %s: file yet not opened, opening", mPath.c_str()); open(); } off_t bytesLeft = inLength; if (mBuffer) { - secdebug("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer); + secnotice("atomicfile", "%p free %s buffer %p", this, mPath.c_str(), mBuffer); unloadBuffer(); } loadBuffer(); - secdebug("atomicfile", "%p allocated %s buffer %p size %qd", this, mPath.c_str(), mBuffer, bytesLeft); + secnotice("atomicfile", "%p allocated %s buffer %p size %qd", this, mPath.c_str(), mBuffer, bytesLeft); off_t maxEnd = inOffset + inLength; if (maxEnd > mLength) @@ -567,7 +545,7 @@ AtomicBufferedFile::close() { if (mFileRef < 0) { - secdebug("atomicfile", "close %s: already closed", mPath.c_str()); + secnotice("atomicfile", "close %s: already closed", mPath.c_str()); } else { @@ -576,11 +554,11 @@ AtomicBufferedFile::close() if (result == -1) { int error = errno; - secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno)); + secnotice("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno)); UnixError::throwMe(error); } - secdebug("atomicfile", "%p closed %s", this, mPath.c_str()); + secnotice("atomicfile", "%p closed %s", this, mPath.c_str()); } } @@ -647,7 +625,7 @@ AtomicTempFile::create(mode_t mode) if (mFileRef == -1) { int error = errno; - secdebug("atomicfile", "open %s: %s", path, strerror(error)); + secnotice("atomicfile", "open %s: %s", path, strerror(error)); // Do the obvious error code translations here. // @@@ Consider moving these up a level. @@ -666,12 +644,12 @@ AtomicTempFile::create(mode_t mode) if (::fchmod(mFileRef, mode)) { int error = errno; - secdebug("atomicfile", "fchmod %s: %s", path, strerror(error)); + secnotice("atomicfile", "fchmod %s: %s", path, strerror(error)); UnixError::throwMe(error); } } - secdebug("atomicfile", "%p created %s", this, path); + secnotice("atomicfile", "%p created %s", this, path); } void @@ -708,7 +686,7 @@ AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const if (pos == -1) { int error = errno; - secdebug("atomicfile", "lseek(%s, %qd): %s", mPath.c_str(), inOffset, strerror(error)); + secnotice("atomicfile", "lseek(%s, %qd): %s", mPath.c_str(), inOffset, strerror(error)); UnixError::throwMe(error); } } @@ -729,18 +707,18 @@ AtomicTempFile::write(AtomicFile::OffsetType inOffsetType, off_t inOffset, const if (error == EINTR) { // We got interrupted by a signal, so try again. - secdebug("atomicfile", "write %s: interrupted, retrying", mPath.c_str()); + secnotice("atomicfile", "write %s: interrupted, retrying", mPath.c_str()); continue; } - secdebug("atomicfile", "write %s: %s", mPath.c_str(), strerror(error)); + secnotice("atomicfile", "write %s: %s", mPath.c_str(), strerror(error)); UnixError::throwMe(error); } // Write returning 0 is bad mmkay. if (bytesWritten == 0) { - secdebug("atomicfile", "write %s: 0 bytes written", mPath.c_str()); + secnotice("atomicfile", "write %s: 0 bytes written", mPath.c_str()); CssmError::throwMe(CSSMERR_DL_INTERNAL_ERROR); } @@ -757,7 +735,7 @@ AtomicTempFile::fsync() { if (mFileRef < 0) { - secdebug("atomicfile", "fsync %s: already closed", mPath.c_str()); + secnotice("atomicfile", "fsync %s: already closed", mPath.c_str()); } else { @@ -770,11 +748,11 @@ AtomicTempFile::fsync() if (result == -1) { int error = errno; - secdebug("atomicfile", "fsync %s: %s", mPath.c_str(), strerror(errno)); + secnotice("atomicfile", "fsync %s: %s", mPath.c_str(), strerror(errno)); UnixError::throwMe(error); } - secdebug("atomicfile", "%p fsynced %s", this, mPath.c_str()); + secnotice("atomicfile", "%p fsynced %s", this, mPath.c_str()); } } @@ -783,7 +761,7 @@ AtomicTempFile::close() { if (mFileRef < 0) { - secdebug("atomicfile", "close %s: already closed", mPath.c_str()); + secnotice("atomicfile", "close %s: already closed", mPath.c_str()); } else { @@ -792,11 +770,11 @@ AtomicTempFile::close() if (result == -1) { int error = errno; - secdebug("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno)); + secnotice("atomicfile", "close %s: %s", mPath.c_str(), strerror(errno)); UnixError::throwMe(error); } - secdebug("atomicfile", "%p closed %s", this, mPath.c_str()); + secnotice("atomicfile", "%p closed %s", this, mPath.c_str()); } } @@ -823,7 +801,7 @@ AtomicTempFile::commit() s = copyfile_state_alloc(); if(copyfile(newPath, oldPath, s, COPYFILE_SECURITY | COPYFILE_NOFOLLOW) == -1) // Not fatal - secdebug("atomicfile", "copyfile (%s, %s): %s", oldPath, newPath, strerror(errno)); + secnotice("atomicfile", "copyfile (%s, %s): %s", oldPath, newPath, strerror(errno)); copyfile_state_free(s); // END @@ -833,14 +811,14 @@ AtomicTempFile::commit() if (::rename(oldPath, newPath) == -1) { int error = errno; - secdebug("atomicfile", "rename (%s, %s): %s", oldPath, newPath, strerror(errno)); + secnotice("atomicfile", "rename (%s, %s): %s", oldPath, newPath, strerror(errno)); UnixError::throwMe(error); } + secnotice("atomicfile", "%p commited %s to %s", this, oldPath, newPath); + // Unlock the lockfile mLockedFile = NULL; - - secdebug("atomicfile", "%p commited %s", this, oldPath); } catch (...) { @@ -863,7 +841,7 @@ AtomicTempFile::rollback() throw() const char *path = mPath.c_str(); if (::unlink(path) == -1) { - secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + secnotice("atomicfile", "unlink %s: %s", path, strerror(errno)); // rollback can't throw } @@ -873,7 +851,7 @@ AtomicTempFile::rollback() throw() const char *path = mFile.path().c_str(); if (::unlink(path) == -1) { - secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + secnotice("atomicfile", "unlink %s: %s", path, strerror(errno)); // rollback can't throw } } @@ -933,7 +911,7 @@ LocalFileLocker::lock(mode_t mode) int result = flock(mLockFile, LOCK_EX); IFDEBUG(double endTime = GetTime()); - IFDEBUG(secdebug("atomictime", "Waited %.4f milliseconds for file lock", (endTime - startTime) * 1000.0)); + IFDEBUG(secnotice("atomictime", "Waited %.4f milliseconds for file lock", (endTime - startTime) * 1000.0)); // errors at this point are bad if (result == -1) @@ -1027,7 +1005,7 @@ NetworkFileLocker::unique(mode_t mode) { int error = errno; ::syslog(LOG_ERR, "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error)); - secdebug("atomicfile", "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error)); + secnotice("atomicfile", "Couldn't create temp file %s: %s", fullname.c_str(), strerror(error)); UnixError::throwMe(error); } @@ -1134,7 +1112,7 @@ NetworkFileLocker::lock(mode_t mode) else doSyslog = true; - secdebug("atomicfile", "Locking %s", path); /* in order to cater for clock skew: get */ + secnotice("atomicfile", "Locking %s", path); /* in order to cater for clock skew: get */ if (!xcreat(path, mode, t)) /* time t from the filesystem */ { /* lock acquired, hurray! */ @@ -1157,12 +1135,12 @@ NetworkFileLocker::lock(mode_t mode) { triedforce=true; ::syslog(LOG_ERR, "Forced unlock denied on %s", path); - secdebug("atomicfile", "Forced unlock denied on %s", path); + secnotice("atomicfile", "Forced unlock denied on %s", path); } else { ::syslog(LOG_ERR, "Forcing lock on %s", path); - secdebug("atomicfile", "Forcing lock on %s", path); + secnotice("atomicfile", "Forcing lock on %s", path); sleep(16 /* DEFsuspend */); break; } @@ -1193,7 +1171,7 @@ NetworkFileLocker::lock(mode_t mode) case ENAMETOOLONG: /* Filename is too long, shorten and retry */ if (mPath.size() > mDir.size() + 8) { - secdebug("atomicfile", "Truncating %s and retrying lock", path); + secnotice("atomicfile", "Truncating %s and retrying lock", path); mPath.erase(mPath.end() - 1); path = mPath.c_str(); /* Reset retry counter. */ @@ -1212,7 +1190,7 @@ NetworkFileLocker::lock(mode_t mode) { int error = errno; ::syslog(LOG_ERR, "Lock failure on %s: %s", path, strerror(error)); - secdebug("atomicfile", "Lock failure on %s: %s", path, strerror(error)); + secnotice("atomicfile", "Lock failure on %s: %s", path, strerror(error)); UnixError::throwMe(error); } } @@ -1223,7 +1201,7 @@ NetworkFileLocker::unlock() const char *path = mPath.c_str(); if (::unlink(path) == -1) { - secdebug("atomicfile", "unlink %s: %s", path, strerror(errno)); + secnotice("atomicfile", "unlink %s: %s", path, strerror(errno)); // unlock can't throw } } diff --git a/OSX/libsecurity_filedb/lib/AtomicFile.h b/OSX/libsecurity_filedb/lib/AtomicFile.h index 65d8905a..db86fd76 100644 --- a/OSX/libsecurity_filedb/lib/AtomicFile.h +++ b/OSX/libsecurity_filedb/lib/AtomicFile.h @@ -125,9 +125,6 @@ private: // Length of file in bytes. off_t mLength; - - // Is on a local file system - bool mIsMapped; }; diff --git a/OSX/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj b/OSX/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj index 69125807..7280f5eb 100644 --- a/OSX/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_filedb/libsecurity_filedb.xcodeproj/project.pbxproj @@ -26,13 +26,6 @@ remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; remoteInfo = libsecurity_cdsa_plugin; }; - 182BB33C146F1057000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB214146F0538000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = generate; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -44,7 +37,7 @@ 4CA1FEBE052A3C8100F22E42 /* libsecurity_filedb.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_filedb.a; sourceTree = BUILT_PRODUCTS_DIR; }; AA827A5B0C62AD0300D7A310 /* OverUnderflowCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverUnderflowCheck.h; sourceTree = ""; }; AAEA4A430E9163290043771D /* ReadWriteSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadWriteSection.cpp; sourceTree = ""; }; - C28A1CED052E14480094CEF0 /* AppleDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AppleDatabase.cpp; sourceTree = ""; }; + C28A1CED052E14480094CEF0 /* AppleDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleDatabase.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C28A1CEE052E14480094CEF0 /* AppleDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AppleDatabase.h; sourceTree = ""; }; C28A1CEF052E14480094CEF0 /* AtomicFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicFile.cpp; sourceTree = ""; }; C28A1CF0052E14480094CEF0 /* AtomicFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AtomicFile.h; sourceTree = ""; }; @@ -151,7 +144,6 @@ buildRules = ( ); dependencies = ( - 182BB33D146F1057000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_filedb; productName = libsecurity_filedb; @@ -164,7 +156,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3600987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_filedb" */; compatibilityVersion = "Xcode 3.2"; @@ -221,14 +213,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 182BB33D146F1057000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = generate; - targetProxy = 182BB33C146F1057000BF1F3 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ C27AD35D0987FCDE001272E0 /* Debug */ = { isa = XCBuildConfiguration; @@ -250,13 +234,22 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB208146F043D000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -264,13 +257,20 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB208146F043D000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_keychain/lib/ACL.cpp b/OSX/libsecurity_keychain/lib/ACL.cpp index 6dfd8f28..3c328bf4 100644 --- a/OSX/libsecurity_keychain/lib/ACL.cpp +++ b/OSX/libsecurity_keychain/lib/ACL.cpp @@ -185,7 +185,7 @@ bool ACL::authorizesSpecifically(AclAuthorization right) void ACL::setIntegrity(const CssmData& digest) { if(mForm != integrityForm) { - secdebugfunc("integrity", "acl has incorrect form: %d", mForm); + secnotice("integrity", "acl has incorrect form: %d", mForm); CssmError::throwMe(CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE); } @@ -230,7 +230,7 @@ void ACL::modify() { StLock_(mMutex); if (mState == unchanged) { - secdebug("SecAccess", "ACL %p marked modified", this); + secinfo("SecAccess", "ACL %p marked modified", this); mState = modified; } } @@ -248,7 +248,7 @@ void ACL::remove() StLock_(mMutex); mAppList.clear(); mForm = invalidForm; - secdebug("SecAccess", "ACL %p marked deleted", this); + secinfo("SecAccess", "ACL %p marked deleted", this); mState = deleted; } @@ -308,12 +308,12 @@ void ACL::setAccess(AclBearer &target, bool update, if (isOwner()) { switch (action) { case unchanged: - secdebug("SecAccess", "ACL %p owner unchanged", this); + secinfo("SecAccess", "ACL %p owner unchanged", this); return; case inserted: // means modify the initial owner case modified: { - secdebug("SecAccess", "ACL %p owner modified", this); + secinfo("SecAccess", "ACL %p owner modified", this); makeSubject(); assert(mSubjectForm); AclOwnerPrototype proto(*mSubjectForm, mDelegate); @@ -329,10 +329,10 @@ void ACL::setAccess(AclBearer &target, bool update, // simple cases switch (action) { case unchanged: // ignore - secdebug("SecAccess", "ACL %p handle 0x%lx unchanged", this, entryHandle()); + secinfo("SecAccess", "ACL %p handle 0x%lx unchanged", this, entryHandle()); return; case deleted: // delete - secdebug("SecAccess", "ACL %p handle 0x%lx deleted", this, entryHandle()); + secinfo("SecAccess", "ACL %p handle 0x%lx deleted", this, entryHandle()); target.deleteAcl(entryHandle(), cred); return; default: @@ -349,12 +349,12 @@ void ACL::setAccess(AclBearer &target, bool update, AclEntryInput input(proto); switch (action) { case inserted: // insert - secdebug("SecAccess", "ACL %p inserted", this); + secinfo("SecAccess", "ACL %p inserted", this); target.addAcl(input, cred); mState = unchanged; break; case modified: // update - secdebug("SecAccess", "ACL %p handle 0x%lx modified", this, entryHandle()); + secinfo("SecAccess", "ACL %p handle 0x%lx modified", this, entryHandle()); target.changeAcl(entryHandle(), input, cred); mState = unchanged; break; @@ -376,13 +376,13 @@ void ACL::parse(const TypedList &subject) case CSSM_ACL_SUBJECT_TYPE_ANY: // subsume an "any" as a standard form mForm = allowAllForm; - secdebug("SecAccess", "parsed an allowAllForm (%d) (%d)", subject.type(), mForm); + secinfo("SecAccess", "parsed an allowAllForm (%d) (%d)", subject.type(), mForm); return; case CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT: // pure keychain prompt - interpret as applist form with no apps parsePrompt(subject); mForm = appListForm; - secdebug("SecAccess", "parsed a Keychain Prompt (%d) as an appListForm (%d)", subject.type(), mForm); + secinfo("SecAccess", "parsed a Keychain Prompt (%d) as an appListForm (%d)", subject.type(), mForm); return; case CSSM_ACL_SUBJECT_TYPE_THRESHOLD: { @@ -401,32 +401,32 @@ void ACL::parse(const TypedList &subject) TypedList &first = subject[3]; if (first.type() == CSSM_ACL_SUBJECT_TYPE_ANY) { mForm = allowAllForm; - secdebug("SecAccess", "parsed a Threshhold (%d) as an allowAllForm (%d)", subject.type(), mForm); + secinfo("SecAccess", "parsed a Threshhold (%d) as an allowAllForm (%d)", subject.type(), mForm); return; } // parse other (code signing) elements for (uint32 n = 0; n < count - 1; n++) { mAppList.push_back(new TrustedApplication(TypedList(subject[n + 3].list()))); - secdebug("SecAccess", "found an application: %s", mAppList.back()->path()); + secinfo("SecAccess", "found an application: %s", mAppList.back()->path()); } } mForm = appListForm; - secdebug("SecAccess", "parsed a Threshhold (%d) as an appListForm (%d)", subject.type(), mForm); + secinfo("SecAccess", "parsed a Threshhold (%d) as an appListForm (%d)", subject.type(), mForm); return; case CSSM_ACL_SUBJECT_TYPE_PARTITION: mForm = integrityForm; mIntegrity.copy(subject.last()->data()); - secdebug("SecAccess", "parsed a Partition (%d) as an integrityForm (%d)", subject.type(), mForm); + secinfo("SecAccess", "parsed a Partition (%d) as an integrityForm (%d)", subject.type(), mForm); return; default: - secdebug("SecAccess", "didn't find a type for %d, marking custom (%d)", subject.type(), mForm); + secinfo("SecAccess", "didn't find a type for %d, marking custom (%d)", subject.type(), mForm); mForm = customForm; mSubjectForm = chunkCopy(&subject); return; } } catch (const ParseError &) { - secdebug("SecAccess", "acl compile failed for type (%d); marking custom", subject.type()); + secinfo("SecAccess", "acl compile failed for type (%d); marking custom", subject.type()); mForm = customForm; mSubjectForm = chunkCopy(&subject); mAppList.clear(); @@ -466,7 +466,7 @@ void ACL::makeSubject() new(allocator) ListElement(allocator, mPromptDescription)); *mSubjectForm += new(allocator) ListElement(prompt); } - secdebug("SecAccess", "made an allowAllForm (%d) into a subjectForm (%d)", mForm, mSubjectForm->type()); + secinfo("SecAccess", "made an allowAllForm (%d) into a subjectForm (%d)", mForm, mSubjectForm->type()); return; case appListForm: { // threshold(1 of n+1) of { app1, ..., appn, PROMPT } @@ -483,17 +483,17 @@ void ACL::makeSubject() new(allocator) ListElement(allocator, mPromptDescription)); *mSubjectForm += new(allocator) ListElement(prompt); } - secdebug("SecAccess", "made an appListForm (%d) into a subjectForm (%d)", mForm, mSubjectForm->type()); + secinfo("SecAccess", "made an appListForm (%d) into a subjectForm (%d)", mForm, mSubjectForm->type()); return; case integrityForm: chunkFree(mSubjectForm, allocator); mSubjectForm = new(allocator) TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_PARTITION, new(allocator) ListElement(allocator, mIntegrity)); - secdebug("SecAccess", "made an integrityForm (%d) into a subjectForm (%d)", mForm, mSubjectForm->type()); + secinfo("SecAccess", "made an integrityForm (%d) into a subjectForm (%d)", mForm, mSubjectForm->type()); return; case customForm: assert(mSubjectForm); // already set; keep it - secdebug("SecAccess", "have a customForm (%d), already have a subjectForm (%d)", mForm, mSubjectForm->type()); + secinfo("SecAccess", "have a customForm (%d), already have a subjectForm (%d)", mForm, mSubjectForm->type()); return; default: diff --git a/OSX/libsecurity_keychain/lib/Access.cpp b/OSX/libsecurity_keychain/lib/Access.cpp index 2aa23a18..64da867e 100644 --- a/OSX/libsecurity_keychain/lib/Access.cpp +++ b/OSX/libsecurity_keychain/lib/Access.cpp @@ -270,7 +270,7 @@ void Access::removeAclsForRight(AclAuthorization right) { for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); ) { if (it->second->authorizesSpecifically(right)) { it = mAcls.erase(it); - secdebugfunc("SecAccess", "%p removed an acl, %d left", this, mAcls.size()); + secinfo("SecAccess", "%p removed an acl, %lu left", this, mAcls.size()); } else { it++; } @@ -339,16 +339,16 @@ void Access::compile(const CSSM_ACL_OWNER_PROTOTYPE &owner, StLock_(mMutex); // add owner acl mAcls[ownerHandle] = new ACL(AclOwnerPrototype::overlay(owner)); - secdebugfunc("SecAccess", "form of owner is: %d", mAcls[ownerHandle]->form()); + secinfo("SecAccess", "form of owner is: %d", mAcls[ownerHandle]->form()); // add acl entries const AclEntryInfo *acl = AclEntryInfo::overlay(acls); for (uint32 n = 0; n < aclCount; n++) { - secdebug("SecAccess", "%p compiling entry %ld", this, acl[n].handle()); + secinfo("SecAccess", "%p compiling entry %ld", this, acl[n].handle()); mAcls[acl[n].handle()] = new ACL(acl[n]); - secdebug("SecAccess", "form is: %d", mAcls[acl[n].handle()]->form()); + secinfo("SecAccess", "form is: %d", mAcls[acl[n].handle()]->form()); } - secdebug("SecAccess", "%p %ld entries compiled", this, mAcls.size()); + secinfo("SecAccess", "%p %ld entries compiled", this, mAcls.size()); } @@ -370,8 +370,8 @@ Access::Maker::Maker(Allocator &alloc, MakerType makerType) mInput = AclEntryPrototype(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_PASSWORD, new(allocator) ListElement(mKey.get()))); mInput.proto().tag(creationEntryTag); - secdebugfunc("SecAccess", "made a CSSM_ACL_SUBJECT_TYPE_PASSWORD ACL entry for %p", this); - secdebugfunc("SecAccess", "mInput: %p, typedList %p", &mInput, mInput.Prototype.TypedSubject); + secinfo("SecAccess", "made a CSSM_ACL_SUBJECT_TYPE_PASSWORD ACL entry for %p", this); + secinfo("SecAccess", "mInput: %p, typedList %p", &mInput, &(mInput.Prototype.TypedSubject)); // create credential sample for access mCreds += TypedList(allocator, CSSM_SAMPLE_TYPE_PASSWORD, new(allocator) ListElement(mKey.get())); @@ -380,7 +380,7 @@ Access::Maker::Maker(Allocator &alloc, MakerType makerType) { // just make it an CSSM_ACL_SUBJECT_TYPE_ANY list mInput = AclEntryPrototype(TypedList(allocator, CSSM_ACL_SUBJECT_TYPE_ANY)); - secdebugfunc("SecAccess", "made a CSSM_ACL_SUBJECT_TYPE_ANY ACL entry for %p", this); + secinfo("SecAccess", "made a CSSM_ACL_SUBJECT_TYPE_ANY ACL entry for %p", this); } } diff --git a/OSX/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h b/OSX/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h index 6cf859a9..ba5e31dc 100644 --- a/OSX/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h +++ b/OSX/libsecurity_keychain/lib/AppleBaselineEscrowCertificates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2013-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -177,7 +177,7 @@ static const UInt8 kBaseLineACFEscrowRootGM[] = { 0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55, 0x04,0x03,0x13,0x16,0x45,0x73,0x63,0x72,0x6F,0x77,0x20,0x53,0x65,0x72,0x76,0x69, 0x63,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35, - 0x30,0x35,0x31,0x36,0x30,0x35,0x32,0x38,0x32,0x31,0x5A,0x17,0x0D,0x32,0x35,0x30, + 0x30,0x35,0x31,0x36,0x30,0x35,0x32,0x38,0x32,0x31,0x5A,0x17,0x0D,0x34,0x39,0x30, 0x35,0x31,0x36,0x30,0x35,0x32,0x38,0x32,0x31,0x5A,0x30,0x79,0x31,0x0C,0x30,0x0A, 0x06,0x03,0x55,0x04,0x05,0x13,0x03,0x31,0x30,0x31,0x31,0x0B,0x30,0x09,0x06,0x03, 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A, @@ -212,30 +212,34 @@ static const UInt8 kBaseLineACFEscrowRootGM[] = { 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x8C,0xC8,0x0F,0xA1, 0x55,0xB0,0x84,0x7B,0x8D,0xC1,0x99,0x8C,0xF3,0x4F,0x18,0xB5,0x0F,0x83,0x80,0x6F, 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, - 0x82,0x01,0x01,0x00,0x95,0xB1,0x41,0x0F,0x10,0x5F,0x4D,0x36,0x4A,0x1F,0xFF,0x7E, - 0x77,0xC9,0x61,0xD4,0xE8,0x56,0xA0,0x5C,0x19,0xF4,0x3E,0x70,0x9B,0xFE,0x22,0xA1, - 0x3C,0xCB,0x3C,0xD6,0xE3,0x26,0xB6,0x46,0x05,0xCE,0x2C,0xC2,0x4A,0xC9,0x6B,0x70, - 0xA4,0x1C,0xF7,0x88,0x48,0x9F,0xAB,0x5A,0x82,0x35,0xC7,0x51,0x77,0xDF,0x7A,0x29, - 0x48,0xB8,0x0A,0x48,0x2E,0x3E,0xEB,0x7A,0x65,0x7F,0xDC,0xCB,0x8B,0x87,0xED,0xEC, - 0xAF,0x35,0xAF,0x52,0xE3,0x28,0x47,0xA1,0x19,0xA7,0x07,0x9E,0xD5,0xD6,0xEC,0x79, - 0xB6,0x25,0x32,0x9A,0xCF,0x08,0x98,0xF3,0xA8,0x64,0x54,0x0B,0x48,0x70,0xE9,0xD2, - 0x45,0x58,0x13,0xE0,0x85,0x39,0xCB,0x7F,0x5C,0x52,0xC8,0x81,0xF1,0x8F,0x02,0x8D, - 0xD3,0xB8,0x42,0x46,0xF2,0x37,0x58,0x9A,0x51,0xB8,0xFB,0xD8,0xDB,0xD6,0xEA,0xFF, - 0x71,0xC9,0x73,0x66,0x37,0x41,0x70,0x2D,0x7C,0xB2,0x87,0x3A,0x9B,0x12,0xEC,0x1E, - 0xB7,0x1F,0xDD,0xD5,0x3C,0xB9,0xF3,0x77,0xEF,0xB4,0xFE,0xCA,0xD9,0xE9,0x49,0x36, - 0x8D,0x47,0xA7,0x08,0x18,0xB5,0xA5,0x78,0x8B,0x50,0x11,0x6F,0x00,0x50,0x7C,0x58, - 0xE0,0xC1,0xD4,0xCA,0x7D,0xE0,0x6E,0x71,0x58,0x71,0x41,0x67,0xE8,0xB2,0xA3,0x40, - 0xFC,0xAF,0x46,0x1E,0x26,0x44,0x6D,0xC3,0x29,0x84,0xCA,0x05,0x29,0x03,0x9E,0x45, - 0xF7,0xA2,0x18,0x58,0xC6,0x55,0x4B,0x6D,0x67,0xA8,0x09,0x98,0x4F,0xCF,0x20,0x83, - 0x58,0x7E,0x4A,0xDE,0x8A,0x0A,0x76,0x63,0x35,0x77,0xF5,0xC3,0x43,0x38,0x50,0x10, - 0xAD,0x95,0xCC,0x4C, + 0x82,0x01,0x01,0x00,0x43,0x8D,0xA8,0x86,0x77,0xB7,0xF5,0xA8,0xD8,0xE5,0x32,0xE5, + 0xE7,0xAA,0x99,0x04,0x4C,0xD2,0x86,0x81,0x4B,0x72,0x89,0xBA,0x40,0x14,0xAD,0x75, + 0xDB,0xA1,0xBF,0xC3,0x73,0x22,0xAF,0xAE,0x33,0xAC,0xB3,0x13,0x62,0xB2,0x3D,0xCA, + 0xD3,0xBC,0x45,0x7A,0xC2,0xBC,0x2C,0xCA,0xA1,0x3F,0xD9,0x52,0xA8,0x54,0xC2,0x44, + 0xB8,0x6B,0xA5,0xCA,0xF4,0x7D,0xF6,0xE3,0x0B,0x1F,0x38,0x16,0x67,0xF1,0x0B,0xA8, + 0x2A,0xDC,0x72,0xC8,0x87,0x3B,0x44,0x55,0xF7,0x0F,0x04,0x57,0x67,0xF1,0x11,0x91, + 0xA0,0xD2,0x78,0xEC,0x8C,0xBB,0x76,0x24,0x66,0x4F,0xA1,0xFE,0xBB,0xDE,0x00,0x01, + 0x9F,0x30,0x18,0x27,0x32,0xFF,0xFF,0xF6,0x9B,0xEA,0x43,0x36,0x67,0x2F,0x83,0x97, + 0x4D,0xE8,0x4E,0x9C,0xC1,0xEE,0x24,0xC8,0x21,0x72,0xFB,0x12,0xA9,0x2E,0x65,0xDE, + 0x84,0xB8,0xFF,0xC4,0xAB,0xDB,0x5D,0x3A,0xE9,0x3C,0x8F,0x1C,0x26,0x65,0x5F,0x34, + 0x50,0xB2,0x60,0x76,0x8B,0x42,0x64,0x5A,0x59,0xEA,0xD1,0x4E,0x23,0xF4,0xC8,0x28, + 0x8F,0x60,0xE5,0x75,0x36,0x3B,0x4C,0x38,0xC9,0x0F,0xCD,0x54,0x79,0x47,0x1D,0xC3, + 0x2F,0x9B,0x33,0x39,0x9F,0x50,0xD2,0x0B,0x68,0x3D,0x8A,0xCA,0x1F,0x5A,0xA5,0x5E, + 0x29,0x68,0x96,0xC2,0x1E,0x02,0xBA,0x8F,0x9C,0x55,0xB3,0x2E,0x24,0x2C,0x58,0xD8, + 0xAC,0xE4,0xF0,0x6C,0xDE,0x16,0x47,0x37,0x0D,0xA8,0x5C,0x09,0x4B,0x23,0x4D,0x21, + 0xFD,0xFF,0xCD,0x50,0xD5,0x59,0x0E,0x37,0x63,0xD0,0xA5,0xC7,0xBF,0xDD,0x88,0xF3, + 0x81,0xB1,0x3F,0x4E, }; static struct RootRecord kBaseLineEscrowRootRecord = {sizeof(kBaseLineEscrowRootGM), (UInt8*)kBaseLineEscrowRootGM}; static struct RootRecord kBaseLineACFEscrowRootRecord = {sizeof(kBaseLineACFEscrowRootGM), (UInt8*)kBaseLineACFEscrowRootGM}; static struct RootRecord* kBaseLineEscrowRoots[] = {&kBaseLineEscrowRootRecord, &kBaseLineACFEscrowRootRecord}; +static struct RootRecord* kBaseLineEscrowBackupRoots[] = {&kBaseLineEscrowRootRecord, &kBaseLineACFEscrowRootRecord}; +static struct RootRecord* kBaseLineEscrowEnrollmentRoots[] = {&kBaseLineACFEscrowRootRecord}; static const int kNumberOfBaseLineEscrowRoots = (int)(sizeof(kBaseLineEscrowRoots)/sizeof(kBaseLineEscrowRoots[0])); +static const int kNumberOfBaseLineEscrowBackupRoots = (int)(sizeof(kBaseLineEscrowBackupRoots)/sizeof(kBaseLineEscrowBackupRoots[0])); +static const int kNumberOfBaseLineEscrowEnrollmentRoots = (int)(sizeof(kBaseLineEscrowEnrollmentRoots)/sizeof(kBaseLineEscrowEnrollmentRoots[0])); static struct RootRecord kBaseLinePCSEscrowRootRecord = {sizeof(kBaseLinePCSEscrowRootGM), (UInt8*)kBaseLinePCSEscrowRootGM}; static struct RootRecord* kBaseLinePCSEscrowRoots[] = {&kBaseLinePCSEscrowRootRecord}; diff --git a/OSX/libsecurity_keychain/lib/CCallbackMgr.cp b/OSX/libsecurity_keychain/lib/CCallbackMgr.cp index 877dc9d0..e85f9c05 100644 --- a/OSX/libsecurity_keychain/lib/CCallbackMgr.cp +++ b/OSX/libsecurity_keychain/lib/CCallbackMgr.cp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2000-2004,2011-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, @@ -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@ */ @@ -36,10 +36,13 @@ #include #include "Globals.h" +#include #include #include #include +#include #include +#include using namespace KeychainCore; using namespace CssmClient; @@ -47,18 +50,31 @@ using namespace SecurityServer; #pragma mark ÑÑÑÑ CallbackInfo ÑÑÑÑ -CallbackInfo::CallbackInfo() : mCallback(NULL),mEventMask(0),mContext(NULL) +CallbackInfo::CallbackInfo() : mCallback(NULL),mEventMask(0),mContext(NULL), mRunLoop(NULL), mActive(false) { } CallbackInfo::CallbackInfo(SecKeychainCallback inCallbackFunction, - SecKeychainEventMask inEventMask, void *inContext) - : mCallback(inCallbackFunction), mEventMask(inEventMask), mContext(inContext) + SecKeychainEventMask inEventMask, void *inContext, CFRunLoopRef runLoop) + : mCallback(inCallbackFunction), mEventMask(inEventMask), mContext(inContext), mRunLoop(NULL), mActive(false) { + mRunLoop = runLoop; + CFRetainSafe(mRunLoop); +} + +CallbackInfo::CallbackInfo(const CallbackInfo& cb) { + mCallback = cb.mCallback; + mEventMask = cb.mEventMask; + mContext = cb.mContext; + mActive = cb.mActive; + + mRunLoop = cb.mRunLoop; + CFRetainSafe(mRunLoop); } CallbackInfo::~CallbackInfo() { + CFReleaseNull(mRunLoop); } bool CallbackInfo::operator==(const CallbackInfo& other) const @@ -110,18 +126,16 @@ CCallbackMgr& CCallbackMgr::Instance() return gCallbackMaker().instance(); } -void CCallbackMgr::AddCallback( SecKeychainCallback inCallbackFunction, +void CCallbackMgr::AddCallback( SecKeychainCallback inCallbackFunction, SecKeychainEventMask inEventMask, void* inContext) { - CallbackInfo info( inCallbackFunction, inEventMask, inContext ); - CallbackInfo existingInfo; - + CallbackInfo info( inCallbackFunction, inEventMask, inContext, CFRunLoopGetCurrent() ); CallbackInfoListIterator ix = find( CCallbackMgr::Instance().mEventCallbacks.begin(), CCallbackMgr::Instance().mEventCallbacks.end(), info ); - + // make sure it is not already there if ( ix!=CCallbackMgr::Instance().mEventCallbacks.end() ) { @@ -130,8 +144,38 @@ void CCallbackMgr::AddCallback( SecKeychainCallback inCallbackFunction, // On Mac OS X this list is per process so this is always a duplicate MacOSError::throwMe(errSecDuplicateCallback); } - + CCallbackMgr::Instance().mEventCallbacks.push_back(info); + + // We want to deliver these notifications if the CFRunLoop we just wrote down is actually actively serviced. + // Otherwise, it'll be a continuous (undetectable) leak. + CFRunLoopTimerContext ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.info = info.mRunLoop; + + CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 0, 0, 0, CCallbackMgr::cfrunLoopActive, &ctx); + secdebug("kcnotify", "adding a activate callback on run loop %p", info.mRunLoop); + CFRunLoopAddTimer(info.mRunLoop, timerRef, kCFRunLoopDefaultMode); +} + +void CCallbackMgr::cfrunLoopActive(CFRunLoopTimerRef timer, void* info) { + CFRunLoopRef runLoop = (CFRunLoopRef) info; + secdebug("kcnotify", "activating run loop %p", runLoop); + + // Use the notification queue to serialize setting the mActive bits + static dispatch_queue_t notification_queue = EventListener::getNotificationQueue(); + dispatch_async(notification_queue, ^() { + // Iterate through list, and activate every notification on this run loop + for(CallbackInfoListIterator ix = CCallbackMgr::Instance().mEventCallbacks.begin(); ix != CCallbackMgr::Instance().mEventCallbacks.end(); ix++) { + // pointer comparison, not CFEqual. + if(ix->mRunLoop == runLoop) { + secdebug("kcnotify", "activating callback on run loop %p", runLoop); + ix->mActive = true; + } + } + }); + + CFRelease(timer); } @@ -153,13 +197,54 @@ void CCallbackMgr::RemoveCallback(SecKeychainCallback inCallbackFunction) MacOSError::throwMe(errSecInvalidCallback); } +struct CallbackMgrInfo { + SecKeychainEvent event; + SecKeychainCallbackInfo secKeychainCallbackInfo; + SecKeychainCallback callback; + void *callbackContext; +}; + +void CCallbackMgr::tellClient(CFRunLoopTimerRef timer, void* info) { + CallbackMgrInfo* cbmInfo = (CallbackMgrInfo*) info; + if(!cbmInfo || !(cbmInfo->callback)) { + return; + } + + cbmInfo->callback(cbmInfo->event, &(cbmInfo->secKeychainCallbackInfo), cbmInfo->callbackContext); + if (cbmInfo->secKeychainCallbackInfo.item) CFRelease(cbmInfo->secKeychainCallbackInfo.item); + if (cbmInfo->secKeychainCallbackInfo.keychain) CFRelease(cbmInfo->secKeychainCallbackInfo.keychain); + free(cbmInfo); + CFRelease(timer); +} + +static SecKeychainItemRef createItemReference(const Item &inItem) +{ + SecKeychainItemRef itemRef = (inItem) ? inItem->handle() : 0; + if(!itemRef) { return NULL; } + +#if SECTRUST_OSX + SecItemClass itemClass = Schema::itemClassFor(inItem->recordType()); + if (itemClass == kSecCertificateItemClass) { + SecCertificateRef certRef = SecCertificateCreateFromItemImplInstance((SecCertificateRef)itemRef); + CFRelease(itemRef); /* certRef maintains its own internal reference to itemRef */ + itemRef = (SecKeychainItemRef) certRef; + } +#endif + return itemRef; +} + +static SecKeychainRef createKeychainReference(const Keychain &inKeychain) +{ + return (inKeychain) ? inKeychain->handle() : 0; +} + void CCallbackMgr::AlertClients(const list &eventCallbacks, SecKeychainEvent inEvent, pid_t inPid, const Keychain &inKeychain, const Item &inItem) { - secdebug("kcnotify", "dispatch event %ld pid %d keychain %p item %p", + secinfo("kcnotify", "dispatch event %ld pid %d keychain %p item %p", (unsigned long)inEvent, inPid, &inKeychain, !!inItem ? &*inItem : NULL); // Iterate through callbacks, looking for those registered for inEvent @@ -170,15 +255,37 @@ void CCallbackMgr::AlertClients(const list &eventCallbacks, if (!(ix->mEventMask & theMask)) continue; - SecKeychainCallbackInfo cbInfo; - cbInfo.version = 0; // @@@ kKeychainAPIVersion; - cbInfo.item = inItem ? inItem->handle() : 0; - cbInfo.keychain = inKeychain ? inKeychain->handle() : 0; - cbInfo.pid = inPid; + if(!(ix->mActive)) { + // We haven't received our callback from this CFRunLoop yet. Assume it's not being pumped, and don't schedule. + secdebug("kcnotify", "not sending event to run loop %p", ix->mRunLoop); + continue; + } + + // The previous notification system required a CFRunLoop to be executing. Schedule the client's notifications back on their CFRunLoop, just in case it's important. + CFRunLoopRef runLoop = ix->mRunLoop; + secdebug("kcnotify", "sending event to runloop %p", runLoop); + + // Set up our callback structures + CallbackMgrInfo* cbmInfo = (CallbackMgrInfo*) calloc(sizeof(CallbackMgrInfo), 1); + + cbmInfo->secKeychainCallbackInfo.version = 0; // @@@ kKeychainAPIVersion; + cbmInfo->secKeychainCallbackInfo.item = createItemReference(inItem); + cbmInfo->secKeychainCallbackInfo.keychain = createKeychainReference(inKeychain); + cbmInfo->secKeychainCallbackInfo.pid = inPid; + + cbmInfo->event = inEvent; + cbmInfo->callback = ix->mCallback; + cbmInfo->callbackContext = ix->mContext; + + CFRunLoopTimerContext ctx; + memset(&ctx, 0, sizeof(ctx)); + ctx.info = cbmInfo; + + // make a run loop timer + CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent(), 0, 0, 0, CCallbackMgr::tellClient, &ctx); - ix->mCallback(inEvent, &cbInfo, ix->mContext); - if (cbInfo.item) CFRelease(cbInfo.item); - if (cbInfo.keychain) CFRelease(cbInfo.keychain); + // Actually call the callback the next time the run loop fires + CFRunLoopAddTimer(runLoop, timerRef, kCFRunLoopDefaultMode); } } diff --git a/OSX/libsecurity_keychain/lib/CCallbackMgr.h b/OSX/libsecurity_keychain/lib/CCallbackMgr.h index 52ea8d11..602d951d 100644 --- a/OSX/libsecurity_keychain/lib/CCallbackMgr.h +++ b/OSX/libsecurity_keychain/lib/CCallbackMgr.h @@ -51,7 +51,8 @@ class CallbackInfo public: ~CallbackInfo(); CallbackInfo(); - CallbackInfo(SecKeychainCallback inCallbackFunction,SecKeychainEventMask inEventMask,void *inContext); + CallbackInfo(SecKeychainCallback inCallbackFunction,SecKeychainEventMask inEventMask,void *inContext, CFRunLoopRef runLoop); + CallbackInfo(const CallbackInfo& cb); bool operator ==(const CallbackInfo& other) const; bool operator !=(const CallbackInfo& other) const; @@ -59,6 +60,8 @@ public: SecKeychainCallback mCallback; SecKeychainEventMask mEventMask; void *mContext; + CFRunLoopRef mRunLoop; + bool mActive; }; // typedefs @@ -89,9 +92,13 @@ private: void consume (SecurityServer::NotificationDomain domain, SecurityServer::NotificationEvent whichEvent, const CssmData &data); - static void AlertClients(const list &eventCallbacks, SecKeychainEvent inEvent, pid_t inPid, + void AlertClients(const list &eventCallbacks, SecKeychainEvent inEvent, pid_t inPid, const Keychain& inKeychain, const Item &inItem); + // Use these as a CFRunLoop callback + static void tellClient(CFRunLoopTimerRef timer, void* ctx); + static void cfrunLoopActive(CFRunLoopTimerRef timer, void* info); + list mEventCallbacks; }; diff --git a/OSX/libsecurity_keychain/lib/Certificate.cpp b/OSX/libsecurity_keychain/lib/Certificate.cpp index 0b7cc0b2..b4b0280f 100644 --- a/OSX/libsecurity_keychain/lib/Certificate.cpp +++ b/OSX/libsecurity_keychain/lib/Certificate.cpp @@ -741,10 +741,10 @@ Certificate::verifyEncoding(CSSM_DATA_PTR data) if (mHaveTypeAndEncoding) { if (mType < CSSM_CERT_X_509v1 || mType > CSSM_CERT_X_509v3) { - secdebug("Certificate", "verifyEncoding: certificate has custom type (%d)", (int)mType); + secinfo("Certificate", "verifyEncoding: certificate has custom type (%d)", (int)mType); } if (mEncoding < CSSM_CERT_ENCODING_BER || mEncoding > CSSM_CERT_ENCODING_DER) { - secdebug("Certificate", "verifyEncoding: certificate has custom encoding (%d)", (int)mEncoding); + secinfo("Certificate", "verifyEncoding: certificate has custom encoding (%d)", (int)mEncoding); } } @@ -760,16 +760,16 @@ Certificate::verifyEncoding(CSSM_DATA_PTR data) CSSM_SIZE tagLength = (CSSM_SIZE)((uintptr_t)derInfo.content.data - (uintptr_t)der.data); CSSM_SIZE derLength = (CSSM_SIZE)derInfo.content.length + tagLength; if (derLength != data->Length) { - secdebug("Certificate", "Certificate DER length is %d, but data length is %d", + secinfo("Certificate", "Certificate DER length is %d, but data length is %d", (int)derLength, (int)data->Length); // will adjust data size if DER length is positive, but smaller than actual length if ((derLength > 0) && (derLength < data->Length)) { verifiedLength = derLength; - secdebug("Certificate", "Will adjust certificate data length to %d", + secinfo("Certificate", "Will adjust certificate data length to %d", (int)derLength); } else { - secdebug("Certificate", "Certificate encoding invalid (DER length is %d)", + secinfo("Certificate", "Certificate encoding invalid (DER length is %d)", (int)derLength); return false; } @@ -778,7 +778,7 @@ Certificate::verifyEncoding(CSSM_DATA_PTR data) } else { // failure to decode provided data as DER sequence - secdebug("Certificate", "Certificate not in DER encoding (error %d)", + secinfo("Certificate", "Certificate not in DER encoding (error %d)", (int)drtn); return false; } @@ -787,7 +787,7 @@ Certificate::verifyEncoding(CSSM_DATA_PTR data) if (verifiedLength > 0) { // setData acquires the mMutex lock, so we call it while not holding the lock setData((UInt32)verifiedLength, data->Data); - secdebug("Certificate", "Adjusted certificate data length to %d", + secinfo("Certificate", "Adjusted certificate data length to %d", (int)verifiedLength); } @@ -797,24 +797,17 @@ Certificate::verifyEncoding(CSSM_DATA_PTR data) const CssmData & Certificate::data() { - CssmDataContainer *data = NULL; - bool hasKeychain = false; - bool verified = false; - { - StLock_(mMutex); - data = mData.get(); - hasKeychain = (mKeychain != NULL); - verified = mEncodingVerified; - } + StLock _(mMutex); + + CssmDataContainer *data = mData.get(); + bool hasKeychain = (mKeychain != NULL); + bool verified = mEncodingVerified; // If data has been set but not yet verified, verify it now. if (!verified && data) { // verifyEncoding might modify mData, so refresh the data container verified = verifyEncoding(data); - { - StLock_(mMutex); - data = mData.get(); - } + data = mData.get(); } // If data isn't set at this point, try to read it from the db record @@ -823,20 +816,16 @@ Certificate::data() // Make sure mUniqueId is set. dbUniqueRecord(); CssmDataContainer _data; - { - StLock_(mMutex); - mData = NULL; - /* new data allocated by CSPDL, implicitly freed by CssmDataContainer */ - mUniqueId->get(NULL, &_data); - } + + mData = NULL; + /* new data allocated by CSPDL, implicitly freed by CssmDataContainer */ + mUniqueId->get(NULL, &_data); + /* this saves a copy to be freed at destruction and to be passed to caller */ setData((UInt32)_data.length(), _data.data()); // verifyEncoding might modify mData, so refresh the data container verified = verifyEncoding(&_data); - { - StLock_(mMutex); - data = mData.get(); - } + data = mData.get(); } // If the data hasn't been set we can't return it. diff --git a/OSX/libsecurity_keychain/lib/CertificateRequest.h b/OSX/libsecurity_keychain/lib/CertificateRequest.h index fcecb54c..144aae80 100644 --- a/OSX/libsecurity_keychain/lib/CertificateRequest.h +++ b/OSX/libsecurity_keychain/lib/CertificateRequest.h @@ -37,7 +37,7 @@ #include #include -#define certReqDbg(args...) secdebug("certReq", ## args) +#define certReqDbg(args...) secinfo("certReq", ## args) namespace Security { diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.cpp b/OSX/libsecurity_keychain/lib/CertificateValues.cpp index 4025c9f6..7fd526d1 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.cpp +++ b/OSX/libsecurity_keychain/lib/CertificateValues.cpp @@ -39,6 +39,7 @@ /* FIXME including SecCertificateInternalP.h here produces errors; investigate */ extern "C" CFDataRef SecCertificateCopyIssuerSequenceP(SecCertificateRefP certificate); extern "C" CFDataRef SecCertificateCopySubjectSequenceP(SecCertificateRefP certificate); +extern "C" CFDictionaryRef SecCertificateCopyAttributeDictionaryP(SecCertificateRefP certificate); extern "C" void appendPropertyP(CFMutableArrayRef properties, CFStringRef propertyType, CFStringRef label, CFTypeRef value); @@ -419,6 +420,18 @@ CFDataRef CertificateValues::copySubjectSequence(CFErrorRef *error) return result; } +CFDictionaryRef CertificateValues::copyAttributeDictionary(CFErrorRef *error) +{ + CFDictionaryRef result = NULL; + SecCertificateRefP certificateP = getSecCertificateRefP(error); + if (certificateP) + { + result = SecCertificateCopyAttributeDictionaryP(certificateP); + CFRelease(certificateP); + } + return result; +} + bool CertificateValues::isValid(CFAbsoluteTime verifyTime, CFErrorRef *error) { bool result = NULL; diff --git a/OSX/libsecurity_keychain/lib/CertificateValues.h b/OSX/libsecurity_keychain/lib/CertificateValues.h index 5f56bbe9..37de693f 100644 --- a/OSX/libsecurity_keychain/lib/CertificateValues.h +++ b/OSX/libsecurity_keychain/lib/CertificateValues.h @@ -53,6 +53,7 @@ public: CFDataRef copyNormalizedSubjectContent(CFErrorRef *error); CFDataRef copyIssuerSequence(CFErrorRef *error); CFDataRef copySubjectSequence(CFErrorRef *error); + CFDictionaryRef copyAttributeDictionary(CFErrorRef *error); bool isValid(CFAbsoluteTime verifyTime, CFErrorRef *error); CFAbsoluteTime notValidBefore(CFErrorRef *error); CFAbsoluteTime notValidAfter(CFErrorRef *error); diff --git a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp index 4836f4dc..9e4e9df6 100644 --- a/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp +++ b/OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp @@ -41,6 +41,7 @@ #include #include #include +#include dispatch_once_t AppSandboxChecked; xpc_object_t KeychainHomeFromXPC; @@ -96,7 +97,7 @@ void PasswordDBLookup::lookupInfoOnUID (uid_t uid) mCurrent = uid; mTime = currentTime; - secdebug("secpref", "uid=%d caching home=%s", uid, pw->pw_dir); + secinfo("secpref", "uid=%d caching home=%s", uid, pw->pw_dir); endpwent(); } @@ -113,7 +114,7 @@ PasswordDBLookup *DLDbListCFPref::mPdbLookup = NULL; DLDbListCFPref::DLDbListCFPref(SecPreferencesDomain domain) : mDomain(domain), mPropertyList(NULL), mChanged(false), mSearchListSet(false), mDefaultDLDbIdentifierSet(false), mLoginDLDbIdentifierSet(false) { - secdebug("secpref", "New DLDbListCFPref %p for domain %d", this, domain); + secinfo("secpref", "New DLDbListCFPref %p for domain %d", this, domain); loadPropertyList(true); } @@ -123,7 +124,7 @@ void DLDbListCFPref::set(SecPreferencesDomain domain) mDomain = domain; - secdebug("secpref", "DLDbListCFPref %p domain set to %d", this, domain); + secinfo("secpref", "DLDbListCFPref %p domain set to %d", this, domain); if (loadPropertyList(true)) resetCachedValues(); @@ -164,7 +165,7 @@ DLDbListCFPref::loadPropertyList(bool force) MacOSError::throwMe(errSecInvalidPrefsDomain); } - secdebug("secpref", "force=%s prefsPath=%s", force ? "true" : "false", + secinfo("secpref", "force=%s prefsPath=%s", force ? "true" : "false", prefsPath.c_str()); CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); @@ -973,6 +974,8 @@ DLDbListCFPref::defaultDLDbIdentifier(const DLDbIdentifier &dlDbIdentifier) } } +// Caution: if the backing file for the defaultDLDbIdentifier doesn't exist (or if the plist file is corrupt), +// this will return a DLDbIdentifier with a NULL impl const DLDbIdentifier & DLDbListCFPref::defaultDLDbIdentifier() { @@ -988,9 +991,9 @@ DLDbListCFPref::defaultDLDbIdentifier() CFDictionaryRef defaultDict = reinterpret_cast(CFArrayGetValueAtIndex(defaultArray, 0)); try { - secdebug("secpref", "getting default DLDbIdentifier from defaultDict"); + secinfo("secpref", "getting default DLDbIdentifier from defaultDict"); mDefaultDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(defaultDict); - secdebug("secpref", "now we think the default keychain is %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : ""); + secinfo("secpref", "now we think the default keychain is %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : ""); } catch (...) { @@ -1001,26 +1004,29 @@ DLDbListCFPref::defaultDLDbIdentifier() if (!defaultArray) { - // If the Panther style login keychain actually exists we use that otherwise no // default is set. mDefaultDLDbIdentifier = loginDLDbIdentifier(); - secdebug("secpref", "now we think the default keychain is: %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : - "Name doesn't exist"); - + + //Since we might be changing the keychain filename, we have to stat the right file. Delegate the knowledge of which files to StorageManager; DLDbListCFPref should contain "login.keychain". + DLDbIdentifier actualIdentifier = KeychainCore::StorageManager::mungeDLDbIdentifier(mDefaultDLDbIdentifier, false); + secinfo("secpref", "now we think the default keychain is: %s (actual: %s)", + (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "Name doesn't exist", + (actualIdentifier) ? actualIdentifier.dbName() : "Name doesn't exist"); + struct stat st; int st_result = -1; - - if (mDefaultDLDbIdentifier.mImpl != NULL) - { - st_result = stat(mDefaultDLDbIdentifier.dbName(), &st); - } - + + if (mDefaultDLDbIdentifier.mImpl != NULL && actualIdentifier.mImpl != NULL) + { + st_result = stat(actualIdentifier.dbName(), &st); + } + if (st_result) { - secdebug("secpref", "stat(%s) -> %d", mDefaultDLDbIdentifier.dbName(), st_result); + secinfo("secpref", "stat(%s) -> %d", actualIdentifier.dbName(), st_result); mDefaultDLDbIdentifier = DLDbIdentifier(); // initialize a NULL keychain - secdebug("secpref", "after DLDbIdentifier(), we think the default keychain is %s", static_cast(mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : ""); + secinfo("secpref", "after DLDbIdentifier(), we think the default keychain is %s", static_cast(mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : ""); } } @@ -1055,9 +1061,9 @@ DLDbListCFPref::loginDLDbIdentifier() CFDictionaryRef loginDict = reinterpret_cast(CFArrayGetValueAtIndex(loginArray, 0)); try { - secdebug("secpref", "Getting login DLDbIdentifier from loginDict"); + secinfo("secpref", "Getting login DLDbIdentifier from loginDict"); mLoginDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(loginDict); - secdebug("secpref", "we think the login keychain is %s", static_cast(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : ""); + secinfo("secpref", "we think the login keychain is %s", static_cast(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : ""); } catch (...) { @@ -1069,7 +1075,7 @@ DLDbListCFPref::loginDLDbIdentifier() if (!loginArray) { mLoginDLDbIdentifier = LoginDLDbIdentifier(); - secdebug("secpref", "after LoginDLDbIdentifier(), we think the login keychain is %s", static_cast(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : ""); + secinfo("secpref", "after LoginDLDbIdentifier(), we think the login keychain is %s", static_cast(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : ""); } mLoginDLDbIdentifierSet = true; diff --git a/OSX/libsecurity_keychain/lib/DynamicDLDBList.cpp b/OSX/libsecurity_keychain/lib/DynamicDLDBList.cpp index 0539e474..35e93069 100644 --- a/OSX/libsecurity_keychain/lib/DynamicDLDBList.cpp +++ b/OSX/libsecurity_keychain/lib/DynamicDLDBList.cpp @@ -140,7 +140,7 @@ DynamicDLDBList::_load() if (serviceMask & CSSM_SERVICE_DL) { string moduleID = (*commonIt)->moduleID(); - secdebug("dynamic", "Loading dynamic %sDL module: %s", + secinfo("dynamic", "Loading dynamic %sDL module: %s", (serviceMask & CSSM_SERVICE_CSP) ? "CSP/" : "", moduleID.c_str()); /* Register module for callbacks and load it. */ @@ -160,7 +160,7 @@ DynamicDLDBList::_load() bool hasCSP = csp.find(MDSClient::Attribute("ModuleID") == moduleID && MDSClient::Attribute("SSID") == subserviceID) != csp.end(); - secdebug("dynamic", "Adding databases from %sDL SSID %lu module: %s", + secinfo("dynamic", "Adding databases from %sDL SSID %lu module: %s", hasCSP ? "CSP/" : "", (unsigned long)subserviceID, moduleID.c_str()); list_changed |= _add(moduleGuid, subserviceID, hasCSP ? CSSM_SERVICE_CSP | CSSM_SERVICE_DL : CSSM_SERVICE_DL); @@ -190,7 +190,7 @@ void DynamicDLDBList::callback(const Guid &guid, uint32 subserviceID, CSSM_SERVICE_TYPE subserviceType, CSSM_MODULE_EVENT eventType) { - secdebug("event", "Received callback from guid: %s ssid: %lu type: %lu event: %lu", + secinfo("event", "Received callback from guid: %s ssid: %lu type: %lu event: %lu", guid.toString().c_str(), (unsigned long)subserviceID, (unsigned long)subserviceType, (unsigned long)eventType); StLock_(mMutex); @@ -202,14 +202,14 @@ DynamicDLDBList::callback(const Guid &guid, uint32 subserviceID, if (eventType == CSSM_NOTIFY_INSERT) { /* A DL or CSP/DL was inserted. */ - secdebug("dynamic", "%sDL module: %s SSID: %lu inserted", + secinfo("dynamic", "%sDL module: %s SSID: %lu inserted", (subserviceType & CSSM_SERVICE_CSP) ? "CSP/" : "", guid.toString().c_str(), (unsigned long)subserviceID); list_changed = _add(guid, subserviceID, subserviceType); } else if (eventType == CSSM_NOTIFY_REMOVE) { /* A DL or CSP/DL was removed. */ - secdebug("dynamic", "%sDL module: %s SSID: %lu removed", + secinfo("dynamic", "%sDL module: %s SSID: %lu removed", (subserviceType & CSSM_SERVICE_CSP) ? "CSP/" : "", guid.toString().c_str(), (unsigned long)subserviceID); list_changed = _remove(guid, subserviceID, subserviceType); } diff --git a/OSX/libsecurity_keychain/lib/Globals.cpp b/OSX/libsecurity_keychain/lib/Globals.cpp index 6c299b92..fc29e3ee 100644 --- a/OSX/libsecurity_keychain/lib/Globals.cpp +++ b/OSX/libsecurity_keychain/lib/Globals.cpp @@ -46,6 +46,9 @@ mUI(true), mIntegrityProtection(false) if (integrity && CFGetTypeID(integrity) == CFBooleanGetTypeID()) { mIntegrityProtection = CFBooleanGetValue((CFBooleanRef)integrity); CFRelease(integrity); + } else { + // preference not set: defaulting to true + mIntegrityProtection = true; } } diff --git a/OSX/libsecurity_keychain/lib/Identity.cpp b/OSX/libsecurity_keychain/lib/Identity.cpp index 826ed985..f11974f4 100644 --- a/OSX/libsecurity_keychain/lib/Identity.cpp +++ b/OSX/libsecurity_keychain/lib/Identity.cpp @@ -30,38 +30,99 @@ #include #include +#include +#include +#include + using namespace KeychainCore; Identity::Identity(const SecPointer &privateKey, + const SecPointer &certificate) : + mPrivateKey(privateKey->handle()), + mCertificate(certificate) +{ +} + +Identity::Identity(SecKeyRef privateKey, const SecPointer &certificate) : - mPrivateKey(privateKey), + mPrivateKey((SecKeyRef)CFRetain(privateKey)), mCertificate(certificate) { } Identity::Identity(const StorageManager::KeychainList &keychains, const SecPointer &certificate) : - mCertificate(certificate) + mPrivateKey(NULL), mCertificate(certificate) { - // Find a key whose label matches the publicKeyHash of the public key in the certificate. - KCCursor keyCursor(keychains, CSSM_DL_DB_RECORD_PRIVATE_KEY, NULL); - keyCursor->add(CSSM_DB_EQUAL, KeySchema::Label, certificate->publicKeyHash()); - - Item key; - if (!keyCursor->next(key)) - MacOSError::throwMe(errSecItemNotFound); - - SecPointer keyItem(static_cast(&*key)); - mPrivateKey = keyItem; + // Find a key whose label matches the publicKeyHash of the public key in the certificate. + CssmData publicKeyHash = certificate->publicKeyHash(); + CFRef keyHash = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, + (const UInt8 *)publicKeyHash.data(), + publicKeyHash.length(), + kCFAllocatorNull); + // First, try the new iOS keychain. + { + const void *keys[] = { kSecClass, kSecAttrKeyClass, kSecAttrApplicationLabel, kSecReturnRef, kSecAttrNoLegacy }; + const void *values[] = { kSecClassKey, kSecAttrKeyClassPrivate, keyHash, kCFBooleanTrue, kCFBooleanTrue }; + CFRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)&mPrivateKey); + if (status == errSecSuccess) { + return; + } + } + // Second, try the legacy OS X keychain(s). + { + mPrivateKey = NULL; + CFRef dynamicKeychains; + SecKeychainCopyDomainSearchList(kSecPreferencesDomainDynamic, dynamicKeychains.take()); + CFRef dynamicSearchList = CFArrayCreateMutable(kCFAllocatorDefault, (CFIndex)keychains.size(), &kCFTypeArrayCallBacks); + CFRef searchList = CFArrayCreateMutable(kCFAllocatorDefault, (CFIndex)keychains.size(), &kCFTypeArrayCallBacks); + for (StorageManager::KeychainList::const_iterator it = keychains.begin(), end = keychains.end(); it != end; ++it) { + if (dynamicKeychains && CFArrayGetCount(dynamicKeychains) && CFArrayContainsValue(dynamicKeychains, CFRangeMake(0, CFArrayGetCount(dynamicKeychains)), **it)) { + CFArrayAppendValue(dynamicSearchList, **it); + } + CFArrayAppendValue(searchList, **it); + } + const void *keys[] = { kSecClass, kSecAttrKeyClass, kSecAttrApplicationLabel, kSecReturnRef, kSecMatchSearchList }; + const void *values[] = { kSecClassKey, kSecAttrKeyClassPrivate, keyHash, kCFBooleanTrue, searchList }; + CFRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)&mPrivateKey); + if (status != errSecSuccess) { + if (CFArrayGetCount(dynamicSearchList)) { + // Legacy way is used for dynamic keychains because SmartCards keychain does not support strict CSSM queries which are generated in SecItemCopyMatching + // Find a key whose label matches the publicKeyHash of the public key in the certificate. + KCCursor keyCursor(keychains, CSSM_DL_DB_RECORD_PRIVATE_KEY, NULL); + keyCursor->add(CSSM_DB_EQUAL, KeySchema::Label, certificate->publicKeyHash()); + + Item key; + if (!keyCursor->next(key)) + MacOSError::throwMe(errSecItemNotFound); + + SecPointer keyItem(static_cast(&*key)); + mPrivateKey = keyItem->handle(); + } + else { + MacOSError::throwMe(errSecItemNotFound); + } + } + } } Identity::~Identity() throw() { + if (mPrivateKey) + CFRelease(mPrivateKey); } SecPointer Identity::privateKey() const { - return mPrivateKey; + return SecPointer(KeyItem::required(mPrivateKey)); } SecPointer @@ -70,6 +131,12 @@ Identity::certificate() const return mCertificate; } +SecKeyRef +Identity::privateKeyRef() const +{ + return mPrivateKey; +} + bool Identity::operator < (const Identity &other) const { @@ -88,9 +155,22 @@ Identity::operator == (const Identity &other) const bool Identity::equal(SecCFObject &other) { - CFHashCode this_hash = hash(); - CFHashCode other_hash = other.hash(); - return (this_hash == other_hash); + // Compare certificates first. + if (Identity *otherIdentity = dynamic_cast(&other)) { + Certificate *pCert = mCertificate.get(), *pOtherCert = otherIdentity->mCertificate.get(); + if (pCert == NULL || pOtherCert == NULL) { + return pCert == pOtherCert; + } + + if (pCert->equal(*pOtherCert)) { + // Compare private keys. + if (mPrivateKey == NULL || otherIdentity->mPrivateKey == NULL) { + return mPrivateKey == otherIdentity->mPrivateKey; + } + return CFEqual(mPrivateKey, otherIdentity->mPrivateKey); + } + } + return false; } CFHashCode Identity::hash() @@ -107,12 +187,8 @@ CFHashCode Identity::hash() struct keyAndCertHash hashes; memset(&hashes, 0, sizeof(struct keyAndCertHash)); - KeyItem* pKeyItem = mPrivateKey.get(); - if (NULL != pKeyItem) - { - hashes.keyHash = pKeyItem->hash(); - } - + hashes.keyHash = CFHash(mPrivateKey); + Certificate* pCert = mCertificate.get(); if (NULL != pCert) { diff --git a/OSX/libsecurity_keychain/lib/Identity.h b/OSX/libsecurity_keychain/lib/Identity.h index 9a1d68c7..29170a27 100644 --- a/OSX/libsecurity_keychain/lib/Identity.h +++ b/OSX/libsecurity_keychain/lib/Identity.h @@ -43,12 +43,15 @@ public: SECCFFUNCTIONS(Identity, SecIdentityRef, errSecInvalidItemRef, gTypes().Identity) Identity(const SecPointer &privateKey, - const SecPointer &certificate); + const SecPointer &certificate); + Identity(const SecKeyRef privateKey, + const SecPointer &certificate); Identity(const StorageManager::KeychainList &keychains, const SecPointer &certificate); virtual ~Identity() throw(); SecPointer privateKey() const; SecPointer certificate() const; + SecKeyRef privateKeyRef() const; bool operator < (const Identity &other) const; bool operator == (const Identity &other) const; @@ -57,7 +60,7 @@ public: CFHashCode hash(); private: - SecPointer mPrivateKey; + SecKeyRef mPrivateKey; SecPointer mCertificate; }; diff --git a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp index e7f24d82..cbee7fa7 100644 --- a/OSX/libsecurity_keychain/lib/IdentityCursor.cpp +++ b/OSX/libsecurity_keychain/lib/IdentityCursor.cpp @@ -1,15 +1,15 @@ /* * Copyright (c) 2002-2008,2011-2012 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@ * * IdentityCursor.cpp -- Working with IdentityCursor @@ -47,20 +47,22 @@ IdentityCursorPolicyAndID::IdentityCursorPolicyAndID(const StorageManager::Keych mPreferredIdentityChecked(false), mPreferredIdentity(nil) { - if (mPolicy) - CFRetain(mPolicy); - - if (mIDString) - CFRetain(mIDString); + if (mPolicy) { + CFRetain(mPolicy); + } + if (mIDString) { + CFRetain(mIDString); + } } IdentityCursorPolicyAndID::~IdentityCursorPolicyAndID() throw() { - if (mPolicy) - CFRelease(mPolicy); - - if (mIDString) - CFRelease(mIDString); + if (mPolicy) { + CFRelease(mPolicy); + } + if (mIDString) { + CFRelease(mIDString); + } } void @@ -105,7 +107,7 @@ IdentityCursorPolicyAndID::findPreferredIdentity() SecPointer identity(new Identity(mSearchList /*keychains*/, certificate)); mPreferredIdentity = identity; - + if (certItemRef) CFRelease(certItemRef); } @@ -221,7 +223,7 @@ IdentityCursorPolicyAndID::next(SecPointer &identity) break; } } // for(;;) - + if ( identityOK ) { identity = currIdentity; // caller will release the identity @@ -311,7 +313,7 @@ IdentityCursor::next(SecPointer &identity) Item key; if (!mKeyCursor->next(key)) return false; - + mCurrentKey = static_cast(key.get()); CssmClient::DbUniqueRecord uniqueId = mCurrentKey->dbUniqueRecord(); @@ -319,7 +321,7 @@ IdentityCursor::next(SecPointer &identity) dbAttributes.add(KeySchema::Label); uniqueId->get(&dbAttributes, NULL); const CssmData &keyHash = dbAttributes[0]; - + mCertificateCursor = KCCursor(mSearchList, CSSM_DL_DB_RECORD_X509_CERTIFICATE, NULL); mCertificateCursor->add(CSSM_DB_EQUAL, Schema::kX509CertificatePublicKeyHash, keyHash); @@ -337,7 +339,7 @@ IdentityCursor::next(SecPointer &identity) CFRelease(kerbKDCCertPubKeyHash); } } - + Item cert; if (mCertificateCursor->next(cert)) { diff --git a/OSX/libsecurity_keychain/lib/Item.cpp b/OSX/libsecurity_keychain/lib/Item.cpp index 025c8b3a..07907423 100644 --- a/OSX/libsecurity_keychain/lib/Item.cpp +++ b/OSX/libsecurity_keychain/lib/Item.cpp @@ -65,6 +65,31 @@ using namespace CSSMDateTimeUtils; // ItemImpl // +ItemImpl *ItemImpl::required(SecKeychainItemRef ptr) +{ + if (ptr != NULL) { + if (ItemImpl *pp = optional(ptr)) { + return pp; + } + } + MacOSError::throwMe(errSecInvalidItemRef); +} + +ItemImpl *ItemImpl::optional(SecKeychainItemRef ptr) +{ + if (SecCFObject *p = KeyItem::fromSecKeyRef(ptr)) { + return dynamic_cast(p); + } else if (SecCFObject *p = SecCFObject::optional(ptr)) { + if (ItemImpl *pp = dynamic_cast(p)) { + return pp; + } else { + MacOSError::throwMe(errSecInvalidItemRef); + } + } else { + return NULL; + } +} + // NewItemImpl constructor ItemImpl::ItemImpl(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, bool dontDoAttributes) : mDbAttributes(new DbAttributes()), @@ -156,7 +181,8 @@ ItemImpl::ItemImpl(ItemImpl &item) : if (item.mKeychain) { // get the entire source item from its keychain. This requires figuring // out the schema for the item based on its record type. - fillDbAttributesFromSchema(*mDbAttributes, item.recordType()); + // Ask the remote item to fill our attributes dictionary, because it probably has an attached keychain to ask + item.fillDbAttributesFromSchema(*mDbAttributes, item.recordType()); item.getContent(mDbAttributes.get(), mData.get()); } @@ -179,7 +205,7 @@ ItemImpl::~ItemImpl() Mutex* -ItemImpl::getMutexForObject() +ItemImpl::getMutexForObject() const { if (mKeychain.get()) { @@ -249,7 +275,7 @@ void ItemImpl::fillDbAttributesFromSchema(DbAttributes& dbAttributes, CSSM_DB_RE SecKeychainAttributeInfo* infos; keychain->getAttributeInfoForItemID(recordType, &infos); - secdebugfunc("integrity", "filling %u attributes for type %u", (unsigned int)infos->count, recordType); + secnotice("integrity", "filling %u attributes for type %u", (unsigned int)infos->count, recordType); for (uint32 i = 0; i < infos->count; i++) { CSSM_DB_ATTRIBUTE_INFO info; @@ -267,27 +293,27 @@ void ItemImpl::fillDbAttributesFromSchema(DbAttributes& dbAttributes, CSSM_DB_RE DbAttributes* ItemImpl::getCurrentAttributes() { DbAttributes* dbAttributes; - secdebugfunc("integrity", "getting current attributes..."); + secnotice("integrity", "getting current attributes..."); if(mUniqueId.get()) { // If we have a unique id, there's an item in the database backing us. Ask for its attributes. - dbAttributes = new DbAttributes(mUniqueId->database(), 1); + dbAttributes = new DbAttributes(dbUniqueRecord()->database(), 1); fillDbAttributesFromSchema(*dbAttributes, recordType()); mUniqueId->get(dbAttributes, NULL); // and fold in any updates. if(mDbAttributes.get()) { - secdebugfunc("integrity", "adding %d attributes from mDbAttributes", mDbAttributes->size()); + secnotice("integrity", "adding %d attributes from mDbAttributes", mDbAttributes->size()); dbAttributes->updateWithDbAttributes(&(*mDbAttributes.get())); } } else if (mDbAttributes.get()) { // We don't have a backing item, so all our attributes are in mDbAttributes. Copy them. - secdebugfunc("integrity", "no unique id, using %d attributes from mDbAttributes", mDbAttributes->size()); + secnotice("integrity", "no unique id, using %d attributes from mDbAttributes", mDbAttributes->size()); dbAttributes = new DbAttributes(); dbAttributes->updateWithDbAttributes(&(*mDbAttributes.get())); } else { // No attributes at all. We should maybe throw here, but let's not. - secdebugfunc("integrity", "no attributes at all"); + secnotice("integrity", "no attributes at all"); dbAttributes = new DbAttributes(); } dbAttributes->recordType(recordType()); @@ -309,7 +335,7 @@ void ItemImpl::encodeAttributesFromDictionary(CssmOwnedData &attributeBlob, DbAt CFRef attributes; attributes.take(CFDictionaryCreateMutable(NULL, dbAttributes->size(), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - secdebugfunc("integrity", "looking at %d attributes", dbAttributes->size()); + secnotice("integrity", "looking at %d attributes", dbAttributes->size()); // TODO: include record type and semantic information? for(int i = 0; i < dbAttributes->size(); i++) { @@ -435,19 +461,19 @@ void ItemImpl::computeDigestFromDictionary(CssmOwnedData &sha2, DbAttributes* db sha2.length(CC_SHA256_DIGEST_LENGTH); CC_SHA256(attributeBlob.get().data(), static_cast(attributeBlob.get().length()), sha2); - secdebugfunc("integrity", "finished: %s", sha2.get().toHex().c_str()); + secnotice("integrity", "finished: %s", sha2.get().toHex().c_str()); } catch (MacOSError mose) { - secdebugfunc("integrity", "MacOSError: %d", (int)mose.osStatus()); + secnotice("integrity", "MacOSError: %d", (int)mose.osStatus()); } catch (...) { - secdebugfunc("integrity", "unknown exception"); + secnotice("integrity", "unknown exception"); } } void ItemImpl::addIntegrity(Access &access, bool force) { - secdebugfunc("integrity", "called"); + secnotice("integrity", "called"); if(!force && (!mKeychain || !mKeychain->hasIntegrityProtection())) { - secdebugfunc("integrity", "skipping integrity add due to keychain version\n"); + secnotice("integrity", "skipping integrity add due to keychain version\n"); return; } @@ -462,17 +488,17 @@ void ItemImpl::addIntegrity(Access &access, bool force) { if(acls.size() >= 1) { // Use the existing ACL acl = acls[0]; - secdebugfunc("integrity", "previous integrity acl exists; setting integrity"); + secnotice("integrity", "previous integrity acl exists; setting integrity"); acl->setIntegrity(digest.get()); // Delete all extra ACLs for(int i = 1; i < acls.size(); i++) { - secdebugfunc("integrity", "extra integrity acls exist; removing %d",i); + secnotice("integrity", "extra integrity acls exist; removing %d",i); acls[i]->remove(); } } else if(acls.size() == 0) { // Make a new ACL - secdebugfunc("integrity", "no previous integrity acl exists; making a new one"); + secnotice("integrity", "no previous integrity acl exists; making a new one"); acl = new ACL(digest.get()); access.add(acl); } @@ -480,7 +506,7 @@ void ItemImpl::addIntegrity(Access &access, bool force) { void ItemImpl::setIntegrity(bool force) { if(!force && (!mKeychain || !mKeychain->hasIntegrityProtection())) { - secdebugfunc("integrity", "skipping integrity set due to keychain version"); + secnotice("integrity", "skipping integrity set due to keychain version"); return; } @@ -500,7 +526,7 @@ void ItemImpl::addIntegrity(Access &access, bool force) { void ItemImpl::setIntegrity(AclBearer &bearer, bool force) { if(!force && (!mKeychain || !mKeychain->hasIntegrityProtection())) { - secdebugfunc("integrity", "skipping integrity acl set due to keychain version"); + secnotice("integrity", "skipping integrity acl set due to keychain version"); return; } @@ -511,17 +537,38 @@ void ItemImpl::setIntegrity(AclBearer &bearer, bool force) { access->setAccess(bearer, true); } +void ItemImpl::removeIntegrity(const AccessCredentials *cred) { + removeIntegrity(*group(), cred); +} + +void ItemImpl::removeIntegrity(AclBearer &bearer, const AccessCredentials *cred) { + SecPointer access = new Access(bearer); + vector acls; + + access->findSpecificAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY, acls); + for(int i = 0; i < acls.size(); i++) { + acls[i]->remove(); + } + + access->findSpecificAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID, acls); + for(int i = 0; i < acls.size(); i++) { + acls[i]->remove(); + } + + access->editAccess(bearer, true, cred); +} + bool ItemImpl::checkIntegrity() { // Note: subclasses are responsible for checking themselves. // If we don't have a keychain yet, we don't have any group. Return true? if(!isPersistent()) { - secdebugfunc("integrity", "no keychain, integrity is valid?"); + secnotice("integrity", "no keychain, integrity is valid?"); return true; } if(!mKeychain || !mKeychain->hasIntegrityProtection()) { - secdebugfunc("integrity", "skipping integrity check due to keychain version"); + secnotice("integrity", "skipping integrity check due to keychain version"); return true; } @@ -538,7 +585,7 @@ bool ItemImpl::checkIntegrity() { bool ItemImpl::checkIntegrity(AclBearer& aclBearer) { if(!mKeychain || !mKeychain->hasIntegrityProtection()) { - secdebugfunc("integrity", "skipping integrity check due to keychain version"); + secnotice("integrity", "skipping integrity check due to keychain version"); return true; } @@ -559,7 +606,7 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* auto_ptr acl(new ACL(info, Allocator::standard())); for(int i = 1; i < aclInfos.count(); i++) { - secdebugfunc("integrity", "*** DUPLICATE INTEGRITY ACL, something has gone wrong"); + secnotice("integrity", "*** DUPLICATE INTEGRITY ACL, something has gone wrong"); } CssmAutoData digest(Allocator::standard()); @@ -570,7 +617,7 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* } catch (CssmError cssme) { const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); if(cssme.error == CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND) { // TODO: No entry, run migrator? @@ -579,17 +626,18 @@ bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* if(cssme.error == CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE) { // something went horribly wrong with fetching acl. - secdebugfunc("integrity", "INVALID ITEM (too many integrity acls)"); + secnotice("integrity", "INVALID ITEM (too many integrity acls)"); return false; } if(cssme.error == CSSMERR_CSP_VERIFY_FAILED) { - secdebugfunc("integrity", "MAC verification failed; something has gone very wrong"); + secnotice("integrity", "MAC verification failed; something has gone very wrong"); + return false; // No MAC, no integrity. } throw cssme; } - secdebugfunc("integrity", "***** INVALID ITEM"); + secnotice("integrity", "***** INVALID ITEM"); return false; } @@ -626,6 +674,7 @@ PrimaryKey ItemImpl::addWithCopyInfo (Keychain &keychain, bool isCopy) } // If the label (PrintName) attribute isn't specified, set a default label. + mDbAttributes->canonicalize(); // make sure we'll find the label with the thing Schema::attributeInfo returns if (!mDoNotEncrypt && !mDbAttributes->find(Schema::attributeInfo(kSecLabelItemAttr))) { // if doNotEncrypt was set all of the attributes are wrapped in the data blob. Don't calculate here. @@ -727,17 +776,31 @@ ItemImpl::add (Keychain &keychain) Item ItemImpl::copyTo(const Keychain &keychain, Access *newAccess) { + // We'll be removing any Partition or Integrity ACLs from this item during + // the copy. Note that creating a new item from this one fetches the data, + // so this process must now be on the ACL/partition ID list for this item, + // and an attacker without access can't cause this removal. + // + // The integrity and partition ID acls will get re-added once the item lands + // in the new keychain, if it supports them. If it doesn't, removing the + // integrity acl as it leaves will prevent any issues if the item is + // modified in the unsupported keychain and then re-copied back into an + // integrity keychain. + StLock_(mMutex); Item item(*this); - if (newAccess) + if (newAccess) { + newAccess->removeAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID); + newAccess->removeAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY); item->setAccess(newAccess); - else - { + } else { /* Attempt to copy the access from the current item to the newly created one. */ SSGroup myGroup = group(); if (myGroup) { SecPointer access = new Access(*myGroup); + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID); + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY); item->setAccess(access); } } @@ -768,19 +831,17 @@ ItemImpl::update() setAttribute(schema->attributeInfoFor(aRecordType, kSecModDateItemAttr), date); } - // Make sure that we have mUniqueId - dbUniqueRecord(); - Db db(mUniqueId->database()); + Db db(dbUniqueRecord()->database()); if (mDoNotEncrypt) { CSSM_DB_RECORD_ATTRIBUTE_DATA attrData; memset (&attrData, 0, sizeof (attrData)); attrData.DataRecordType = aRecordType; - mUniqueId->modifyWithoutEncryption(aRecordType, - &attrData, - mData.get(), - CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + dbUniqueRecord()->modifyWithoutEncryption(aRecordType, + &attrData, + mData.get(), + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); } else if (useSecureStorage(db)) { @@ -793,10 +854,10 @@ ItemImpl::update() } else { - mUniqueId->modify(aRecordType, - mDbAttributes.get(), - mData.get(), - CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + dbUniqueRecord()->modify(aRecordType, + mDbAttributes.get(), + mData.get(), + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); } if (!mDoNotEncrypt) @@ -820,7 +881,7 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer AclFactory aclFactory; const AccessCredentials *nullCred = aclFactory.nullCred(); - secdebugfunc("integrity", "called"); + secnotice("integrity", "called"); bool haveOldUniqueId = !!mUniqueId.get(); SSDbUniqueRecord ssUniqueId(NULL); @@ -839,7 +900,7 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer // If there aren't any attributes, make up some blank ones. if (!mDbAttributes.get()) { - secdebugfunc("integrity", "making new dbattributes"); + secnotice("integrity", "making new dbattributes"); mDbAttributes.reset(new DbAttributes()); mDbAttributes->recordType(mPrimaryKey->recordType()); } @@ -857,7 +918,7 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer if ((!access) && (haveOldUniqueId)) { // Copy the ACL from the old group. - secdebugfunc("integrity", "copying old ACL"); + secnotice("integrity", "copying old ACL"); access = new Access(*(ssGroup)); // We can't copy these over to the new item; they're going to be reset. @@ -865,7 +926,7 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID); access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY); } else if (!access) { - secdebugfunc("integrity", "setting up new ACL"); + secnotice("integrity", "setting up new ACL"); // create default access controls for the new item CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(kSecLabelItemAttr)); string printName = data ? CssmData::overlay(data->Value[0]).toString() : "keychain item"; @@ -885,7 +946,7 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer } } } else { - secdebugfunc("integrity", "passed an Access, use it"); + secnotice("integrity", "passed an Access, use it"); // Access is non-null. Do nothing. } @@ -905,17 +966,17 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer maker.initialOwner(prototype, nullCred); if(saveToNewSSGroup) { - secdebugfunc("integrity", "saving to a new SSGroup"); + secnotice("integrity", "saving to a new SSGroup"); // If we're updating an item, it has an old group and possibly an // old mUniqueId. Delete these from the database, so we can insert // new ones. if(haveOldUniqueId) { - secdebugfunc("integrity", "deleting old mUniqueId"); + secnotice("integrity", "deleting old mUniqueId"); mUniqueId->deleteRecord(); mUniqueId.release(); } else { - secdebugfunc("integrity", "no old mUniqueId"); + secnotice("integrity", "no old mUniqueId"); } // Create a new SSGroup with temporary access controls @@ -924,8 +985,7 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer try { doChange(keychain, recordType, ^{ - mUniqueId = ssDb->insert(recordType, mDbAttributes.get(), - newdata, newSSGroup, cred); + mUniqueId = ssDb->ssInsert(recordType, mDbAttributes.get(), newdata, newSSGroup, cred); }); // now finalize the access controls on the group @@ -935,29 +995,32 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer // We have to reset this after we add the integrity, since it needs the attributes mDbAttributes.reset(NULL); - transaction.success(); + transaction.commit(); } catch (CssmError cssme) { const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "caught CssmError during add: %d %s", (int) cssme.error, errStr); - newSSGroup->deleteKey(nullCred); + secnotice("integrity", "caught CssmError during add: %d %s", (int) cssme.error, errStr); + + // Delete the new SSGroup that we just created + deleteSSGroup(newSSGroup, nullCred); throw; } catch (MacOSError mose) { - secdebugfunc("integrity", "caught MacOSError during add: %d", (int) mose.osStatus()); - newSSGroup->deleteKey(nullCred); + secnotice("integrity", "caught MacOSError during add: %d", (int) mose.osStatus()); + + deleteSSGroup(newSSGroup, nullCred); throw; } catch (...) { - secdebugfunc("integrity", "caught unknown exception during add"); - // Delete the new SSGroup that we just created - newSSGroup->deleteKey(nullCred); + secnotice("integrity", "caught unknown exception during add"); + + deleteSSGroup(newSSGroup, nullCred); throw; } } else { // Modify the old SSGroup - secdebugfunc("integrity", "modifying the existing SSGroup"); + secnotice("integrity", "modifying the existing SSGroup"); try { doChange(keychain, recordType, ^{ @@ -976,26 +1039,39 @@ ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer // We have to reset this after we add the integrity, since it needs the attributes mDbAttributes.reset(NULL); - transaction.success(); + transaction.commit(); } catch (CssmError cssme) { const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "caught CssmError during modify: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "caught CssmError during modify: %d %s", (int) cssme.error, errStr); throw; } catch (MacOSError mose) { - secdebugfunc("integrity", "caught MacOSError during modify: %d", (int) mose.osStatus()); + secnotice("integrity", "caught MacOSError during modify: %d", (int) mose.osStatus()); throw; } catch (...) { - secdebugfunc("integrity", "caught unknown exception during modify"); + secnotice("integrity", "caught unknown exception during modify"); throw; } } } +// Helper function to delete a group and swallow all errors +void ItemImpl::deleteSSGroup(SSGroup & ssgroup, const AccessCredentials* nullCred) { + try{ + ssgroup->deleteKey(nullCred); + } catch(CssmError error) { + secnotice("integrity", "caught cssm error during deletion of group: %d %s", (int) error.osStatus(), error.what()); + } catch(MacOSError error) { + secnotice("integrity", "caught macos error during deletion of group: %d %s", (int) error.osStatus(), error.what()); + } catch(UnixError error) { + secnotice("integrity", "caught unix error during deletion of group: %d %s", (int) error.osStatus(), error.what()); + } +} + void ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryChange) ()) { @@ -1007,16 +1083,16 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC // Try to extract the item and check its attributes, then try again if necessary auto_ptr primaryKeyAttrs; if(cssme.error == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) { - secdebugfunc("integrity", "possible duplicate, trying to delete invalid items"); + secnotice("integrity", "possible duplicate, trying to delete invalid items"); Keychain kc = (keychain ? keychain : mKeychain); if(!kc) { - secdebugfunc("integrity", "no valid keychain"); + secnotice("integrity", "no valid keychain"); } // Only check for corrupt items if the keychain supports them if((!kc) || !kc->hasIntegrityProtection()) { - secdebugfunc("integrity", "skipping integrity check for corrupt items due to keychain support"); + secnotice("integrity", "skipping integrity check for corrupt items due to keychain support"); throw; } else { primaryKeyAttrs.reset(getCurrentAttributes()); @@ -1037,7 +1113,7 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC // Our keychain doesn't know about any item with this primary key, so maybe // we have a corrupt item in the database. Let's check. - secdebugfunc("integrity", "making a cursor from primary key"); + secnotice("integrity", "making a cursor from primary key"); CssmClient::DbCursor cursor = pk->createCursor(kc); DbUniqueRecord uniqueId; @@ -1051,11 +1127,11 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC // Occasionally this cursor won't return the item attributes (for an unknown reason). // However, we know the attributes any item with this primary key should have, so use those instead. while (cursor->next(dbDupAttributes.get(), NULL, uniqueId)) { - secdebugfunc("integrity", "got an item..."); + secnotice("integrity", "got an item..."); SSGroup group = safer_cast(*uniqueId).group(); if(!ItemImpl::checkIntegrityFromDictionary(*group, dbDupAttributes.get())) { - secdebugfunc("integrity", "item is invalid! deleting..."); + secnotice("integrity", "item is invalid! deleting..."); uniqueId->deleteRecord(); tryAgain = true; } @@ -1063,11 +1139,11 @@ ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryC } if(tryAgain) { - secdebugfunc("integrity", "trying again..."); + secnotice("integrity", "trying again..."); tryChange(); } else { // We didn't find an invalid item, the duplicate item exception is real - secdebugfunc("integrity", "duplicate item exception is real; throwing it on"); + secnotice("integrity", "duplicate item exception is real; throwing it on"); throw; } } @@ -1152,6 +1228,16 @@ ItemImpl::dbUniqueRecord() MacOSError::throwMe(errSecInvalidItemRef); } + // Check that our Db still matches our keychain's db. If not, find this item again in the new Db. + // Why silly !(x == y) construction? Compiler calls operator bool() on each pointer otherwise. + if(!(mUniqueId->database() == keychain()->database())) { + secnotice("integrity", "updating db of mUniqueRecord"); + + DbCursor cursor(mPrimaryKey->createCursor(mKeychain)); + if (!cursor->next(NULL, NULL, mUniqueId)) + MacOSError::throwMe(errSecInvalidItemRef); + } + return mUniqueId; } @@ -1289,7 +1375,7 @@ ItemImpl::getContent(SecItemClass *itemClass, SecKeychainAttributeList *attrList UInt32 attrCount = attrList ? attrList->count : 0; // make a DBAttributes structure and populate it - DbAttributes dbAttributes(mUniqueId->database(), attrCount); + DbAttributes dbAttributes(dbUniqueRecord()->database(), attrCount); for (UInt32 ix = 0; ix < attrCount; ++ix) { dbAttributes.add(Schema::attributeInfo(attrList->attr[ix].tag)); @@ -1338,7 +1424,7 @@ ItemImpl::getContent(SecItemClass *itemClass, SecKeychainAttributeList *attrList #if SENDACCESSNOTIFICATIONS if (outData) { - secdebug("kcnotify", "ItemImpl::getContent(%p, %p, %p, %p) retrieved content", + secinfo("kcnotify", "ItemImpl::getContent(%p, %p, %p, %p) retrieved content", itemClass, attrList, length, outData); KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); @@ -1431,7 +1517,7 @@ ItemImpl::getAttributesAndData(SecKeychainAttributeInfo *info, SecItemClass *ite dbUniqueRecord(); UInt32 attrCount = info ? info->count : 0; - DbAttributes dbAttributes(mUniqueId->database(), attrCount); + DbAttributes dbAttributes(dbUniqueRecord()->database(), attrCount); for (UInt32 ix = 0; ix < attrCount; ix++) { CssmDbAttributeData &record = dbAttributes.add(); @@ -1487,7 +1573,7 @@ ItemImpl::getAttributesAndData(SecKeychainAttributeInfo *info, SecItemClass *ite itemData.Length=0; #if SENDACCESSNOTIFICATIONS - secdebug("kcnotify", "ItemImpl::getAttributesAndData(%p, %p, %p, %p, %p) retrieved data", + secinfo("kcnotify", "ItemImpl::getAttributesAndData(%p, %p, %p, %p, %p) retrieved data", info, itemClass, attrList, length, outData); KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); @@ -1535,10 +1621,9 @@ ItemImpl::getAttribute(SecKeychainAttribute& attr, UInt32 *actualLength) if (!mKeychain) MacOSError::throwMe(errSecNoSuchAttr); - dbUniqueRecord(); - DbAttributes dbAttributes(mUniqueId->database(), 1); + DbAttributes dbAttributes(dbUniqueRecord()->database(), 1); dbAttributes.add(Schema::attributeInfo(attr.tag)); - mUniqueId->get(&dbAttributes, NULL); + dbUniqueRecord()->get(&dbAttributes, NULL); getAttributeFrom(&dbAttributes.at(0), attr, actualLength); } @@ -1568,7 +1653,7 @@ ItemImpl::getAttributeFrom(CssmDbAttributeData *data, SecKeychainAttribute &attr length = sizeof(zero); buf = &zero; } - else if (CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) + else if (data->format() == CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE) length = 0; // Should we throw here? else // All other formats length = 0; @@ -1655,7 +1740,7 @@ ItemImpl::getData(CssmDataContainer& outData) getContent(NULL, &outData); #if SENDACCESSNOTIFICATIONS - secdebug("kcnotify", "ItemImpl::getData retrieved data"); + secinfo("kcnotify", "ItemImpl::getData retrieved data"); //%%% be done elsewhere, but here is good for now KCEventNotifier::PostKeychainEvent(kSecDataAccessEvent, mKeychain, this); @@ -1672,7 +1757,7 @@ ItemImpl::group() Db db(mKeychain->database()); if (useSecureStorage(db)) { - group = safer_cast(*mUniqueId).group(); + group = safer_cast(*dbUniqueRecord()).group(); } } @@ -1729,19 +1814,27 @@ void ItemImpl::getContent(DbAttributes *dbAttributes, CssmDataContainer *itemData) { StLock_(mMutex); - // Make sure mUniqueId is set. - dbUniqueRecord(); if (itemData) { - Db db(mUniqueId->database()); + Db db(dbUniqueRecord()->database()); if (mDoNotEncrypt) { - mUniqueId->getWithoutEncryption (dbAttributes, itemData); + dbUniqueRecord()->getWithoutEncryption (dbAttributes, itemData); return; } if (useSecureStorage(db)) { - SSDbUniqueRecordImpl* impl = dynamic_cast(&(*mUniqueId)); + try { + if(!checkIntegrity()) { + secnotice("integrity", "item has no integrity, denying access"); + CssmError::throwMe(errSecInvalidItemRef); + } + } catch(CssmError cssme) { + secnotice("integrity", "error while checking integrity, denying access: %s", cssme.what()); + throw cssme; + } + + SSDbUniqueRecordImpl* impl = dynamic_cast(&(*dbUniqueRecord())); if (impl == NULL) { CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); @@ -1754,7 +1847,7 @@ ItemImpl::getContent(DbAttributes *dbAttributes, CssmDataContainer *itemData) } } - mUniqueId->get(dbAttributes, itemData); + dbUniqueRecord()->get(dbAttributes, itemData); } bool diff --git a/OSX/libsecurity_keychain/lib/Item.h b/OSX/libsecurity_keychain/lib/Item.h index 26d7d7f2..8e9460dd 100644 --- a/OSX/libsecurity_keychain/lib/Item.h +++ b/OSX/libsecurity_keychain/lib/Item.h @@ -45,7 +45,10 @@ class Keychain; class ItemImpl : public SecCFObject { public: - SECCFFUNCTIONS(ItemImpl, SecKeychainItemRef, errSecInvalidItemRef, gTypes().ItemImpl) + SECCFFUNCTIONS_CREATABLE(ItemImpl, SecKeychainItemRef, gTypes().ItemImpl) + + static ItemImpl *required(SecKeychainItemRef ptr); + static ItemImpl *optional(SecKeychainItemRef ptr); friend class Item; friend class KeychainImpl; @@ -79,7 +82,7 @@ public: CFDataRef getPersistentRef(); PrimaryKey addWithCopyInfo(Keychain &keychain, bool isCopy); - Mutex* getMutexForObject(); + Mutex* getMutexForObject() const; // Return true iff the item integrity has not been compromised. virtual bool checkIntegrity(); @@ -194,6 +197,9 @@ protected: * the ACL will be copied from the old group, and the old group deleted. */ void updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer* data, Keychain keychain = NULL, SecPointer access = NULL); + // Helper function to abstract out error handling. Does not report any errors. + void deleteSSGroup(SSGroup & ssgroup, const AccessCredentials* nullCred); + void doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryChange) () ); // Add integrity acl entry to access. @@ -208,6 +214,12 @@ protected: // Set the integrity of this bearer to be whatever my attributes are now virtual void setIntegrity(AclBearer &bearer, bool force = false); + // Call this function to remove the integrity and partition_id ACLs from + // this item. You're not supposed to be able to do this, so force the issue + // by providing credentials to this keychain. + virtual void removeIntegrity(const AccessCredentials *cred); + virtual void removeIntegrity(AclBearer &bearer, const AccessCredentials *cred); + // new item members RefPointer mData; auto_ptr mDbAttributes; diff --git a/OSX/libsecurity_keychain/lib/KCCursor.cpp b/OSX/libsecurity_keychain/lib/KCCursor.cpp index 1c0cdb9d..b252dd9c 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.cpp +++ b/OSX/libsecurity_keychain/lib/KCCursor.cpp @@ -60,6 +60,7 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, SecIt mCurrent(mSearchList.begin()), mAllFailed(true), mDeleteInvalidRecords(false), + mIsNewKeychain(true), mMutex(Mutex::recursive), mKeychainReadLock(NULL) { @@ -117,6 +118,7 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const mCurrent(mSearchList.begin()), mAllFailed(true), mDeleteInvalidRecords(false), + mIsNewKeychain(true), mMutex(Mutex::recursive), mKeychainReadLock(NULL) { @@ -187,20 +189,10 @@ KCCursorImpl::next(Item &item) DbUniqueRecord uniqueId; OSStatus status = 0; - // if this is true, we should perform newKeychain() on mCurrent before - // taking any locks. Starts false because mDbCursor isn't anything yet, and - // so the while loop will run newKeychain for us. - bool isNewKeychain = false; - for (;;) { Item tempItem = NULL; { - if(isNewKeychain) { - newKeychain(mCurrent); - isNewKeychain = false; - } - while (!mDbCursor) { // Do the newKeychain dance before we check our done status @@ -229,6 +221,7 @@ KCCursorImpl::next(Item &item) catch(const CommonError &err) { ++mCurrent; + mIsNewKeychain = true; } } @@ -271,7 +264,7 @@ KCCursorImpl::next(Item &item) // we'd like to call newKeychain(mCurrent) here, but to avoid deadlock // we need to drop the current keychain's mutex first. Use this silly // hack to void the stack Mutex object. - isNewKeychain = true; + mIsNewKeychain = true; continue; } @@ -319,7 +312,7 @@ KCCursorImpl::next(Item &item) if (mDeleteInvalidRecords) { // This is an invalid record for some reason; delete it and restart the loop const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "deleting corrupt record because: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "deleting corrupt record because: %d %s", (int) cssme.error, errStr); deleteInvalidRecord(uniqueId); // if deleteInvalidRecord doesn't throw, we want to restart the loop @@ -331,26 +324,6 @@ KCCursorImpl::next(Item &item) } // release the Keychain lock before checking item integrity to avoid deadlock - try { - // If the Item's attribute hash does not match, skip the item - if(!tempItem->checkIntegrity()) { - secdebugfunc("integrity", "item has no integrity, skipping"); - continue; - } - } catch(CssmError cssme) { - if (mDeleteInvalidRecords) { - // This is an invalid record for some reason; delete it and restart the loop - const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "deleting corrupt record because: %d %s", (int) cssme.error, errStr); - - deleteInvalidRecord(uniqueId); - // if deleteInvalidRecord doesn't throw, we want to restart the loop - continue; - } else { - throw; - } - } - item = tempItem; break; @@ -366,7 +339,7 @@ void KCCursorImpl::deleteInvalidRecord(DbUniqueRecord& uniqueId) { uniqueId->deleteRecord(); } catch(CssmError delcssme) { if (delcssme.osStatus() == CSSMERR_DL_RECORD_NOT_FOUND) { - secdebugfunc("integrity", "couldn't delete nonexistent record (this is okay)"); + secnotice("integrity", "couldn't delete nonexistent record (this is okay)"); } else { throw; } @@ -392,6 +365,11 @@ void KCCursorImpl::setDeleteInvalidRecords(bool deleteRecord) { } void KCCursorImpl::newKeychain(StorageManager::KeychainList::iterator kcIter) { + if(!mIsNewKeychain) { + // We've already been called on this keychain, don't bother. + return; + } + // Always lose the last keychain's lock if(mKeychainReadLock) { delete mKeychainReadLock; @@ -400,8 +378,12 @@ void KCCursorImpl::newKeychain(StorageManager::KeychainList::iterator kcIter) { if(kcIter != mSearchList.end()) { (*kcIter)->performKeychainUpgradeIfNeeded(); + (*kcIter)->tickle(); // Grab a read lock on the keychain mKeychainReadLock = new StReadWriteLock(*((*kcIter)->getKeychainReadWriteLock()), StReadWriteLock::Read); } + + // Mark down that this function has been called + mIsNewKeychain = false; } diff --git a/OSX/libsecurity_keychain/lib/KCCursor.h b/OSX/libsecurity_keychain/lib/KCCursor.h index c65bf060..de0fe7a3 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.h +++ b/OSX/libsecurity_keychain/lib/KCCursor.h @@ -68,6 +68,9 @@ private: bool mAllFailed; bool mDeleteInvalidRecords; + // Remembers if we've called newKeychain() on mCurrent. + bool mIsNewKeychain; + protected: Mutex mMutex; StReadWriteLock* mKeychainReadLock; diff --git a/OSX/libsecurity_keychain/lib/KCEventNotifier.cpp b/OSX/libsecurity_keychain/lib/KCEventNotifier.cpp index 746bab58..662e1dc4 100644 --- a/OSX/libsecurity_keychain/lib/KCEventNotifier.cpp +++ b/OSX/libsecurity_keychain/lib/KCEventNotifier.cpp @@ -75,7 +75,7 @@ void KCEventNotifier::PostKeychainEvent(SecKeychainEvent whichEvent, SecurityServer::ClientSession cs (Allocator::standard(), Allocator::standard()); cs.postNotification (SecurityServer::kNotificationDomainDatabase, whichEvent, data); - secdebug("kcnotify", "KCEventNotifier::PostKeychainEvent posted event %u", (unsigned int) whichEvent); + secinfo("kcnotify", "KCEventNotifier::PostKeychainEvent posted event %u", (unsigned int) whichEvent); } free (data.data ()); diff --git a/OSX/libsecurity_keychain/lib/KeyItem.cpp b/OSX/libsecurity_keychain/lib/KeyItem.cpp index 0fe303ba..7829ca54 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.cpp +++ b/OSX/libsecurity_keychain/lib/KeyItem.cpp @@ -40,6 +40,7 @@ #include #include #include +#include // @@@ This needs to be shared. #pragma clang diagnostic push @@ -52,6 +53,58 @@ static CSSM_DB_NAME_ATTR(kInfoKeyApplicationTag, kSecKeyApplicationTag, (char*) using namespace KeychainCore; using namespace CssmClient; +KeyItem *KeyItem::required(SecKeyRef ptr) +{ + if (KeyItem *p = optional(ptr)) { + return p; + } else { + MacOSError::throwMe(errSecInvalidItemRef); + } +} + +KeyItem *KeyItem::optional(SecKeyRef ptr) +{ + if (ptr != NULL) { + if (KeyItem *pp = dynamic_cast(fromSecKeyRef(ptr))) { + return pp; + } else { + MacOSError::throwMe(errSecInvalidItemRef); + } + } else { + return NULL; + } +} + +KeyItem::operator CFTypeRef() const throw() +{ + StMaybeLock _(this->getMutexForObject()); + + if (mWeakSecKeyRef != NULL) { + if (_CFTryRetain(mWeakSecKeyRef) == NULL) { + // mWeakSecKeyRef is not really valid, pointing to SecKeyRef which going to die - it is somewhere between last CFRelease and entering into mutex-protected section of SecCDSAKeyDestroy. Avoid using it, pretend that no enveloping SecKeyRef exists. But make sure that this KeyImpl is disconnected from this about-to-die SecKeyRef, because we do not want KeyImpl connected to it to be really destroyed, it will be connected to newly created SecKeyRef (see below). + mWeakSecKeyRef->key = NULL; + mWeakSecKeyRef = NULL; + } else { + // We did not really want to retain, it was just weak->strong promotion test. + CFRelease(mWeakSecKeyRef); + } + } + + if (mWeakSecKeyRef == NULL) { + // Create enveloping ref on-demand. Transfer reference count from SecCFObject + // to newly created SecKeyRef wrapper. + attachSecKeyRef(); + } + return mWeakSecKeyRef; +} + +void KeyItem::initializeWithSecKeyRef(SecKeyRef ref) +{ + isNew(); + mWeakSecKeyRef = ref; +} + + KeyItem::KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) : ItemImpl(keychain, primaryKey, uniqueId), mKey(), @@ -121,7 +174,7 @@ KeyItem::update() /* Update integrity on key */ setIntegrity(); - transaction.success(); + transaction.commit(); } Item @@ -232,8 +285,9 @@ KeyItem::copyTo(const Keychain &keychain, Access *newAccess) throw; } - /* Set the acl and owner on the unwrapped key. */ - addIntegrity(*access); + /* Set the acl and owner on the unwrapped key. See note in ItemImpl::copyTo about removing rights. */ + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID); + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY); access->setAccess(*unwrappedKey, maker); /* Return a keychain item which represents the new key. */ @@ -387,21 +441,50 @@ KeyItem::ssDbUniqueRecord() return CssmClient::SSDbUniqueRecord(simpl); } -CssmClient::Key & -KeyItem::key() +CssmKey::Header +KeyItem::unverifiedKeyHeader() { + return unverifiedKey()->header(); +} + +CssmClient::Key +KeyItem::unverifiedKey() { - StLock_(mMutex); + StLock_(mMutex); if (!mKey) { CssmClient::SSDbUniqueRecord uniqueId(ssDbUniqueRecord()); CssmDataContainer dataBlob(uniqueId->allocator()); uniqueId->get(NULL, &dataBlob); - mKey = CssmClient::Key(uniqueId->database()->csp(), *reinterpret_cast(dataBlob.Data)); + return CssmClient::Key(uniqueId->database()->csp(), *reinterpret_cast(dataBlob.Data)); } return mKey; } +CssmClient::Key & +KeyItem::key() +{ + StLock_(mMutex); + if (!mKey) + { + mKey = unverifiedKey(); + + try { + if(!ItemImpl::checkIntegrity(*mKey)) { + secnotice("integrity", "key has no integrity, denying access"); + mKey.release(); + CssmError::throwMe(errSecInvalidItemRef); + } + } catch(CssmError cssme) { + mKey.release(); + secnotice("integrity", "error while checking integrity, denying access: %s", cssme.what()); + throw cssme; + } + } + + return mKey; +} + CssmClient::CSP KeyItem::csp() { @@ -499,6 +582,11 @@ KeyItem::getCredentials( } } +CssmClient::Key +KeyItem::publicKey() { + return mPublicKey; +} + bool KeyItem::operator == (KeyItem &other) { @@ -527,178 +615,206 @@ KeyItem::createPair( SecPointer &outPublicKey, SecPointer &outPrivateKey) { - bool freeKeys = false; - bool deleteContext = false; - - if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) - MacOSError::throwMe(errSecInvalidKeychain); - - SSDbImpl* impl = dynamic_cast(&(*keychain->database())); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - SSDb ssDb(impl); - CssmClient::CSP csp(keychain->csp()); - CssmClient::CSP appleCsp(gGuidAppleCSP); + SSDb ssDb(NULL); + Access::Maker maker; + const AccessCredentials *cred = NULL; + CssmClient::CSP appleCsp(gGuidAppleCSP); + CssmClient::CSP csp = appleCsp; + ResourceControlContext rcc; + memset(&rcc, 0, sizeof(rcc)); + CssmData label; + uint8 labelBytes[20]; + + if (keychain) { + if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP)) + MacOSError::throwMe(errSecInvalidKeychain); + + SSDbImpl* impl = dynamic_cast(&(*keychain->database())); + if (impl == NULL) + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - // Generate a random label to use initially - CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW); - uint8 labelBytes[20]; - CssmData label(labelBytes, sizeof(labelBytes)); - random.generate(label, (uint32)label.Length); + ssDb = SSDb(impl); + csp = CssmClient::CSP(keychain->csp()); - // Create a Access::Maker for the initial owner of the private key. - ResourceControlContext rcc; - memset(&rcc, 0, sizeof(rcc)); - Access::Maker maker; - // @@@ Potentially provide a credential argument which allows us to generate keys in the csp. Currently the CSP let's anyone do this, but we might restrict this in the future, f.e. a smartcard could require out of band pin entry before a key can be generated. - maker.initialOwner(rcc); - // Create the cred we need to manipulate the keys until we actually set a new access control for them. - const AccessCredentials *cred = maker.cred(); + // Generate a random label to use initially + CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW); + label = CssmData(labelBytes, sizeof(labelBytes)); + random.generate(label, (uint32)label.length()); - CSSM_KEY publicCssmKey, privateCssmKey; - memset(&publicCssmKey, 0, sizeof(publicCssmKey)); - memset(&privateCssmKey, 0, sizeof(privateCssmKey)); + // Create a Access::Maker for the initial owner of the private key. + // @@@ Potentially provide a credential argument which allows us to generate keys in the csp. Currently the CSP let's anyone do this, but we might restrict this in the future, f.e. a smartcard could require out of band pin entry before a key can be generated. + maker.initialOwner(rcc); + // Create the cred we need to manipulate the keys until we actually set a new access control for them. + cred = maker.cred(); + } + CssmKey publicCssmKey, privateCssmKey; CSSM_CC_HANDLE ccHandle = 0; + bool freePublicKey = false; + bool freePrivateKey = false; + bool deleteContext = false; + bool permanentPubKey = false; + bool permanentPrivKey = false; + SecPointer publicKeyItem, privateKeyItem; - try - { + try { CSSM_RETURN status; - if (contextHandle) - ccHandle = contextHandle; - else - { + if (contextHandle) { + ccHandle = contextHandle; + } else { status = CSSM_CSP_CreateKeyGenContext(csp->handle(), algorithm, keySizeInBits, NULL, NULL, NULL, NULL, NULL, &ccHandle); if (status) CssmError::throwMe(status); deleteContext = true; } - CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle(); - CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle; - CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } }; - status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes); - if (status) - CssmError::throwMe(status); + if (ssDb) { + CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle(); + CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle; + CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } }; + status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes); + if (status) + CssmError::throwMe(status); + } // Generate the keypair status = CSSM_GenerateKeyPair(ccHandle, publicKeyUsage, publicKeyAttr, &label, &publicCssmKey, privateKeyUsage, privateKeyAttr, &label, &rcc, &privateCssmKey); if (status) CssmError::throwMe(status); - freeKeys = true; + if ((publicKeyAttr & CSSM_KEYATTR_PERMANENT) != 0) { + permanentPubKey = true; + freePublicKey = true; + } + if ((privateKeyAttr & CSSM_KEYATTR_PERMANENT) != 0) { + permanentPrivKey = true; + freePrivateKey = true; + } - // Find the keys we just generated in the DL to get SecKeyRef's to them - // so we can change the label to be the hash of the public key, and + // Find the keys if we just generated them in the DL so we can change the label to be the hash of the public key, and // fix up other attributes. // Look up public key in the DLDB. - DbAttributes pubDbAttributes; - DbUniqueRecord pubUniqueId; - SSDbCursor dbPubCursor(ssDb, 1); - dbPubCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY); - dbPubCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); - CssmClient::Key publicKey; - if (!dbPubCursor->nextKey(&pubDbAttributes, publicKey, pubUniqueId)) - MacOSError::throwMe(errSecItemNotFound); + CssmClient::Key publicKey; + DbAttributes pubDbAttributes; + DbUniqueRecord pubUniqueId; + if (permanentPubKey) { + SSDbCursor dbPubCursor(ssDb, 1); + dbPubCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY); + dbPubCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + if (!dbPubCursor->nextKey(&pubDbAttributes, publicKey, pubUniqueId)) + MacOSError::throwMe(errSecItemNotFound); + } else { + publicKey = CssmClient::Key(appleCsp, publicCssmKey); + outPublicKey = new KeyItem(publicKey); + freePublicKey = false; + } // Look up private key in the DLDB. - DbAttributes privDbAttributes; - DbUniqueRecord privUniqueId; - SSDbCursor dbPrivCursor(ssDb, 1); - dbPrivCursor->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY); - dbPrivCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); - CssmClient::Key privateKey; - if (!dbPrivCursor->nextKey(&privDbAttributes, privateKey, privUniqueId)) - MacOSError::throwMe(errSecItemNotFound); - - // Convert reference public key to a raw key so we can use it - // in the appleCsp. - CssmClient::WrapKey wrap(csp, CSSM_ALGID_NONE); - wrap.cred(cred); - CssmClient::Key rawPubKey = wrap(publicKey); - - // Calculate the hash of the public key using the appleCSP. - CssmClient::PassThrough passThrough(appleCsp); - void *outData; - CssmData *cssmData; - - /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the - * associated key blob. - * Key is specified in CSSM_CSP_CreatePassThroughContext. - * Hash is allocated bythe CSP, in the App's memory, and returned - * in *outData. */ - passThrough.key(rawPubKey); - passThrough(CSSM_APPLECSP_KEYDIGEST, NULL, &outData); - cssmData = reinterpret_cast(outData); - CssmData &pubKeyHash = *cssmData; - - auto_ptrprivDescription; - auto_ptrpubDescription; - try { - privDescription.reset(new string(initialAccess->promptDescription())); - pubDescription.reset(new string(initialAccess->promptDescription())); - } - catch(...) { - /* this path taken if no promptDescription available, e.g., for complex ACLs */ - privDescription.reset(new string("Private key")); - pubDescription.reset(new string("Public key")); - } + CssmClient::Key privateKey; + DbAttributes privDbAttributes; + DbUniqueRecord privUniqueId; + if (permanentPrivKey) { + SSDbCursor dbPrivCursor(ssDb, 1); + dbPrivCursor->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY); + dbPrivCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label); + if (!dbPrivCursor->nextKey(&privDbAttributes, privateKey, privUniqueId)) + MacOSError::throwMe(errSecItemNotFound); + } else { + privateKey = CssmClient::Key(appleCsp, privateCssmKey); + outPrivateKey = new KeyItem(privateKey); + freePrivateKey = false; + } - // Set the label of the public key to the public key hash. - // Set the PrintName of the public key to the description in the acl. - pubDbAttributes.add(kInfoKeyLabel, pubKeyHash); - pubDbAttributes.add(kInfoKeyPrintName, *pubDescription); - modifyUniqueId(keychain, ssDb, pubUniqueId, pubDbAttributes, CSSM_DL_DB_RECORD_PUBLIC_KEY); + if (ssDb) { + // Convert reference public key to a raw key so we can use it in the appleCsp. + CssmClient::WrapKey wrap(csp, CSSM_ALGID_NONE); + wrap.cred(cred); + CssmClient::Key rawPubKey = wrap(publicKey); + + // Calculate the hash of the public key using the appleCSP. + CssmClient::PassThrough passThrough(appleCsp); + + /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the + * associated key blob. + * Key is specified in CSSM_CSP_CreatePassThroughContext. + * Hash is allocated by the CSP, in the App's memory, and returned + * in *outData. */ + passThrough.key(rawPubKey); + CssmData *pubKeyHashData; + passThrough(CSSM_APPLECSP_KEYDIGEST, (const void *)NULL, &pubKeyHashData); + CssmAutoData pubKeyHash(passThrough.allocator()); + pubKeyHash.set(*pubKeyHashData); + passThrough.allocator().free(pubKeyHashData); + + auto_ptrprivDescription; + auto_ptrpubDescription; + try { + privDescription.reset(new string(initialAccess->promptDescription())); + pubDescription.reset(new string(initialAccess->promptDescription())); + } + catch (...) { + /* this path taken if no promptDescription available, e.g., for complex ACLs */ + privDescription.reset(new string("Private key")); + pubDescription.reset(new string("Public key")); + } - // Set the label of the private key to the public key hash. - // Set the PrintName of the private key to the description in the acl. - privDbAttributes.add(kInfoKeyLabel, pubKeyHash); - privDbAttributes.add(kInfoKeyPrintName, *privDescription); - modifyUniqueId(keychain, ssDb, privUniqueId, privDbAttributes, CSSM_DL_DB_RECORD_PRIVATE_KEY); + if (permanentPubKey) { + // Set the label of the public key to the public key hash. + // Set the PrintName of the public key to the description in the acl. + pubDbAttributes.add(kInfoKeyLabel, pubKeyHash.get()); + pubDbAttributes.add(kInfoKeyPrintName, *pubDescription); + modifyUniqueId(keychain, ssDb, pubUniqueId, pubDbAttributes, CSSM_DL_DB_RECORD_PUBLIC_KEY); + + // Create keychain item which will represent the public key. + publicKeyItem = dynamic_cast(keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId).get()); + if (!publicKeyItem) { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } - // @@@ Not exception safe! - csp.allocator().free(cssmData->Data); - csp.allocator().free(cssmData); + if (publicKeyAttr & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) { + /* + * Make the public key acl completely open. + * If the key was not encrypted, it already has a wide-open + * ACL (though that is a feature of securityd; it's not + * CDSA-specified behavior). + */ + SecPointer pubKeyAccess(new Access()); + publicKeyItem->addIntegrity(*pubKeyAccess); + pubKeyAccess->setAccess(*publicKey, maker); + } + outPublicKey = publicKeyItem; + } - // Create keychain items which will represent the keys. - publicKeyItem = dynamic_cast(keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId).get()); - privateKeyItem = dynamic_cast(keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId).get()); + if (permanentPrivKey) { + // Set the label of the private key to the public key hash. + // Set the PrintName of the private key to the description in the acl. + privDbAttributes.add(kInfoKeyLabel, pubKeyHash.get()); + privDbAttributes.add(kInfoKeyPrintName, *privDescription); + modifyUniqueId(keychain, ssDb, privUniqueId, privDbAttributes, CSSM_DL_DB_RECORD_PRIVATE_KEY); + + // Create keychain item which will represent the private key. + privateKeyItem = dynamic_cast(keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId).get()); + if (!privateKeyItem) { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } - if (!publicKeyItem || !privateKeyItem) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + // Finally fix the acl and owner of the private key to the specified access control settings. + privateKeyItem->addIntegrity(*initialAccess); + initialAccess->setAccess(*privateKey, maker); + outPrivateKey = privateKeyItem; + } } - - // Finally fix the acl and owner of the private key to the specified access control settings. - privateKeyItem->addIntegrity(*initialAccess); - initialAccess->setAccess(*privateKey, maker); - - if(publicKeyAttr & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) { - /* - * Make the public key acl completely open. - * If the key was not encrypted, it already has a wide-open - * ACL (though that is a feature of securityd; it's not - * CDSA-specified behavior). - */ - SecPointer pubKeyAccess(new Access()); - publicKeyItem->addIntegrity(*pubKeyAccess); - pubKeyAccess->setAccess(*publicKey, maker); - } - - outPublicKey = publicKeyItem; - outPrivateKey = privateKeyItem; + outPrivateKey->mPublicKey = publicKey; } catch (...) { - if (freeKeys) - { - // Delete the keys if something goes wrong so we don't end up with inaccessible keys in the database. - CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, TRUE); - CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, TRUE); + // Delete the keys if something goes wrong so we don't end up with inaccessible keys in the database. + if (freePublicKey) { + CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, permanentPubKey); + } + if (freePrivateKey) { + CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, permanentPrivKey); } if (deleteContext) @@ -707,19 +823,23 @@ KeyItem::createPair( throw; } - if (freeKeys) - { + if (freePublicKey) { CSSM_FreeKey(csp->handle(), NULL, &publicCssmKey, FALSE); + } + if (freePrivateKey) { CSSM_FreeKey(csp->handle(), NULL, &privateCssmKey, FALSE); } if (deleteContext) CSSM_DeleteContext(ccHandle); - if (keychain && publicKeyItem && privateKeyItem) - { - keychain->postEvent(kSecAddEvent, publicKeyItem); - keychain->postEvent(kSecAddEvent, privateKeyItem); + if (keychain) { + if (permanentPubKey) { + keychain->postEvent(kSecAddEvent, publicKeyItem); + } + if (permanentPrivKey) { + keychain->postEvent(kSecAddEvent, privateKeyItem); + } } } @@ -1139,216 +1259,6 @@ KeyItem::generate(Keychain keychain, } -void KeyItem::RawSign(SecPadding padding, CSSM_DATA dataToSign, const AccessCredentials *credentials, CSSM_DATA& signature) -{ - CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); - - if ((baseAlg != CSSM_ALGID_RSA) && (baseAlg != CSSM_ALGID_ECDSA)) - { - MacOSError::throwMe(errSecParam); - } - - CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; - - switch (padding) - { - case kSecPaddingPKCS1: - { - paddingAlg = CSSM_PADDING_PKCS1; - break; - } - - case kSecPaddingPKCS1MD2: - { - baseAlg = CSSM_ALGID_MD2WithRSA; - break; - } - - case kSecPaddingPKCS1MD5: - { - baseAlg = CSSM_ALGID_MD5WithRSA; - break; - } - - case kSecPaddingPKCS1SHA1: - { - baseAlg = CSSM_ALGID_SHA1WithRSA; - break; - } - - case kSecPaddingSigRaw: - { - paddingAlg = CSSM_PADDING_SIGRAW; - break; - } - - default: - { - paddingAlg = CSSM_PADDING_NONE; - break; - } - } - - Sign signContext(csp(), baseAlg); - signContext.key(key()); - signContext.cred(credentials); - // Fields required for CSSM_CSP_CreateSignatureContext set above. Using add instead of set ensures - // that the context is constructed before the set is attempted, which would fail silently otherwise. - signContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlg); - - CssmData data(dataToSign.Data, dataToSign.Length); - signContext.sign(data); - - CssmData sig(signature.Data, signature.Length); - signContext(sig); // yes, this is an accessor. Believe it, or not. - signature.Length = sig.length(); -} - - - -void KeyItem::RawVerify(SecPadding padding, CSSM_DATA dataToVerify, const AccessCredentials *credentials, CSSM_DATA sig) -{ - CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); - if ((baseAlg != CSSM_ALGID_RSA) && (baseAlg != CSSM_ALGID_ECDSA)) - { - MacOSError::throwMe(errSecParam); - } - - CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; - - switch (padding) - { - case kSecPaddingPKCS1: - { - paddingAlg = CSSM_PADDING_PKCS1; - break; - } - - case kSecPaddingPKCS1MD2: - { - baseAlg = CSSM_ALGID_MD2WithRSA; - break; - } - - case kSecPaddingPKCS1MD5: - { - baseAlg = CSSM_ALGID_MD5WithRSA; - break; - } - - case kSecPaddingPKCS1SHA1: - { - baseAlg = CSSM_ALGID_SHA1WithRSA; - break; - } - - case kSecPaddingSigRaw: - { - paddingAlg = CSSM_PADDING_SIGRAW; - break; - } - - default: - { - paddingAlg = CSSM_PADDING_NONE; - break; - } - } - - Verify verifyContext(csp(), baseAlg); - verifyContext.key(key()); - verifyContext.cred(credentials); - // Fields required for CSSM_CSP_CreateSignatureContext set above. Using add instead of set ensures - // that the context is constructed before the set is attempted, which would fail silently otherwise. - verifyContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlg); - - CssmData data(dataToVerify.Data, dataToVerify.Length); - CssmData signature(sig.Data, sig.Length); - verifyContext.verify(data, signature); -} - - - -void KeyItem::Encrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData) -{ - CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); - if (baseAlg != CSSM_ALGID_RSA) - { - MacOSError::throwMe(errSecParam); - } - - CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; - - switch (padding) - { - case kSecPaddingPKCS1: - { - paddingAlg = CSSM_PADDING_PKCS1; - break; - } - - default: - { - paddingAlg = CSSM_PADDING_NONE; - break; - } - } - - CssmClient::Encrypt encryptContext(csp(), baseAlg); - encryptContext.key(key()); - encryptContext.padding(paddingAlg); - encryptContext.cred(credentials); - - CssmData inData(dataToEncrypt.Data, dataToEncrypt.Length); - CssmData outData(encryptedData.Data, encryptedData.Length); - CssmData remData((void*) NULL, 0); - - encryptedData.Length = encryptContext.encrypt(inData, outData, remData); -} - - - -void KeyItem::Decrypt(SecPadding padding, CSSM_DATA dataToDecrypt, const AccessCredentials *credentials, CSSM_DATA& decryptedData) -{ - CSSM_ALGORITHMS baseAlg = key()->header().algorithm(); - if (baseAlg != CSSM_ALGID_RSA) - { - MacOSError::throwMe(errSecParam); - } - - CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1; - - switch (padding) - { - case kSecPaddingPKCS1: - { - paddingAlg = CSSM_PADDING_PKCS1; - break; - } - - - default: - { - paddingAlg = CSSM_PADDING_NONE; - break; - } - } - - CssmClient::Decrypt decryptContext(csp(), baseAlg); - decryptContext.key(key()); - decryptContext.padding(paddingAlg); - decryptContext.cred(credentials); - - CssmData inData(dataToDecrypt.Data, dataToDecrypt.Length); - CssmData outData(decryptedData.Data, decryptedData.Length); - CssmData remData((void*) NULL, 0); - decryptedData.Length = decryptContext.decrypt(inData, outData, remData); - if (remData.Data != NULL) - { - free(remData.Data); - } -} - CFHashCode KeyItem::hash() { CFHashCode result = 0; @@ -1394,7 +1304,7 @@ CFHashCode KeyItem::hash() } void KeyItem::setIntegrity(bool force) { - ItemImpl::setIntegrity(*key(), force); + ItemImpl::setIntegrity(*unverifiedKey(), force); } bool KeyItem::checkIntegrity() { @@ -1402,9 +1312,19 @@ bool KeyItem::checkIntegrity() { return true; } - return ItemImpl::checkIntegrity(*key()); + try { + // key() checks integrity of itself, and throws if there's a problem. + key(); + return true; + } catch (CssmError cssme) { + return false; + } } + void KeyItem::removeIntegrity(const AccessCredentials *cred) { + ItemImpl::removeIntegrity(*key(), cred); + } + // KeyItems are a little bit special: the only modifications you can do to them // is to change their Print Name, Label, or Application Tag. // @@ -1433,12 +1353,12 @@ void KeyItem::modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqu // KeyItems only have integrity if the keychain supports it; otherwise, // don't pre-check for duplicates if((!keychain) || !keychain->hasIntegrityProtection()) { - secdebugfunc("integrity", "key skipping duplicate integrity check due to keychain version"); + secnotice("integrity", "key skipping duplicate integrity check due to keychain version"); checkForDuplicates = false; } if (checkForDuplicates) { - secdebugfunc("integrity", "looking for duplicates"); + secnotice("integrity", "looking for duplicates"); // If there are duplicates that are invalid, delete it and // continue. Otherwise, if there are duplicates, throw errSecDuplicateItem. DbAttributes otherDbAttributes; @@ -1446,17 +1366,17 @@ void KeyItem::modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqu CssmClient::Key otherKey; while(otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId)) { - secdebugfunc("integrity", "found a duplicate, checking integrity"); + secnotice("integrity", "found a duplicate, checking integrity"); PrimaryKey pk = keychain->makePrimaryKey(recordType, otherUniqueId); ItemImpl* maybeItem = keychain->_lookupItem(pk); if(maybeItem) { if(maybeItem->checkIntegrity()) { - secdebugfunc("integrity", "duplicate is real, throwing error"); + secnotice("integrity", "duplicate is real, throwing error"); MacOSError::throwMe(errSecDuplicateItem); } else { - secdebugfunc("integrity", "existing duplicate item is invalid, removing..."); + secnotice("integrity", "existing duplicate item is invalid, removing..."); Item item(maybeItem); keychain->deleteItem(item); } @@ -1464,10 +1384,10 @@ void KeyItem::modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqu KeyItem temp(keychain, pk, otherUniqueId); if(temp.checkIntegrity()) { - secdebugfunc("integrity", "duplicate is real, throwing error"); + secnotice("integrity", "duplicate is real, throwing error"); MacOSError::throwMe(errSecDuplicateItem); } else { - secdebugfunc("integrity", "duplicate is invalid, removing"); + secnotice("integrity", "duplicate is invalid, removing"); // Keychain's idea of deleting items involves notifications and callbacks. We don't want that, // (since this isn't a real item and it should go away quietly), so use this roundabout method. otherUniqueId->deleteRecord(); @@ -1478,9 +1398,9 @@ void KeyItem::modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqu } try { - secdebugfunc("integrity", "modifying unique id"); + secnotice("integrity", "modifying unique id"); uniqueId->modify(recordType, &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); - secdebugfunc("integrity", "done modifying unique id"); + secnotice("integrity", "done modifying unique id"); } catch(CssmError e) { // Just in case something went wrong, clean up after this add uniqueId->deleteRecord(); diff --git a/OSX/libsecurity_keychain/lib/KeyItem.h b/OSX/libsecurity_keychain/lib/KeyItem.h index 56776933..ede8dd64 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.h +++ b/OSX/libsecurity_keychain/lib/KeyItem.h @@ -40,7 +40,20 @@ class KeyItem : public ItemImpl { NOCOPY(KeyItem) public: - SECCFFUNCTIONS(KeyItem, SecKeyRef, errSecInvalidItemRef, gTypes().KeyItem) + SECCFFUNCTIONS_BASE(KeyItem, SecKeyRef) + + // SecKeyRef is now provided by iOS implementation, so we have to hack standard accessors normally defined by + // 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(); + static SecCFObject *fromSecKeyRef(CFTypeRef ref); + void attachSecKeyRef() const; + void initializeWithSecKeyRef(SecKeyRef ref); + +private: + // This weak backpointer to owning SecKeyRef instance (which is created by iOS SecKey code). + mutable SecKeyRef mWeakSecKeyRef; // db item constructor private: @@ -68,8 +81,13 @@ public: CssmClient::Key &key(); CssmClient::CSP csp(); + // Returns the header of the unverified key (without checking integrity). This will skip ACL checks, but don't trust the data very much. + // Can't return a reference, because maybe the unverified key will get released upon return. + CssmKey::Header unverifiedKeyHeader(); + const CSSM_X509_ALGORITHM_IDENTIFIER& algorithmIdentifier(); unsigned int strengthInBits(const CSSM_X509_ALGORITHM_IDENTIFIER *algid); + CssmClient::Key publicKey(); const AccessCredentials *getCredentials( CSSM_ACL_AUTHORIZATION_TAG operation, @@ -119,28 +137,38 @@ public: virtual const CssmData &itemID(); - void RawSign(SecPadding padding, CSSM_DATA dataToSign, const AccessCredentials *credentials, CSSM_DATA& signedData); - void RawVerify(SecPadding padding, CSSM_DATA dataToVerify, const AccessCredentials *credentials, CSSM_DATA signature); - void Encrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData); - void Decrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData); - virtual CFHashCode hash(); virtual void setIntegrity(bool force = false); virtual bool checkIntegrity(); + // Call this function to remove the integrity and partition_id ACLs from + // this item. You're not supposed to be able to do this, so force the issue + // by providing credentials to this keychain. + virtual void removeIntegrity(const AccessCredentials *cred); + static void modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqueId, DbAttributes& newDbAttributes, CSSM_DB_RECORDTYPE recordType); protected: virtual PrimaryKey add(Keychain &keychain); private: + CssmClient::Key unverifiedKey(); + CssmClient::Key mKey; const CSSM_X509_ALGORITHM_IDENTIFIER *algid; CssmAutoData mPubKeyHash; + CssmClient::Key mPublicKey; }; } // end namespace KeychainCore } // end namespace Security +struct OpaqueSecKeyRef { + CFRuntimeBase _base; + const SecKeyDescriptor *key_class; + SecKeyRef cdsaKey; + Security::KeychainCore::KeyItem *key; +}; + #endif // !_SECURITY_KEYITEM_H_ diff --git a/OSX/libsecurity_keychain/lib/Keychains.cpp b/OSX/libsecurity_keychain/lib/Keychains.cpp index de34f0b4..06c4bddc 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.cpp +++ b/OSX/libsecurity_keychain/lib/Keychains.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include #include "DLDbListCFPref.h" #include +#include #include #include #include @@ -395,7 +397,7 @@ static void check_system_keychain() // KeychainImpl // KeychainImpl::KeychainImpl(const Db &db) - : mAttemptedUpgrade(false), mDbItemMapMutex(Mutex::recursive), mDbDeletedItemMapMutex(Mutex::recursive), +: mCacheTimer(NULL), mSuppressTickle(false), mAttemptedUpgrade(false), mDbItemMapMutex(Mutex::recursive), mDbDeletedItemMapMutex(Mutex::recursive), mInCache(false), mDb(db), mCustomUnlockCreds (this), mIsInBatchMode (false), mMutex(Mutex::recursive) { dispatch_once(&SecKeychainSystemKeychainChecked, ^{ @@ -420,7 +422,7 @@ KeychainImpl::~KeychainImpl() } Mutex* -KeychainImpl::getMutexForObject() +KeychainImpl::getMutexForObject() const { return globals().storageManager.getStorageManagerMutex(); } @@ -490,6 +492,9 @@ KeychainImpl::create(UInt32 passwordLength, const void *inPassword) AclFactory::PasswordChangeCredentials pCreds (password, alloc); AclFactory::AnyResourceContext rcc(pCreds); create(&rcc); + + // Now that we've created, trigger setting the defaultCredentials + mDb->open(); } void KeychainImpl::create(ConstStringPtr inPassword) @@ -510,6 +515,9 @@ KeychainImpl::create() AclFactory aclFactory; AclFactory::AnyResourceContext rcc(aclFactory.unlockCred()); create(&rcc); + + // Now that we've created, trigger setting the defaultCredentials + mDb->open(); } void KeychainImpl::createWithBlob(CssmData &blob) @@ -767,8 +775,6 @@ KeychainImpl::isActive() const void KeychainImpl::completeAdd(Item &inItem, PrimaryKey &primaryKey) { - - // The inItem shouldn't be in the cache yet assert(!inItem->inCache()); @@ -788,7 +794,7 @@ void KeychainImpl::completeAdd(Item &inItem, PrimaryKey &primaryKey) // uniquifying items. We really need to insert the item into the // map before we start the add. And have the item be in an // "is being added" state. - secdebug("keychain", "add of new item %p somehow replaced %p", + secnotice("keychain", "add of new item %p somehow replaced %p", inItem.get(), oldItem); mDbItemMap.erase(p.first); @@ -850,7 +856,7 @@ KeychainImpl::didUpdate(const Item &inItem, PrimaryKey &oldPK, // uniquifying items. We really need to insert the item into // the map with the new primary key before we start the update. // And have the item be in an "is being updated" state. - secdebug("keychain", "update of item %p somehow replaced %p", + secnotice("keychain", "update of item %p somehow replaced %p", inItem.get(), oldItem); mDbItemMap.erase(p.first); @@ -861,24 +867,20 @@ KeychainImpl::didUpdate(const Item &inItem, PrimaryKey &oldPK, } } - // Item updates now are technically a delete and re-add, so post these events instead of kSecUpdateEvent - postEvent(kSecDeleteEvent, inItem); - postEvent(kSecAddEvent, inItem); + // Item updates now are technically a delete and re-add, so post these events instead of kSecUpdateEvent + postEvent(kSecDeleteEvent, inItem, oldPK); + postEvent(kSecAddEvent, inItem); } void KeychainImpl::deleteItem(Item &inoutItem) { { - // We don't need to hold the DO mutex through event posting, and, in fact, doing so causes deadlock. - // Hold it only as long as needed, instead. - - // item must be persistent if (!inoutItem->isPersistent()) MacOSError::throwMe(errSecInvalidItemRef); - secdebug("kcnotify", "starting deletion of item %p", inoutItem.get()); + secinfo("kcnotify", "starting deletion of item %p", inoutItem.get()); DbUniqueRecord uniqueId = inoutItem->dbUniqueRecord(); PrimaryKey primaryKey = inoutItem->primaryKey(); @@ -909,6 +911,13 @@ KeychainImpl::deleteItem(Item &inoutItem) postEvent(kSecDeleteEvent, inoutItem); } +void KeychainImpl::changeDatabase(CssmClient::Db db) +{ + StLock_(mDbMutex); + mDb = db; + mDb->defaultCredentials(this); +} + CssmClient::CSP KeychainImpl::csp() @@ -1020,6 +1029,7 @@ KeychainImpl::_lookupItem(const PrimaryKey &primaryKey) ItemImpl * KeychainImpl::_lookupDeletedItemOnly(const PrimaryKey &primaryKey) { + StLock _(mDbDeletedItemMapMutex); DbItemMap::iterator it = mDbDeletedItemMap.find(primaryKey); if (it != mDbDeletedItemMap.end()) { @@ -1043,8 +1053,7 @@ KeychainImpl::item(const PrimaryKey &primaryKey) try { // We didn't find it so create a new item with just a keychain and - // a primary key. However since we aren't holding - // globals().apiLock anymore some other thread might have beaten + // a primary key. Some other thread might have beaten // us to creating this item and adding it to the cache. If that // happens we retry the lookup. return Item(this, primaryKey); @@ -1168,7 +1177,7 @@ KeychainImpl::didDeleteItem(ItemImpl *inItemImpl) StLock_(mMutex); // Called by CCallbackMgr - secdebug("kcnotify", "%p notified that item %p was deleted", this, inItemImpl); + secinfo("kcnotify", "%p notified that item %p was deleted", this, inItemImpl); removeItem(inItemImpl->primaryKey(), inItemImpl); } @@ -1230,14 +1239,14 @@ KeychainImpl::forceRemoveFromCache(ItemImpl* inItemImpl) { } } // drop mDbDeletedItemMapMutex } catch(UnixError ue) { - secdebugfunc("keychain", "caught UnixError: %d %s", ue.unixError(), ue.what()); + secnotice("keychain", "caught UnixError: %d %s", ue.unixError(), ue.what()); } catch (CssmError cssme) { const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("keychain", "caught CssmError: %d %s", (int) cssme.error, errStr); + secnotice("keychain", "caught CssmError: %d %s", (int) cssme.error, errStr); } catch (MacOSError mose) { - secdebugfunc("keychain", "MacOSError: %d", (int)mose.osStatus()); + secnotice("keychain", "MacOSError: %d", (int)mose.osStatus()); } catch(...) { - secdebugfunc("keychain", "Unknown error"); + secnotice("keychain", "Unknown error"); } } @@ -1349,13 +1358,20 @@ KeychainImpl::setBatchMode(Boolean mode, Boolean rollback) KCEventNotifier::PostKeychainEvent(kSecKeychainEnteredBatchModeEvent); } } - void KeychainImpl::postEvent(SecKeychainEvent kcEvent, ItemImpl* item) +{ + postEvent(kcEvent, item, NULL); +} + +void +KeychainImpl::postEvent(SecKeychainEvent kcEvent, ItemImpl* item, PrimaryKey pk) { PrimaryKey primaryKey; - { + if(pk.get()) { + primaryKey = pk; + } else { StLock_(mMutex); if (item != NULL) @@ -1383,6 +1399,12 @@ KeychainImpl::postEvent(SecKeychainEvent kcEvent, ItemImpl* item) } } +void KeychainImpl::tickle() { + if(!mSuppressTickle) { + globals().storageManager.tickleKeychain(this); + } +} + bool KeychainImpl::performKeychainUpgradeIfNeeded() { // Grab this keychain's mutex. This might not be sufficient, since the @@ -1390,7 +1412,7 @@ bool KeychainImpl::performKeychainUpgradeIfNeeded() { StLock_(mMutex); if(!globals().integrityProtection()) { - secdebugfunc("integrity", "skipping upgrade for %s due to global integrity protection being diabled", mDb->name()); + secnotice("integrity", "skipping upgrade for %s due to global integrity protection being disabled", mDb->name()); return false; } @@ -1401,7 +1423,7 @@ bool KeychainImpl::performKeychainUpgradeIfNeeded() { // We only want to upgrade file-based Apple keychains. Check the GUID. if(mDb->dl()->guid() != gGuidAppleCSPDL) { - secdebugfunc("integrity", "skipping upgrade for %s due to guid mismatch\n", mDb->name()); + secnotice("integrity", "skipping upgrade for %s due to guid mismatch\n", mDb->name()); return false; } @@ -1412,7 +1434,7 @@ bool KeychainImpl::performKeychainUpgradeIfNeeded() { // Don't upgrade the System root certificate keychain (to make old tp code happy) if(strncmp(mDb->name(), SYSTEM_ROOT_STORE_PATH, strlen(SYSTEM_ROOT_STORE_PATH)) == 0) { - secdebugfunc("integrity", "skipping upgrade for %s\n", mDb->name()); + secnotice("integrity", "skipping upgrade for %s\n", mDb->name()); return false; } @@ -1424,104 +1446,262 @@ bool KeychainImpl::performKeychainUpgradeIfNeeded() { if(cssme.error == CSSMERR_DL_DATASTORE_DOESNOT_EXIST) { // oh well! We tried to get the blob version of a database // that doesn't exist. It doesn't need migration, so do nothing. - secdebugfunc("integrity", "dbBlobVersion() failed for a non-existent database"); + secnotice("integrity", "dbBlobVersion() failed for a non-existent database"); return false; } else { // Some other error occurred. We can't upgrade this keychain, so fail. const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "dbBlobVersion() failed for a CssmError: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "dbBlobVersion() failed for a CssmError: %d %s", (int) cssme.error, errStr); return false; } } catch (...) { - secdebugfunc("integrity", "dbBlobVersion() failed for an unknown reason"); + secnotice("integrity", "dbBlobVersion() failed for an unknown reason"); return false; } - if(dbBlobVersion != SecurityServer::DbBlob::currentVersion) { - secdebugfunc("integrity", "going to upgrade %s from version %d to %d!", mDb->name(), dbBlobVersion, SecurityServer::DbBlob::currentVersion); - // We need to opportunistically perform the upgrade/reload dance. - // - // If the keychain is unlocked, try to upgrade it. - // In either case, reload the database from disk. - // We need this keychain's read/write lock. - // Try to grab the keychain write lock. - StReadWriteLock lock(mRWLock, StReadWriteLock::TryWrite); + // Check the location of this keychain + string path = mDb->name(); + string keychainDbPath = StorageManager::makeKeychainDbFilename(path); - // If we didn't manage to grab the lock, there's readers out there - // currently reading this keychain. Abort the upgrade. - if(!lock.isLocked()) { - return false; - } + bool inHomeLibraryKeychains = StorageManager::pathInHomeLibraryKeychains(path); + + string keychainDbSuffix = "-db"; + bool endsWithKeychainDb = (path.size() > keychainDbSuffix.size() && (0 == path.compare(path.size() - keychainDbSuffix.size(), keychainDbSuffix.size(), keychainDbSuffix))); + + bool isSystemKeychain = (0 == path.compare("/Library/Keychains/System.keychain")); + + bool result = false; + + if(inHomeLibraryKeychains && endsWithKeychainDb && dbBlobVersion == SecurityServer::DbBlob::version_MacOS_10_0) { + // something has gone horribly wrong: an old-versioned keychain has a .keychain-db name. Rename it. + string basePath = path; + basePath.erase(basePath.end()-3, basePath.end()); + + attemptKeychainRename(path, basePath, dbBlobVersion); + + // If we moved to a good path, we might still want to perform the upgrade. Update our variables. + path = mDb->name(); try { - // We can only attempt an upgrade if the keychain is currently unlocked - // There's a TOCTTOU issue here, but it's going to be rare in practice, and the upgrade will simply fail. - if(!mDb->isLocked()) { - secdebugfunc("integrity", "attempting migration on database %s", mDb->name()); - // Database blob is out of date. Attempt a migration. - uint32 convertedVersion = attemptKeychainMigration(dbBlobVersion, SecurityServer::DbBlob::currentVersion); - if(convertedVersion == SecurityServer::DbBlob::currentVersion) { - secdebugfunc("integrity", "conversion succeeded"); - } else { - secdebugfunc("integrity", "conversion failed, keychain is still %d", convertedVersion); - } - } + dbBlobVersion = mDb->dbBlobVersion(); } catch (CssmError cssme) { const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); + secnotice("integrity", "dbBlobVersion() after a rename failed for a CssmError: %d %s", (int) cssme.error, errStr); + return false; } catch (...) { - // Something went wrong, but don't worry about it. + secnotice("integrity", "dbBlobVersion() failed for an unknown reason after a rename"); + return false; + } + + endsWithKeychainDb = (path.size() > keychainDbSuffix.size() && (0 == path.compare(path.size() - keychainDbSuffix.size(), keychainDbSuffix.size(), keychainDbSuffix))); + keychainDbPath = StorageManager::makeKeychainDbFilename(path); + secnotice("integrity", "after rename, our database thinks that it is %s", path.c_str()); + } + + // Migrate an old keychain in ~/Library/Keychains + if(inHomeLibraryKeychains && dbBlobVersion != SecurityServer::DbBlob::version_partition && !endsWithKeychainDb) { + // We can only attempt to migrate an unlocked keychain. + if(mDb->isLocked()) { + // However, it's possible that while we weren't doing any keychain operations, someone upgraded the keychain, + // and then locked it. No way around hitting the filesystem here: check for the existence of a new file and, + // if no new file exists, quit. + DLDbIdentifier mungedDLDbIdentifier = StorageManager::mungeDLDbIdentifier(mDb->dlDbIdentifier(), false); + string mungedPath(mungedDLDbIdentifier.dbName()); + + // If this matches the file we already have, skip the upgrade. Otherwise, continue. + if(mungedPath == path) { + secnotice("integrity", "skipping upgrade for locked keychain %s\n", mDb->name()); + return false; + } + } + + result = keychainMigration(path, dbBlobVersion, keychainDbPath, SecurityServer::DbBlob::version_partition); + } else if(inHomeLibraryKeychains && dbBlobVersion == SecurityServer::DbBlob::version_partition && !endsWithKeychainDb) { + // This is a new-style keychain with the wrong name, try to rename it + attemptKeychainRename(path, keychainDbPath, dbBlobVersion); + result = true; + } else if(isSystemKeychain && dbBlobVersion == SecurityServer::DbBlob::version_partition) { + // Try to "unupgrade" the system keychain, to clean up our old issues + secnotice("integrity", "attempting downgrade for %s version %d (%d %d %d)", path.c_str(), dbBlobVersion, inHomeLibraryKeychains, endsWithKeychainDb, isSystemKeychain); + + // First step: acquire the credentials to allow for ACL modification + SecurityServer::SystemKeychainKey skk(kSystemUnlockFile); + if(skk.valid()) { + // We've managed to read the key; now, create credentials using it + CssmClient::Key systemKeychainMasterKey(csp(), skk.key(), true); + CssmClient::AclFactory::MasterKeyUnlockCredentials creds(systemKeychainMasterKey, Allocator::standard(Allocator::sensitive)); + + // Attempt the downgrade, using our master key as the ACL override + result = keychainMigration(path, dbBlobVersion, path, SecurityServer::DbBlob::version_MacOS_10_0, creds.getAccessCredentials()); + } else { + secnotice("integrity", "Couldn't read System.keychain key, skipping update"); } + } else { + secnotice("integrity", "not attempting migration for %s version %d (%d %d %d)", path.c_str(), dbBlobVersion, inHomeLibraryKeychains, endsWithKeychainDb, isSystemKeychain); + + // Since we don't believe any migration needs to be done here, mark the + // migration as "attempted" to short-circuit future checks. + mAttemptedUpgrade = true; + } - // No matter if the migrator succeeded, we need to reload this keychain from disk. - // Maybe someone else beat us to upgrading the keychain, but it's been locked since then. - secdebugfunc("integrity", "reloading keychain"); - globals().storageManager.reloadKeychain(this); - secdebugfunc("integrity", "database %s is version %d", mDb->name(), mDb->dbBlobVersion()); + // We might have changed our location on disk. Let StorageManager know. + globals().storageManager.registerKeychainImpl(this); + + // if we attempted a migration, try to clean up leftover files from XARA backup have provided me with 12GB of login keychain copies + if(result) { + string pattern = path + "_*_backup"; + glob_t pglob = {}; + secnotice("integrity", "globbing for %s", pattern.c_str()); + int globresult = glob(pattern.c_str(), GLOB_MARK, NULL, &pglob); + if(globresult == 0) { + secnotice("integrity", "glob: %lu results", pglob.gl_pathc); + if(pglob.gl_pathc > 10) { + // There are more than 10 backup files, indicating a problem. + // Delete all but one of them. Under rdar://23950408, they should all be identical. + secnotice("integrity", "saving backup file: %s", pglob.gl_pathv[0]); + for(int i = 1; i < pglob.gl_pathc; i++) { + secnotice("integrity", "cleaning up backup file: %s", pglob.gl_pathv[i]); + // ignore return code; this is a best-effort cleanup + unlink(pglob.gl_pathv[i]); + } + } + + struct stat st; + bool pathExists = (::stat(path.c_str(), &st) == 0); + bool keychainDbPathExists = (::stat(keychainDbPath.c_str(), &st) == 0); + + if(!pathExists && keychainDbPathExists && pglob.gl_pathc >= 1) { + // We have a file at keychainDbPath, no file at path, and at least one backup keychain file. + // + // Move the backup file to path, to simulate the current "split-world" view, + // which copies from path to keychainDbPath, then modifies keychainDbPath. + secnotice("integrity", "moving backup file %s to %s", pglob.gl_pathv[0], path.c_str()); + ::rename(pglob.gl_pathv[0], path.c_str()); + } + } - return true; + globfree(&pglob); } - return false; + return result; } -// Make sure you have this keychain's mutex and write lock when you call this function! -uint32 KeychainImpl::attemptKeychainMigration(uint32 oldBlobVersion, uint32 newBlobVersion) { - Db db = mDb; // let's not muck up our db for now - db->takeFileLock(); +bool KeychainImpl::keychainMigration(const string oldPath, const uint32 dbBlobVersion, const string newPath, const uint32 newBlobVersion, const AccessCredentials *cred) { + secnotice("integrity", "going to migrate %s at version %d to", oldPath.c_str(), dbBlobVersion); + secnotice("integrity", " %s at version %d", newPath.c_str(), newBlobVersion); + + // We need to opportunistically perform the upgrade/reload dance. + // + // If the keychain is unlocked, try to upgrade it. + // In either case, reload the database from disk. + // We need this keychain's read/write lock. + + // Try to grab the keychain write lock. + StReadWriteLock lock(mRWLock, StReadWriteLock::TryWrite); + + // If we didn't manage to grab the lock, there's readers out there + // currently reading this keychain. Abort the upgrade. + if(!lock.isLocked()) { + secnotice("integrity", "couldn't get read-write lock, aborting upgrade"); + return false; + } + + // Take the file lock on the existing database. We don't need to commit this txion, because we're not planning to + // change the original keychain. + FileLockTransaction fileLockmDb(mDb); // Let's reload this keychain to see if someone changed it on disk globals().storageManager.reloadKeychain(this); + bool result = false; + + try { + // We can only attempt an upgrade if the keychain is currently unlocked + // There's a TOCTTOU issue here, but it's going to be rare in practice, and the upgrade will simply fail. + if(!mDb->isLocked()) { + secnotice("integrity", "have a plan to migrate database %s", mDb->name()); + // Database blob is out of date. Attempt a migration. + uint32 convertedVersion = attemptKeychainMigration(oldPath, dbBlobVersion, newPath, newBlobVersion, cred); + if(convertedVersion == newBlobVersion) { + secnotice("integrity", "conversion succeeded"); + result = true; + } else { + secnotice("integrity", "conversion failed, keychain is still %d", convertedVersion); + } + } else { + secnotice("integrity", "keychain is locked, can't upgrade"); + } + } catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secnotice("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); + } catch (...) { + // Something went wrong, but don't worry about it. + secnotice("integrity", "caught unknown error"); + } + + // No matter if the migrator succeeded, we need to reload this keychain from disk. + secnotice("integrity", "reloading keychain after migration"); + globals().storageManager.reloadKeychain(this); + secnotice("integrity", "database %s is now version %d", mDb->name(), mDb->dbBlobVersion()); + + return result; +} + +// Make sure you have this keychain's mutex and write lock when you call this function! +uint32 KeychainImpl::attemptKeychainMigration(const string oldPath, const uint32 oldBlobVersion, const string newPath, const uint32 newBlobVersion, const AccessCredentials* cred) { if(mDb->dbBlobVersion() == newBlobVersion) { // Someone else upgraded this, hurray! - secdebugfunc("integrity", "reloaded keychain version %d, quitting", mDb->dbBlobVersion()); - db->releaseFileLock(false); + secnotice("integrity", "reloaded keychain version %d, quitting", mDb->dbBlobVersion()); return newBlobVersion; } mAttemptedUpgrade = true; uint32 newDbVersion = oldBlobVersion; - try { - secdebugfunc("integrity", "attempting migration from version %d to %d", oldBlobVersion, newBlobVersion); + if( (oldBlobVersion == SecurityServer::DbBlob::version_MacOS_10_0 && newBlobVersion == SecurityServer::DbBlob::version_partition) || + (oldBlobVersion == SecurityServer::DbBlob::version_partition && newBlobVersion == SecurityServer::DbBlob::version_MacOS_10_0 && cred != NULL)) { + // Here's the upgrade outline: + // + // 1. Make a copy of the keychain with the new file path + // 2. Open that keychain database. + // 3. Recode it to use the new version. + // 4. Notify the StorageManager that the DLDB identifier for this keychain has changed. + // + // If we're creating a new keychain file, on failure, try to delete the new file. Otherwise, + // everyone will try to use it. + + secnotice("integrity", "attempting migration from version %d to %d", oldBlobVersion, newBlobVersion); - // First, make a backup of this database (so we never lose data if something goes wrong) - mDb->makeBackup(); + Db db; + bool newFile = (oldPath != newPath); + + try { + DLDbIdentifier dldbi(dlDbIdentifier().ssuid(), newPath.c_str(), dlDbIdentifier().dbLocation()); + if(newFile) { + secnotice("integrity", "creating a new keychain at %s", newPath.c_str()); + db = mDb->cloneTo(dldbi); + } else { + secnotice("integrity", "using old keychain at %s", newPath.c_str()); + db = mDb; + } + FileLockTransaction fileLockDb(db); + + if(newFile) { + // since we're creating a completely new file, if this migration fails, delete the new file + fileLockDb.setDeleteOnFailure(); + } - if(oldBlobVersion == SecurityServer::DbBlob::version_MacOS_10_0 && newBlobVersion == SecurityServer::DbBlob::version_partition) { // Let the upgrade begin. newDbVersion = db->recodeDbToVersion(newBlobVersion); if(newDbVersion != newBlobVersion) { // Recoding failed. Don't proceed. - secdebugfunc("integrity", "recodeDbToVersion failed, version is still %d", newDbVersion); - db->releaseFileLock(false); + secnotice("integrity", "recodeDbToVersion failed, version is still %d", newDbVersion); return newDbVersion; } - secdebugfunc("integrity", "recoded db successfully, adding extra integrity"); + secnotice("integrity", "recoded db successfully, adding extra integrity"); Keychain keychain(db); @@ -1529,6 +1709,7 @@ uint32 KeychainImpl::attemptKeychainMigration(uint32 oldBlobVersion, uint32 newB // Don't upgrade this keychain, since we just upgraded the DB // But the DB won't return any new data until the txion commits keychain->mAttemptedUpgrade = true; + keychain->mSuppressTickle = true; SecItemClass classes[] = {kSecGenericPasswordItemClass, kSecInternetPasswordItemClass, @@ -1549,14 +1730,19 @@ uint32 KeychainImpl::attemptKeychainMigration(uint32 oldBlobVersion, uint32 newB while(kcc->next(item)) { try { - // Force the item to set integrity. The keychain is confused about its version because it hasn't written to disk yet, - // but if we've reached this point, the keychain supports integrity. - item->setIntegrity(true); + if(newBlobVersion == SecurityServer::DbBlob::version_partition) { + // Force the item to set integrity. The keychain is confused about its version because it hasn't written to disk yet, + // but if we've reached this point, the keychain supports integrity. + item->setIntegrity(true); + } else if(newBlobVersion == SecurityServer::DbBlob::version_MacOS_10_0) { + // We're downgrading this keychain. Pass in whatever credentials our caller thinks will allow this ACL modification. + item->removeIntegrity(cred); + } } catch(CssmError cssme) { // During recoding, we might have deleted some corrupt keys. Because of this, we might have zombie SSGroup records left in // the database that have no matching key. If we get a DL_RECORD_NOT_FOUND error, delete the matching item record. if (cssme.osStatus() == CSSMERR_DL_RECORD_NOT_FOUND) { - secdebugfunc("integrity", "deleting corrupt (Not Found) record"); + secnotice("integrity", "deleting corrupt (Not Found) record"); keychain->deleteItem(item); } else { throw; @@ -1565,30 +1751,75 @@ uint32 KeychainImpl::attemptKeychainMigration(uint32 oldBlobVersion, uint32 newB } } - // If we reach here, tell releaseFileLock() to commit the transaction and return the new blob version - secdebugfunc("integrity", "releasing file lock"); - db->releaseFileLock(true); + // Tell securityd we're done with the upgrade, to re-enable all protections + db->recodeFinished(); + + // If we reach here, tell the file locks to commit the transaction and return the new blob version + fileLockDb.success(); - secdebugfunc("integrity", "success, returning version %d", newDbVersion); + secnotice("integrity", "success, returning version %d", newDbVersion); return newDbVersion; + } catch(UnixError ue) { + secnotice("integrity", "caught UnixError: %d %s", ue.unixError(), ue.what()); + } catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secnotice("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); + } catch (MacOSError mose) { + secnotice("integrity", "MacOSError: %d", (int)mose.osStatus()); + } catch (const std::bad_cast & e) { + secnotice("integrity", "***** bad cast: %s", e.what()); + } catch (...) { + // We failed to migrate. We won't commit the transaction, so the blob on-disk stays the same. + secnotice("integrity", "***** unknown error"); } - } catch (CssmError cssme) { - const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); - db->releaseFileLock(false); - } catch (MacOSError mose) { - secdebugfunc("integrity", "MacOSError: %d", (int)mose.osStatus()); - db->releaseFileLock(false); - } catch (...) { - // We failed to migrate. We won't commit the transaction, so the blob on-disk stays the same. - secdebugfunc("integrity", "unknown error"); - db->releaseFileLock(false); + } else { + secnotice("integrity", "no migration path for %s at version %d to", oldPath.c_str(), oldBlobVersion); + secnotice("integrity", " %s at version %d", newPath.c_str(), newBlobVersion); + return oldBlobVersion; } - // If we reached here, we failed the migration. Return the old version. + // If we reached here, the migration failed. Return the old version. return oldBlobVersion; } +void KeychainImpl::attemptKeychainRename(const string oldPath, const string newPath, uint32 blobVersion) { + secnotice("integrity", "attempting to rename keychain (%d) from %s to %s", blobVersion, oldPath.c_str(), newPath.c_str()); + + // Take the file lock on this database, so other people won't try to move it before we do + // NOTE: during a migration from a v256 to a v512 keychain, the db is first copied from the .keychain to the + // .keychain-db path. Other non-migrating processes, if they open the keychain, enter this function to + // try to move it back. These will attempt to take the .keychain-db file lock, but they will not succeed + // until the migration is finished. Once they acquire that, they might try to take the .keychain file lock. + // This is technically lock inversion, but deadlocks will not happen since the migrating process creates the + // .keychain-db file lock before creating the .keychain-db file, so other processes will not try to grab the + // .keychain-db lock in this function before the migrating process already has it. + FileLockTransaction fileLockmDb(mDb); + + // first, check if someone renamed this keychain while we were grabbing the file lock + globals().storageManager.reloadKeychain(this); + + uint32 dbBlobVersion = SecurityServer::DbBlob::version_MacOS_10_0; + + try { + dbBlobVersion = mDb->dbBlobVersion(); + } catch (...) { + secnotice("integrity", "dbBlobVersion() failed for an unknown reason while renaming, aborting rename"); + return; + } + + if(dbBlobVersion != blobVersion) { + secnotice("integrity", "database version changed while we were grabbing the file lock; aborting rename"); + return; + } + + if(oldPath != mDb->name()) { + secnotice("integrity", "database location changed while we were grabbing the file lock; aborting rename"); + return; + } + + // we're still at the original location and version; go ahead and do the move + globals().storageManager.rename(this, newPath.c_str()); +} Keychain::Keychain() { @@ -1663,11 +1894,11 @@ bool KeychainImpl::hasIntegrityProtection() { if(mDb->dbBlobVersion() >= SecurityServer::DbBlob::version_partition) { return true; } else { - secdebugfunc("integrity", "keychain blob version does not support integrity"); + secnotice("integrity", "keychain blob version does not support integrity"); return false; } } else { - secdebugfunc("integrity", "keychain guid does not support integrity"); + secnotice("integrity", "keychain guid does not support integrity"); return false; } return false; diff --git a/OSX/libsecurity_keychain/lib/Keychains.h b/OSX/libsecurity_keychain/lib/Keychains.h index 334cd682..0e0c87f9 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.h +++ b/OSX/libsecurity_keychain/lib/Keychains.h @@ -136,7 +136,7 @@ public: virtual ~KeychainImpl(); Mutex* getKeychainMutex(); - Mutex* getMutexForObject(); + Mutex* getMutexForObject() const; ReadWriteLock* getKeychainReadWriteLock(); void aboutToDestruct(); @@ -184,6 +184,7 @@ public: KCCursor createCursor(const SecKeychainAttributeList *attrList); KCCursor createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList); CssmClient::Db database() { StLock_(mDbMutex); return mDb; } + void changeDatabase(CssmClient::Db db); DLDbIdentifier dlDbIdentifier() const { return mDb->dlDbIdentifier(); } CssmClient::CSP csp(); @@ -222,6 +223,7 @@ public: void inCache(bool inCache) throw() { mInCache = inCache; } void postEvent(SecKeychainEvent kcEvent, ItemImpl* item); + void postEvent(SecKeychainEvent kcEvent, ItemImpl* item, PrimaryKey pk); void addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl); @@ -236,8 +238,27 @@ private: // DO NOT hold any of the keychain locks when you call this bool performKeychainUpgradeIfNeeded(); + // Notify the keychain that you're accessing it. Used in conjunction with + // the StorageManager for time-based caching. + void tickle(); + + // Used by StorageManager to remember the timer->keychain pairing + dispatch_source_t mCacheTimer; + + // Set this to true to make tickling do nothing. + bool mSuppressTickle; + +public: + // Grab the locks and then call attemptKeychainMigration + // The access credentials are only used when downgrading version, and will be passed along with ACL edits + bool keychainMigration(const string oldPath, const uint32 dbBlobVersion, const string newPath, const uint32 newBlobVersion, const AccessCredentials *cred = NULL); + +private: // Attempt to upgrade this keychain's database - uint32 attemptKeychainMigration(uint32 oldBlobVersion, uint32 newBlobVersion); + uint32 attemptKeychainMigration(const string oldPath, const uint32 oldBlobVersion, const string newPath, const uint32 newBlobVersion, const AccessCredentials *cred); + + // Attempt to rename this keychain, if someone hasn't beaten us to it + void attemptKeychainRename(const string oldPath, const string newPath, uint32 blobVersion); // Remember if we've attempted to upgrade this keychain's database bool mAttemptedUpgrade; @@ -250,9 +271,18 @@ private: // mDbDeletedItemMapMutex when you call this function. void forceRemoveFromCache(ItemImpl* inItemImpl); + // Looks up an item in the item cache. + // + // To use this in a thread-safe manner, you must hold this keychain's mutex + // from before you begin this operation until you have safely completed a + // CFRetain on the resulting ItemImpl. ItemImpl *_lookupItem(const PrimaryKey &primaryKey); // Looks up a deleted item in the deleted item map. Does not check the normal map. + // + // To use this in a thread-safe manner, you must hold this keychain's mutex + // from before you begin this operation until you have safely completed a + // CFRetain on the resulting ItemImpl. ItemImpl *_lookupDeletedItemOnly(const PrimaryKey &primaryKey); const AccessCredentials *makeCredentials(); diff --git a/OSX/libsecurity_keychain/lib/Policies.cpp b/OSX/libsecurity_keychain/lib/Policies.cpp index 43f5c5a5..4f0cd433 100644 --- a/OSX/libsecurity_keychain/lib/Policies.cpp +++ b/OSX/libsecurity_keychain/lib/Policies.cpp @@ -82,12 +82,12 @@ Policy::Policy(TP supportingTp, const CssmOid &policyOid) mAuxValue(Allocator::standard()) { // value is as yet unimplemented - secdebug("policy", "Policy() this %p", this); + secinfo("policy", "Policy() this %p", this); } Policy::~Policy() throw() { - secdebug("policy", "~Policy() this %p", this); + secinfo("policy", "~Policy() this %p", this); } void Policy::setValue(const CssmData &value) diff --git a/OSX/libsecurity_keychain/lib/SecAccess.cpp b/OSX/libsecurity_keychain/lib/SecAccess.cpp index 39a8b120..ba74e379 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.cpp +++ b/OSX/libsecurity_keychain/lib/SecAccess.cpp @@ -30,7 +30,6 @@ #include "SecBridge.h" #include -#undef secdebug #include diff --git a/OSX/libsecurity_keychain/lib/SecAccess.h b/OSX/libsecurity_keychain/lib/SecAccess.h index f355ab94..2ba66080 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.h +++ b/OSX/libsecurity_keychain/lib/SecAccess.h @@ -135,7 +135,7 @@ OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef __nullable trustedli @param owner A pointer to a CSSM access control list owner. @param aclCount An unsigned 32-bit integer representing the number of items in the access control list. @param acls A pointer to the access control list. - @param On return, a pointer to the new access reference. + @param accessRef On return, a pointer to the new access reference. @result A result code. See "Security Error Codes" (SecBase.h). @discussion For 10.7 and later please use the SecAccessCreateWithOwnerAndACL API */ diff --git a/OSX/libsecurity_keychain/lib/SecBasePriv.h b/OSX/libsecurity_keychain/lib/SecBasePriv.h index 88721e24..23599b80 100644 --- a/OSX/libsecurity_keychain/lib/SecBasePriv.h +++ b/OSX/libsecurity_keychain/lib/SecBasePriv.h @@ -78,6 +78,7 @@ enum errSecReturnMissingPointer = priv_errSecParam, // -34014, /* The caller passed asked for something to be returned but did not pass in a result pointer. */ errSecMatchLimitUnsupported = priv_errSecParam, // -34015, /* The caller passed in a kSecMatchLimit key to a call which does not support limits. */ errSecItemIllegalQuery = priv_errSecParam, // -34016, /* The caller passed in a query which contained too many keys. */ + errSecMissingEntitlement = -34018, /* Internal error when a required entitlement isn't present. */ }; const char *cssmErrorString(CSSM_RETURN error); diff --git a/OSX/libsecurity_keychain/lib/SecBridge.h b/OSX/libsecurity_keychain/lib/SecBridge.h index 2c541baf..8486ad2a 100644 --- a/OSX/libsecurity_keychain/lib/SecBridge.h +++ b/OSX/libsecurity_keychain/lib/SecBridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2011,2013-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011,2013-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -45,14 +45,14 @@ using namespace KeychainCore; // END_API3(name, bad) // like END_API1, with API name as debug scope for printing function result // #define BEGIN_SECAPI \ - OSStatus __secapiresult = errSecSuccess; \ + OSStatus __secapiresult = errSecSuccess; \ try { #define END_SECAPI }\ catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \ catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } \ catch (...) { __secapiresult=errSecInternalComponent; } \ - return __secapiresult; + return __secapiresult; #define END_SECAPI1(BAD_RETURN_VAL) \ } \ catch (...) \ @@ -61,30 +61,97 @@ using namespace KeychainCore; } \ return __secapiresult; #define END_SECAPI1(BAD_RETURN_VAL) }\ - catch (...) { __secapiresult=BAD_RETURN_VAL; } \ - return __secapiresult; + catch (...) { __secapiresult=BAD_RETURN_VAL; } \ + return __secapiresult; #define END_SECAPI0 }\ - catch (...) { return; } + catch (...) { return; } + + +// +// BEGIN_SECKCITEMAPI +// Note: this macro assumes an input parameter named "itemRef" +// +#if SECTRUST_OSX +#define BEGIN_SECKCITEMAPI \ + OSStatus __secapiresult=errSecSuccess; \ + SecKeychainItemRef __itemImplRef=NULL; \ + bool __is_certificate=(itemRef && (CFGetTypeID(itemRef) == SecCertificateGetTypeID())); \ + if (__is_certificate) { \ + if (SecCertificateIsItemImplInstance((SecCertificateRef)itemRef)) { \ + __itemImplRef=(SecKeychainItemRef)CFRetain(itemRef); \ + } else { \ + __itemImplRef=(SecKeychainItemRef)SecCertificateCopyKeychainItem((SecCertificateRef)itemRef); \ + if (!__itemImplRef) { \ + __itemImplRef=(SecKeychainItemRef)SecCertificateCreateItemImplInstance((SecCertificateRef)itemRef); \ + (void)SecCertificateSetKeychainItem((SecCertificateRef)itemRef,__itemImplRef); \ + } \ + } \ + } else { \ + __itemImplRef=(SecKeychainItemRef)((itemRef) ? CFRetain(itemRef) : NULL); \ + } \ + try { +#else +#define BEGIN_SECKCITEMAPI \ + OSStatus __secapiresult=errSecSuccess; \ + SecKeychainItemRef __itemImplRef=(SecKeychainItemRef)((itemRef) ? CFRetain(itemRef) : NULL); \ + try { +#endif +// +// END_SECKCITEMAPI +// +#define END_SECKCITEMAPI } \ + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \ + catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } \ + catch (...) { __secapiresult=errSecInternalComponent; } \ + if (__itemImplRef) { CFRelease(__itemImplRef); } \ + return __secapiresult; + +// +// BEGIN_SECCERTAPI +// Note: this macro assumes an input parameter named "certificate" +// #if SECTRUST_OSX #define BEGIN_SECCERTAPI \ -OSStatus __secapiresult=errSecSuccess; \ -SecCertificateRef __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); \ -if (!__itemImplRef) { __itemImplRef=SecCertificateCreateItemImplInstance(certificate); } \ -try { + OSStatus __secapiresult=errSecSuccess; \ + SecCertificateRef __itemImplRef=NULL; \ + if (SecCertificateIsItemImplInstance(certificate)) { __itemImplRef=(SecCertificateRef)CFRetain(certificate); } \ + if (!__itemImplRef && certificate) { __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); } \ + if (!__itemImplRef && certificate) { __itemImplRef=SecCertificateCreateItemImplInstance(certificate); \ + (void)SecCertificateSetKeychainItem(certificate,__itemImplRef); } \ + try { #else #define BEGIN_SECCERTAPI \ -OSStatus __secapiresult=errSecSuccess; \ -SecCertificateRef __itemImplRef=(SecCertificateRef)((certificate)?CFRetain(certificate):NULL); \ -try { + OSStatus __secapiresult=errSecSuccess; \ + SecCertificateRef __itemImplRef=(SecCertificateRef)((certificate)?CFRetain(certificate):NULL); \ + try { #endif -#define END_SECCERTAPI }\ -catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ -catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \ -catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } \ -catch (...) { __secapiresult=errSecInternalComponent; } \ -if (__itemImplRef) { CFRelease(__itemImplRef); } \ -return __secapiresult; +// +// END_SECCERTAPI +// +#define END_SECCERTAPI } \ + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } \ + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } \ + catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } \ + catch (...) { __secapiresult=errSecInternalComponent; } \ + if (__itemImplRef) { CFRelease(__itemImplRef); } \ + return __secapiresult; + + +// +// BEGIN_SECKEYAPI +// +#define BEGIN_SECKEYAPI(resultType, resultInit) \ +resultType result = resultInit; try { + +extern "C" bool SecError(OSStatus status, CFErrorRef *error, CFStringRef format, ...); +#define END_SECKEYAPI }\ +catch (const MacOSError &err) { SecError(err.osStatus(), error, CFSTR("%s"), err.what()); result = NULL; } \ +catch (const CommonError &err) { SecError(SecKeychainErrFromOSStatus(err.osStatus()), error, CFSTR("%s"), err.what()); result = NULL; } \ +catch (const std::bad_alloc &) { SecError(errSecAllocate, error, CFSTR("allocation failed")); result = NULL; } \ +catch (...) { SecError(errSecInternalComponent, error, CFSTR("internal error")); result = NULL; } \ +return result; #endif /* !_SECURITY_SECBRIDGE_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecCFTypes.cpp b/OSX/libsecurity_keychain/lib/SecCFTypes.cpp index 474d8206..cfbf7e8e 100644 --- a/OSX/libsecurity_keychain/lib/SecCFTypes.cpp +++ b/OSX/libsecurity_keychain/lib/SecCFTypes.cpp @@ -58,7 +58,6 @@ SecCFTypes::SecCFTypes() : ItemImpl("SecKeychainItem"), KCCursorImpl("SecKeychainSearch"), KeychainImpl("SecKeychain"), - KeyItem("SecKey"), PasswordImpl("SecPassword"), Policy("SecPolicy"), PolicyCursor("SecPolicySearch"), diff --git a/OSX/libsecurity_keychain/lib/SecCFTypes.h b/OSX/libsecurity_keychain/lib/SecCFTypes.h index 18935453..c1a8e1d2 100644 --- a/OSX/libsecurity_keychain/lib/SecCFTypes.h +++ b/OSX/libsecurity_keychain/lib/SecCFTypes.h @@ -88,7 +88,6 @@ public: CFClass ItemImpl; CFClass KCCursorImpl; CFClass KeychainImpl; - CFClass KeyItem; CFClass PasswordImpl; CFClass Policy; CFClass PolicyCursor; diff --git a/OSX/libsecurity_keychain/lib/SecCertificate.cpp b/OSX/libsecurity_keychain/lib/SecCertificate.cpp index 8c908f64..b9086d28 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificate.cpp +++ b/OSX/libsecurity_keychain/lib/SecCertificate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -50,7 +50,6 @@ #include "AppleBaselineEscrowCertificates.h" -SecCertificateRef SecCertificateCreateItemImplInstance(SecCertificateRef certificate); OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle); extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); @@ -63,9 +62,12 @@ SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates"); using namespace CssmClient; -#if !SECTRUST_OSX CFTypeID +#if SECTRUST_OSX +static SecCertificateGetTypeID_osx(void) +#else SecCertificateGetTypeID(void) +#endif { BEGIN_SECAPI @@ -73,7 +75,33 @@ SecCertificateGetTypeID(void) END_SECAPI1(_kCFRuntimeNotATypeID) } + +Boolean +SecCertificateIsItemImplInstance(SecCertificateRef certificate) +{ + if (certificate == NULL) { + return false; + } +#if !SECTRUST_OSX + return true; +#else + 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; + } + + return (typeID == SecCertificateGetTypeID_osx() || + typeID == SecKeychainItemGetTypeID()) ? true : false; +#endif +} /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */ SecCertificateRef @@ -144,6 +172,26 @@ SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate) #endif } +#if !SECTRUST_OSX +OSStatus +SecCertificateSetKeychainItem(SecCertificateRef certificate, CFTypeRef keychain_item) +{ + // pre-STU, this function is a no-op since it's the same item reference + return errSecSuccess; +} +#endif + +#if !SECTRUST_OSX +CFTypeRef +SecCertificateCopyKeychainItem(SecCertificateRef certificate) +{ + if (certificate) { + CFRetain(certificate); + } + return certificate; +} +#endif + /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ OSStatus SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate) @@ -161,7 +209,16 @@ SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CE return errSecParam; } SecCertificateRef certRef = NULL; - CFDataRef dataRef = CFDataCreate(NULL, data->Data, data->Length); + + // REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch + // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly + // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits + // are non-zero, the length is incredibly wrong. + // + // Assume that there will not exist a certificate > 4GiB, and fake this length field. + CSSM_SIZE length = data->Length & 0xfffffffful; + + CFDataRef dataRef = CFDataCreate(NULL, data->Data, length); if (dataRef) { certRef = SecCertificateCreateWithData(NULL, dataRef); CFRelease(dataRef); @@ -201,7 +258,7 @@ SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data) OSStatus SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Item item(Certificate::required(__itemImplRef)); @@ -214,12 +271,28 @@ SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keycha OSStatus SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl +#if !SECTRUST_OSX + BEGIN_SECAPI + + Required(data) = Certificate::required(certificate)->data(); + + END_SECAPI +#else BEGIN_SECCERTAPI - Required(data) = Certificate::required(__itemImplRef)->data(); + if (!certificate || !data) { + __secapiresult=errSecParam; + } + else if (SecCertificateIsItemImplInstance(certificate)) { + Required(data) = Certificate::required(certificate)->data(); + } + else { + data->Length = (CSSM_SIZE)SecCertificateGetLength(certificate); + data->Data = (uint8*)SecCertificateGetBytePtr(certificate); + } END_SECCERTAPI +#endif } #if !SECTRUST_OSX @@ -228,7 +301,7 @@ CFDataRef SecCertificateCopyData(SecCertificateRef certificate) { CFDataRef data = NULL; - OSStatus __secapiresult = errSecSuccess; + OSStatus __secapiresult = errSecSuccess; try { CssmData output = Certificate::required(certificate)->data(); CFIndex length = (CFIndex)output.length(); @@ -241,26 +314,12 @@ SecCertificateCopyData(SecCertificateRef certificate) catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } catch (...) { __secapiresult=errSecInternalComponent; } - return data; + return data; } #endif #if !SECTRUST_OSX -CFDataRef -SecCertificateGetSHA1Digest(SecCertificateRef certificate) -{ - CFDataRef data = NULL; - OSStatus __secapiresult = errSecSuccess; - try { - data = Certificate::required(certificate)->sha1Hash(); - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } - return data; -} - +/* new in 10.12 */ CFDataRef SecCertificateCopySHA256Digest(SecCertificateRef certificate) { @@ -268,8 +327,9 @@ SecCertificateCopySHA256Digest(SecCertificateRef certificate) OSStatus __secapiresult = errSecSuccess; try { data = Certificate::required(certificate)->sha256Hash(); - if (data) + if (data) { CFRetain(data); + } } catch (const MacOSError &err) { __secapiresult=err.osStatus(); } catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } @@ -277,8 +337,23 @@ SecCertificateCopySHA256Digest(SecCertificateRef certificate) catch (...) { __secapiresult=errSecInternalComponent; } return data; } +#endif - +#if !SECTRUST_OSX +CFDataRef +SecCertificateGetSHA1Digest(SecCertificateRef certificate) +{ + CFDataRef data = NULL; + OSStatus __secapiresult = errSecSuccess; + try { + data = Certificate::required(certificate)->sha1Hash(); + } + catch (const MacOSError &err) { __secapiresult=err.osStatus(); } + catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } + catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } + catch (...) { __secapiresult=errSecInternalComponent; } + return data; +} #endif #if !SECTRUST_OSX @@ -324,7 +399,7 @@ SecCertificateCopyDNSNames(SecCertificateRef certificate) OSStatus SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(certificateType) = Certificate::required(__itemImplRef)->type(); @@ -336,7 +411,7 @@ SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificate OSStatus SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(subject) = Certificate::required(__itemImplRef)->subjectName(); @@ -348,7 +423,7 @@ SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **s OSStatus SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(issuer) = Certificate::required(__itemImplRef)->issuerName(); @@ -360,55 +435,12 @@ SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **is OSStatus SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) { -#if !SECTRUST_OSX - BEGIN_SECAPI - - Required(clHandle) = Certificate::required(certificate)->clHandle(); - - END_SECAPI -#else -#if 0 - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(clHandle) = Certificate::required(__itemImplRef)->clHandle(); END_SECCERTAPI -#endif - /* bridge code to support deprecated functionality */ - OSStatus __secapiresult=errSecSuccess; - bool kcItem=true; - SecCertificateRef __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); - if (!__itemImplRef) { __itemImplRef=SecCertificateCreateItemImplInstance(certificate); kcItem=false; } - try { - Required(clHandle) = Certificate::required(__itemImplRef)->clHandle(); - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } - if (__itemImplRef) { - if (!kcItem) { - /* we can't release the temporary certificate, or the CL handle becomes invalid. - * for now, just stick the temporary certificate into an array. - * TBD: use a dictionary, indexed by hash of certificate. */ - static CFMutableArrayRef sLegacyCertArray = NULL; - if (!sLegacyCertArray) { - sLegacyCertArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - if (!sLegacyCertArray) { - return errSecAllocate; - } - } - CFArrayAppendValue(sLegacyCertArray, __itemImplRef); -#ifndef NDEBUG - syslog(LOG_ERR, "WARNING: SecCertificateGetCLHandle called on certificate which is not in a keychain."); -#endif - } - CFRelease(__itemImplRef); - } - return __secapiresult; - -#endif } /* private function; assumes input is old-style ItemImpl certificate reference, @@ -424,7 +456,6 @@ SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE * END_SECAPI } - /* * Private API to infer a display name for a SecCertificateRef which * may or may not be in a keychain. @@ -434,7 +465,7 @@ SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE * OSStatus SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Certificate::required(__itemImplRef)->inferLabel(false, &Required(label)); @@ -446,7 +477,7 @@ SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label) OSStatus SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle(); @@ -458,7 +489,7 @@ SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) OSStatus SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(algid) = Certificate::required(__itemImplRef)->algorithmID(); @@ -470,7 +501,7 @@ SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGO OSStatus SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(commonName) = Certificate::required(__itemImplRef)->commonName(); @@ -484,7 +515,7 @@ CFStringRef SecCertificateCopySubjectSummary(SecCertificateRef certificate) { CFStringRef summary = NULL; - OSStatus __secapiresult; + OSStatus __secapiresult; try { Certificate::required(certificate)->inferLabel(false, &summary); @@ -494,7 +525,7 @@ SecCertificateCopySubjectSummary(SecCertificateRef certificate) catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } catch (...) { __secapiresult=errSecInternalComponent; } - return summary; + return summary; } #endif @@ -521,7 +552,7 @@ SecCertificateCopyIssuerSummary(SecCertificateRef certificate) OSStatus SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component); @@ -541,7 +572,7 @@ SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonNa OSStatus SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress(); @@ -553,7 +584,7 @@ SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailA OSStatus SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(emailAddresses) = Certificate::required(__itemImplRef)->copyEmailAddresses(); @@ -569,7 +600,7 @@ SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emai OSStatus SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field)); @@ -581,7 +612,7 @@ SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *fie OSStatus SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues); @@ -593,7 +624,7 @@ SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID * OSStatus SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field)); @@ -605,7 +636,7 @@ SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID OSStatus SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue) { - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue); @@ -833,12 +864,21 @@ SecCertificateCopyPreference( *certificate = (SecCertificateRef)certItemRef; #if SECTRUST_OSX + if (certItemRef && (CFGetTypeID(certItemRef) == SecIdentityGetTypeID())) { + // SecKeychainItemCopyFromPersistentReference handed out an identity reference + *certificate = NULL; + status = SecIdentityCopyCertificate((SecIdentityRef)certItemRef, certificate); + CFRelease(certItemRef); + return status; + } +#if 0 /* SecKeychainItemCopyFromPersistentReference now does this work for us */ // convert ItemImpl-based SecCertificateRef to new-world version before returning CssmData certData = Certificate::required(*certificate)->data(); CFRef cfData(CFDataCreate(NULL, certData.Data, certData.Length)); SecCertificateRef tmpRef = *certificate; *certificate = SecCertificateCreateWithData(NULL, cfData); CFRelease(tmpRef); +#endif #endif END_SECAPI @@ -950,7 +990,7 @@ OSStatus SecCertificateSetPreference( return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage); } - // This macro converts a new-style SecCertificateRef to an old-style ItemImpl + // This macro creates an ItemImpl certificate if it does not exist BEGIN_SECCERTAPI // determine the account attribute @@ -1064,9 +1104,21 @@ CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayR { CFDictionaryRef result = NULL; OSStatus __secapiresult; + SecCertificateRef tmpcert = NULL; +#if SECTRUST_OSX + // convert input to a new-style certificate reference if necessary, + // since the implementation of CertificateValues calls SecCertificate API functions + // which now assume a unified certificate reference. + if (SecCertificateIsItemImplInstance(certificate)) { + tmpcert = SecCertificateCreateFromItemImplInstance(certificate); + } +#endif + if (certificate && !tmpcert) { + tmpcert = (SecCertificateRef) CFRetain(certificate); + } try { - CertificateValues cv(certificate); + CertificateValues cv(tmpcert); result = cv.copyFieldValues(keys,error); __secapiresult=0; } @@ -1074,6 +1126,7 @@ CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayR catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } catch (...) { __secapiresult=errSecInternalComponent; } + if (tmpcert) { CFRelease(tmpcert); } return result; } @@ -1188,6 +1241,26 @@ CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate) } #endif +#if !SECTRUST_OSX +CFDictionaryRef SecCertificateCopyAttributeDictionary(SecCertificateRef certificate) +{ + CFDictionaryRef result = NULL; + OSStatus status; + try + { + CertificateValues cv(certificate); + result = cv.copyAttributeDictionary(NULL); + status=0; + } + 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; } + + return result; +} +#endif + #if !SECTRUST_OSX bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime) { diff --git a/OSX/libsecurity_keychain/lib/SecCertificate.h b/OSX/libsecurity_keychain/lib/SecCertificate.h index 7eb01b64..aac97e5a 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificate.h +++ b/OSX/libsecurity_keychain/lib/SecCertificate.h @@ -31,6 +31,8 @@ #ifndef _SECURITY_SECCERTIFICATE_H_ #define _SECURITY_SECCERTIFICATE_H_ +#define _SECURITY_VERSION_GREATER_THAN_57610_ + #include #include #include @@ -102,7 +104,7 @@ OSStatus SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type @function SecCertificateCreateWithData @abstract Create a certificate reference given its DER representation as a CFData. @param allocator CFAllocator to allocate the certificate data. Pass NULL to use the default allocator. - @param certificate DER encoded X.509 certificate. + @param data DER encoded X.509 certificate. @result On return, a reference to the certificate. Returns NULL if the passed-in data is not a valid DER-encoded X.509 certificate. */ __nullable @@ -307,6 +309,39 @@ OSStatus SecCertificateSetPreference(SecCertificateRef certificate, CFStringRef OSStatus SecCertificateSetPreferred(SecCertificateRef __nullable certificate, CFStringRef name, CFArrayRef __nullable keyUsage) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +/*! + @typedef SecKeyUsage + @abstract Flags to indicate key usages in the KeyUsage extension of a certificate + @constant kSecKeyUsageUnspecified No KeyUsage extension in certificate. + @constant kSecKeyUsageDigitalSignature DigitalSignature bit set in KeyUsage extension. + @constant kSecKeyUsageNonRepudiation NonRepudiation bit set in KeyUsage extension. + @constant kSecKeyUsageContentCommitment ContentCommitment bit set in KeyUsage extension. + @constant kSecKeyUsageKeyEncipherment KeyEncipherment bit set in KeyUsage extension. + @constant kSecKeyUsageDataEncipherment DataEncipherment bit set in KeyUsage extension. + @constant kSecKeyUsageKeyAgreement KeyAgreement bit set in KeyUsage extension. + @constant kSecKeyUsageKeyCertSign KeyCertSign bit set in KeyUsage extension. + @constant kSecKeyUsageCRLSign CRLSign bit set in KeyUsage extension. + @constant kSecKeyUsageEncipherOnly EncipherOnly bit set in KeyUsage extension. + @constant kSecKeyUsageDecipherOnly DecipherOnly bit set in KeyUsage extension. + @constant kSecKeyUsageCritical KeyUsage extension is marked critical. + @constant kSecKeyUsageAll For masking purposes, all SecKeyUsage values. + */ +typedef CF_OPTIONS(uint32_t, SecKeyUsage) { + kSecKeyUsageUnspecified = 0, + kSecKeyUsageDigitalSignature = 1 << 0, + kSecKeyUsageNonRepudiation = 1 << 1, + kSecKeyUsageContentCommitment= 1 << 1, + kSecKeyUsageKeyEncipherment = 1 << 2, + kSecKeyUsageDataEncipherment = 1 << 3, + kSecKeyUsageKeyAgreement = 1 << 4, + kSecKeyUsageKeyCertSign = 1 << 5, + kSecKeyUsageCRLSign = 1 << 6, + kSecKeyUsageEncipherOnly = 1 << 7, + kSecKeyUsageDecipherOnly = 1 << 8, + kSecKeyUsageCritical = 1 << 31, + kSecKeyUsageAll = 0x7FFFFFFF +}; + /*! @enum kSecPropertyKey @abstract Constants used to access dictionary entries returned by SecCertificateCopyValues diff --git a/OSX/libsecurity_keychain/lib/SecCertificateP.c b/OSX/libsecurity_keychain/lib/SecCertificateP.c index fc6403c9..611d9d57 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificateP.c +++ b/OSX/libsecurity_keychain/lib/SecCertificateP.c @@ -187,21 +187,21 @@ struct __SecCertificate { }; /* Public Constants for property list keys. */ -CFStringRef kSecPropertyKeyType = CFSTR("type"); -CFStringRef kSecPropertyKeyLabel = CFSTR("label"); -CFStringRef kSecPropertyKeyLocalizedLabel = CFSTR("localized label"); -CFStringRef kSecPropertyKeyValue = CFSTR("value"); +const CFStringRef kSecPropertyKeyType = CFSTR("type"); +const CFStringRef kSecPropertyKeyLabel = CFSTR("label"); +const CFStringRef kSecPropertyKeyLocalizedLabel = CFSTR("localized label"); +const CFStringRef kSecPropertyKeyValue = CFSTR("value"); /* Public Constants for property list values. */ -CFStringRef kSecPropertyTypeWarning = CFSTR("warning"); -CFStringRef kSecPropertyTypeError = CFSTR("error"); -CFStringRef kSecPropertyTypeSuccess = CFSTR("success"); -CFStringRef kSecPropertyTypeTitle = CFSTR("title"); -CFStringRef kSecPropertyTypeSection = CFSTR("section"); -CFStringRef kSecPropertyTypeData = CFSTR("data"); -CFStringRef kSecPropertyTypeString = CFSTR("string"); -CFStringRef kSecPropertyTypeURL = CFSTR("url"); -CFStringRef kSecPropertyTypeDate = CFSTR("date"); +const CFStringRef kSecPropertyTypeWarning = CFSTR("warning"); +const CFStringRef kSecPropertyTypeError = CFSTR("error"); +const CFStringRef kSecPropertyTypeSuccess = CFSTR("success"); +const CFStringRef kSecPropertyTypeTitle = CFSTR("title"); +const CFStringRef kSecPropertyTypeSection = CFSTR("section"); +const CFStringRef kSecPropertyTypeData = CFSTR("data"); +const CFStringRef kSecPropertyTypeString = CFSTR("string"); +const CFStringRef kSecPropertyTypeURL = CFSTR("url"); +const CFStringRef kSecPropertyTypeDate = CFSTR("date"); /* Extension parsing routine. */ typedef void (*SecCertificateExtensionParser)(SecCertificateRefP certificate, @@ -597,7 +597,7 @@ static OSStatus parseX501Name(const DERItem *x501Name, void *context, static void SecCEPSubjectKeyIdentifier(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERDecodedInfo keyIdentifier; DERReturn drtn = DERDecodeItem(&extn->extnValue, &keyIdentifier); require_noerr_quiet(drtn, badDER); @@ -606,12 +606,12 @@ static void SecCEPSubjectKeyIdentifier(SecCertificateRefP certificate, return; badDER: - secdebug("cert", "Invalid SubjectKeyIdentifier Extension"); + secinfo("cert", "Invalid SubjectKeyIdentifier Extension"); } static void SecCEPKeyUsage(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); SecKeyUsage keyUsage = extn->critical ? kSecKeyUsageCritical : 0; DERDecodedInfo bitStringContent; DERReturn drtn = DERDecodeItem(&extn->extnValue, &bitStringContent); @@ -646,28 +646,28 @@ badDER: static void SecCEPPrivateKeyUsagePeriod(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } static void SecCEPSubjectAltName(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); certificate->_subjectAltName = extn; } static void SecCEPIssuerAltName(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } static void SecCEPBasicConstraints(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERBasicConstraints basicConstraints; require_noerr_quiet(DERParseSequence(&extn->extnValue, DERNumBasicConstraintsItemSpecs, DERBasicConstraintsItemSpecs, &basicConstraints, sizeof(basicConstraints)), badDER); - require_noerr_quiet(DERParseBoolean(&basicConstraints.cA, false, + require_noerr_quiet(DERParseBooleanWithDefault(&basicConstraints.cA, false, &certificate->_basicConstraints.isCA), badDER); if (basicConstraints.pathLenConstraint.length != 0) { require_noerr_quiet(DERParseInteger( @@ -680,12 +680,12 @@ static void SecCEPBasicConstraints(SecCertificateRefP certificate, return; badDER: certificate->_basicConstraints.present = false; - secdebug("cert", "Invalid BasicConstraints Extension"); + secinfo("cert", "Invalid BasicConstraints Extension"); } static void SecCEPCrlDistributionPoints(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } /* @@ -702,9 +702,11 @@ static void SecCEPCrlDistributionPoints(SecCertificateRefP certificate, policyQualifierId PolicyQualifierId, qualifier ANY DEFINED BY policyQualifierId } */ +/* maximum number of policies of 8192 seems more than adequate */ +#define MAX_CERTIFICATE_POLICIES 8192 static void SecCEPCertificatePolicies(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERTag tag; DERSequence piSeq; SecCEPolicyInformation *policies = NULL; @@ -713,7 +715,8 @@ static void SecCEPCertificatePolicies(SecCertificateRefP certificate, require_quiet(tag == ASN1_CONSTR_SEQUENCE, badDER); DERDecodedInfo piContent; DERSize policy_count = 0; - while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + while ((policy_count < MAX_CERTIFICATE_POLICIES) && + (drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { require_quiet(piContent.tag == ASN1_CONSTR_SEQUENCE, badDER); policy_count++; } @@ -722,7 +725,8 @@ static void SecCEPCertificatePolicies(SecCertificateRefP certificate, * policy_count); DERDecodeSeqInit(&extn->extnValue, &tag, &piSeq); DERSize policy_ix = 0; - while ((drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { + while ((policy_ix < (policy_count > 0 ? policy_count : 1)) && + (drtn = DERDecodeSeqNext(&piSeq, &piContent)) == DR_Success) { DERPolicyInformation pi; drtn = DERParseSequenceContent(&piContent.content, DERNumPolicyInformationItemSpecs, @@ -741,7 +745,7 @@ badDER: if (policies) free(policies); certificate->_certificatePolicies.present = false; - secdebug("cert", "Invalid CertificatePolicies Extension"); + secinfo("cert", "Invalid CertificatePolicies Extension"); } /* @@ -754,7 +758,7 @@ badDER: #if 0 static void SecCEPPolicyMappings(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERTag tag; DERSequence pmSeq; SecCEPolicyMapping *mappings = NULL; @@ -792,12 +796,12 @@ badDER: free(mappings); CFReleaseSafe(mappings); certificate->_policyMappings.present = false; - secdebug("cert", "Invalid CertificatePolicies Extension"); + secinfo("cert", "Invalid CertificatePolicies Extension"); } #else static void SecCEPPolicyMappings(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERTag tag; DERSequence pmSeq; CFMutableDictionaryRef mappings = NULL; @@ -838,7 +842,7 @@ static void SecCEPPolicyMappings(SecCertificateRefP certificate, badDER: CFReleaseSafe(mappings); certificate->_policyMappings = NULL; - secdebug("cert", "Invalid CertificatePolicies Extension"); + secinfo("cert", "Invalid CertificatePolicies Extension"); } #endif @@ -854,7 +858,7 @@ KeyIdentifier ::= OCTET STRING */ static void SecCEPAuthorityKeyIdentifier(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERAuthorityKeyIdentifier akid; DERReturn drtn; drtn = DERParseSequence(&extn->extnValue, @@ -876,12 +880,12 @@ static void SecCEPAuthorityKeyIdentifier(SecCertificateRefP certificate, return; badDER: - secdebug("cert", "Invalid AuthorityKeyIdentifier Extension"); + secinfo("cert", "Invalid AuthorityKeyIdentifier Extension"); } static void SecCEPPolicyConstraints(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERPolicyConstraints pc; DERReturn drtn; drtn = DERParseSequence(&extn->extnValue, @@ -908,12 +912,12 @@ static void SecCEPPolicyConstraints(SecCertificateRefP certificate, return; badDER: certificate->_policyConstraints.present = false; - secdebug("cert", "Invalid PolicyConstraints Extension"); + secinfo("cert", "Invalid PolicyConstraints Extension"); } static void SecCEPExtendedKeyUsage(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } /* @@ -923,14 +927,14 @@ static void SecCEPExtendedKeyUsage(SecCertificateRefP certificate, */ static void SecCEPInhibitAnyPolicy(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); require_noerr_quiet(DERParseInteger( &extn->extnValue, &certificate->_inhibitAnyPolicySkipCerts), badDER); return; badDER: certificate->_inhibitAnyPolicySkipCerts = UINT32_MAX; - secdebug("cert", "Invalid InhibitAnyPolicy Extension"); + secinfo("cert", "Invalid InhibitAnyPolicy Extension"); } /* @@ -951,7 +955,7 @@ badDER: */ static void SecCEPAuthorityInfoAccess(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); DERTag tag; DERSequence adSeq; DERReturn drtn = DERDecodeSeqInit(&extn->extnValue, &tag, &adSeq); @@ -998,7 +1002,7 @@ static void SecCEPAuthorityInfoAccess(SecCertificateRefP certificate, break; } default: - secdebug("cert", "bad general name for id-ad-ocsp AccessDescription t: 0x%02x v: %.*s", + secinfo("cert", "bad general name for id-ad-ocsp AccessDescription t: 0x%02llx v: %.*s", generalNameContent.tag, (int)generalNameContent.content.length, generalNameContent.content.data); goto badDER; break; @@ -1007,22 +1011,22 @@ static void SecCEPAuthorityInfoAccess(SecCertificateRefP certificate, require_quiet(drtn == DR_EndOfSequence, badDER); return; badDER: - secdebug("cert", "failed to parse Authority Information Access extension"); + secinfo("cert", "failed to parse Authority Information Access extension"); } static void SecCEPSubjectInfoAccess(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } static void SecCEPNetscapeCertType(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } static void SecCEPEntrustVersInfo(SecCertificateRefP certificate, const SecCertificateExtension *extn) { - secdebug("cert", "critical: %s", extn->critical ? "yes" : "no"); + secinfo("cert", "critical: %s", extn->critical ? "yes" : "no"); } /* Dictionary key callback for comparing to DERItems. */ @@ -1493,7 +1497,7 @@ static bool SecCertificateParse(SecCertificateRefP certificate) require_noerr_quiet(drtn, badCert); /* Copy stuff into certificate->extensions[ix]. */ certificate->_extensions[ix].extnID = extn.extnID; - require_noerr_quiet(drtn = DERParseBoolean(&extn.critical, false, + require_noerr_quiet(drtn = DERParseBooleanWithDefault(&extn.critical, false, &certificate->_extensions[ix].critical), badCert); certificate->_extensions[ix].extnValue = extn.extnValue; @@ -1504,10 +1508,10 @@ static bool SecCertificateParse(SecCertificateRefP certificate) /* Invoke the parser. */ parser(certificate, &certificate->_extensions[ix]); } else if (certificate->_extensions[ix].critical) { - secdebug("cert", "Found unknown critical extension"); + secinfo("cert", "Found unknown critical extension"); certificate->_foundUnknownCriticalExtension = true; } else { - secdebug("cert", "Found unknown non critical extension"); + secinfo("cert", "Found unknown non critical extension"); } } } @@ -1887,7 +1891,7 @@ CFAbsoluteTime SecAbsoluteTimeFromDateContent(DERTag tag, const uint8_t *bytes, timeZoneOffset = 0; } - secdebug("dateparse", + secinfo("dateparse", "date %.*s year: %04d-%02d-%02d %02d:%02d:%02.f %+05.f", (int)length, bytes, (int)gdate.year, gdate.month, gdate.day, gdate.hour, gdate.minute, gdate.second, @@ -2167,7 +2171,7 @@ static CFStringRef copyDERThingContentDescription(CFAllocatorRef allocator, /* @@@ Localize. */ /* "format string for undisplayed field data with a given DER tag" */ return printableOnly ? NULL : CFStringCreateWithFormat(allocator, NULL, - CFSTR("not displayed (tag = %d; length %d)"), + CFSTR("not displayed (tag = %llu; length %d)"), tag, (int)derThing->length); } } @@ -2312,7 +2316,7 @@ static void appendBoolProperty(CFMutableArrayRef properties, static void appendBooleanProperty(CFMutableArrayRef properties, CFStringRef label, const DERItem *boolean, bool defaultValue) { bool result; - DERReturn drtn = DERParseBoolean(boolean, defaultValue, &result); + DERReturn drtn = DERParseBooleanWithDefault(boolean, defaultValue, &result); if (drtn) { /* Couldn't parse boolean; dump the raw unparsed data as hex. */ appendInvalidProperty(properties, label, boolean); @@ -2413,7 +2417,7 @@ static void appendKeyUsage(CFMutableArrayRef properties, SecKeyUsage usage = (extnValue->data[3] << 8); if (extnValue->length == 5) usage += extnValue->data[4]; - secdebug("keyusage", "keyusage: %04X", usage); + secinfo("keyusage", "keyusage: %04X", usage); static const CFStringRef usageNames[] = { CFSTR("Digital Signature"), CFSTR("Non-Repudiation"), @@ -3681,13 +3685,12 @@ OSStatus SecCertificateIsSignedByP(SecCertificateRefP certificate, algId.parameters.Length = certificate->_tbsSigAlg.params.length; algId.parameters.Data = certificate->_tbsSigAlg.params.data; -#warning implementation empty #if 0 OSStatus status = SecKeyDigestAndVerify(issuerKey, &algId, certificate->_tbs.data, certificate->_tbs.length, certificate->_signature.data, certificate->_signature.length); if (status) { - secdebug("verify", "signature verify failed: %d", status); + secinfo("verify", "signature verify failed: %d", status); return errSecNotSigner; } #endif @@ -3741,11 +3744,11 @@ static OSStatus SecCertificateIsIssuedBy(SecCertificateRefP certificate, signedDataLength = DER_MD_DIGEST_INFO_LEN; crtn = mdDigestInfo(WD_MD2, &certificate->_tbs, signedData); } else { - secdebug("verify", "unsupported algorithm"); + secinfo("verify", "unsupported algorithm"); return errSecUnsupportedAlgorithm; } if (crtn) { - secdebug("verify", "*DigestInfo returned: %d", crtn); + secinfo("verify", "*DigestInfo returned: %d", crtn); /* FIXME: Do proper error code translation. */ return errSecUnsupportedAlgorithm; } @@ -3754,7 +3757,7 @@ static OSStatus SecCertificateIsIssuedBy(SecCertificateRefP certificate, signedData, signedDataLength, certificate->_signature.data, certificate->_signature.length); if (status) { - secdebug("verify", "signature verify failed: %d", status); + secinfo("verify", "signature verify failed: %d", status); return errSecNotSigner; } @@ -3781,7 +3784,7 @@ static OSStatus _SecCertificateSetParent(SecCertificateRefP certificate, /* We don't retain ourselves cause that would be bad mojo, however we do record that we are properly self signed. */ certificate->_isSelfSigned = kSecSelfSignedTrue; - secdebug("cert", "set self as parent"); + secinfo("cert", "set self as parent"); return errSecSuccess; } @@ -3845,7 +3848,7 @@ static bool SecCertificateFindParent(SecCertificateRefP certificate) { OSStatus status = SecItemCopyMatching(query, &results); CFRelease(query); if (status) { - secdebug("cert", "SecCertificateFindParent: SecItemCopyMatching: %d", + secinfo("cert", "SecCertificateFindParent: SecItemCopyMatching: %d", status); return false; } @@ -4396,7 +4399,7 @@ CFDataRef SecDERItemCopySequenceP(DERItem *content) { sequence_length); CFDataSetLength(sequence, sequence_length); uint8_t *sequence_ptr = CFDataGetMutableBytePtr(sequence); - *sequence_ptr++ = 0x30; /* ASN1_CONSTR_SEQUENCE */ + *sequence_ptr++ = ONE_BYTE_ASN1_CONSTR_SEQUENCE; require_noerr_quiet(DEREncodeLength(content->length, sequence_ptr, &seq_len_length), out); sequence_ptr += seq_len_length; @@ -4428,7 +4431,6 @@ const DERItem *SecCertificateGetPublicKeyDataP(SecCertificateRefP certificate) { SecKeyRefP SecCertificateCopyPublicKeyP(SecCertificateRefP certificate) { SecKeyRefP publicKey = NULL; -#warning implementation empty #if 0 const DERAlgorithmId *algId = SecCertificateGetPublicKeyAlgorithmP(certificate); @@ -4437,7 +4439,7 @@ SecKeyRefP SecCertificateCopyPublicKeyP(SecCertificateRefP certificate) { publicKey = SecKeyCreateRSAPublicKey(kCFAllocatorDefault, keyData->data, keyData->length, kSecKeyEncodingPkcs1); } else { - secdebug("cert", "Unsupported algorithm oid"); + secinfo("cert", "Unsupported algorithm oid"); } #endif diff --git a/OSX/libsecurity_keychain/lib/SecCertificatePriv.h b/OSX/libsecurity_keychain/lib/SecCertificatePriv.h index 1827773d..3e36b135 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificatePriv.h +++ b/OSX/libsecurity_keychain/lib/SecCertificatePriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004,2011-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2004,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -31,17 +31,21 @@ #include #include #include +#include #if defined(__cplusplus) extern "C" { #endif -typedef uint32_t SecCertificateEscrowRootType; -enum { +typedef CF_ENUM(uint32_t, SecCertificateEscrowRootType) { kSecCertificateBaselineEscrowRoot = 0, kSecCertificateProductionEscrowRoot = 1, kSecCertificateBaselinePCSEscrowRoot = 2, kSecCertificateProductionPCSEscrowRoot = 3, + kSecCertificateBaselineEscrowBackupRoot = 4, // v100 and v101 + kSecCertificateProductionEscrowBackupRoot = 5, + kSecCertificateBaselineEscrowEnrollmentRoot = 6, // v101 only + kSecCertificateProductionEscrowEnrollmentRoot = 7, }; extern const CFStringRef kSecCertificateProductionEscrowKey; @@ -57,6 +61,9 @@ SecCertificateRef SecCertificateCreateItemImplInstance(SecCertificateRef certifi /* Inverse of above; convert legacy Certificate instance to new ref. */ SecCertificateRef SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate); +/* Convenience function to determine type of certificate instance. */ +Boolean SecCertificateIsItemImplInstance(SecCertificateRef certificate); + /* Given a legacy C++ ItemImpl-based Certificate instance obtained with SecCertificateCreateItemImplInstance, return its clHandle pointer. @@ -69,6 +76,12 @@ OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, const UInt8 *bytes, CFIndex length); +/* Returns a certificate from a pem blob. + Return NULL if the passed-in data is not a valid DER-encoded X.509 + certificate. */ +SecCertificateRef SecCertificateCreateWithPEM(CFAllocatorRef allocator, + CFDataRef pem_certificate); + /* Return the length of the DER representation of this certificate. */ CFIndex SecCertificateGetLength(SecCertificateRef certificate); @@ -78,12 +91,18 @@ const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate); /* Return the SHA-1 hash of this certificate. */ CFDataRef SecCertificateGetSHA1Digest(SecCertificateRef certificate); -/* Return the SHA2-256 hash of this certificate. */ +/* Return the SHA-256 hash of this certificate. */ CFDataRef SecCertificateCopySHA256Digest(SecCertificateRef certificate); /* Return the SHA-1 hash of the public key in this certificate. */ CFDataRef SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate); +/* Return the SHA-1 hash of the SubjectPublicKeyInfo sequence in this certificate. */ +CFDataRef SecCertificateCopySubjectPublicKeyInfoSHA1Digest(SecCertificateRef certificate); + +/* Return the SHA-256 hash of the SubjectPublicKeyInfo sequence in this certificate. */ +CFDataRef SecCertificateCopySubjectPublicKeyInfoSHA256Digest(SecCertificateRef certificate); + /* Deprecated; use SecCertificateCopyCommonName() instead. */ OSStatus SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName); @@ -95,9 +114,22 @@ OSStatus SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRe certificate if any. */ CFArrayRef SecCertificateCopyDNSNames(SecCertificateRef certificate); +/* Return an array of CFStringRefs representing the NTPrincipalNames in the + certificate if any. */ +CFArrayRef SecCertificateCopyNTPrincipalNames(SecCertificateRef certificate); + +/* Create a unified SecCertificateRef from a legacy keychain item and its data. */ SecCertificateRef SecCertificateCreateWithKeychainItem(CFAllocatorRef allocator, CFDataRef der_certificate, CFTypeRef keychainItem); +/* Set a legacy item instance for a unified SecCertificateRef. */ +OSStatus SecCertificateSetKeychainItem(SecCertificateRef certificate, + CFTypeRef keychain_item); + +/* Return a keychain item reference, given a unified SecCertificateRef. + Note: for this function to succeed, the provided certificate must have been + created by SecCertificateCreateWithKeychainItem, otherwise NULL is returned. + */ CFTypeRef SecCertificateCopyKeychainItem(SecCertificateRef certificate); /*! @@ -110,6 +142,13 @@ CFTypeRef SecCertificateCopyKeychainItem(SecCertificateRef certificate); */ CFStringRef SecCertificateCopyIssuerSummary(SecCertificateRef certificate); +/* Return a string formatted according to RFC 2253 representing the complete + subject of certificate. */ +CFStringRef SecCertificateCopySubjectString(SecCertificateRef certificate); + +CFMutableArrayRef SecCertificateCopySummaryProperties( + SecCertificateRef certificate, CFAbsoluteTime verifyTime); + /* * Private API to infer a display name for a SecCertificateRef which * may or may not be in a keychain. @@ -191,6 +230,12 @@ CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate); /* Return the DER encoded subject sequence for the certificate's subject. */ CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate); +#if (SECTRUST_OSX && TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) +CFDataRef SecCertificateGetNormalizedIssuerContent(SecCertificateRef certificate); +CFDataRef SecCertificateGetNormalizedSubjectContent(SecCertificateRef certificate); +CFDataRef SecCertificateCopyNormalizedIssuerSequence(SecCertificateRef certificate); +CFDataRef SecCertificateCopyNormalizedSubjectSequence(SecCertificateRef certificate); +#endif /* Convenience functions for searching. */ @@ -265,6 +310,28 @@ CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate) OSStatus SecCertificateIsSelfSigned(SecCertificateRef certRef, Boolean *isSelfSigned) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_9_0); +/*! + @function SecCertificateIsSelfSignedCA + @abstract Determine if the given certificate is self-signed and has a basic + constraints extension indicating it is a certificate authority. + @param certificate A certificate reference. + @result Returns true if the certificate is self-signed and has a basic + constraints extension indicating it is a certificate authority, otherwise false. +*/ +bool SecCertificateIsSelfSignedCA(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_9_0); + +/*! + @function SecCertificateIsCA + @abstract Determine if the given certificate has a basic + constraints extension indicating it is a certificate authority. + @param certificate A certificate reference. + @result Returns true if the certificate has a basic constraints + extension indicating it is a certificate authority, otherwise false. +*/ +bool SecCertificateIsCA(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_9_0); + /*! @function SecCertificateCopyEscrowRoots @abstract Retrieve the array of valid escrow certificates for a given root type. @@ -274,6 +341,9 @@ OSStatus SecCertificateIsSelfSigned(SecCertificateRef certRef, Boolean *isSelfSi CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +/* Return an attribute dictionary used to store this item in a keychain. */ +CFDictionaryRef SecCertificateCopyAttributeDictionary(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); /* * Enumerated constants for signature hash algorithms. @@ -303,6 +373,27 @@ enum { SecSignatureHashAlgorithm SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate) __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); +/*! + @function SecCertificateCopyProperties + @abstract Return a property array for this trust certificate. + @param certificate A reference to the certificate to evaluate. + @result A property array. It is the caller's responsability to CFRelease + the returned array when it is no longer needed. + See SecTrustCopySummaryPropertiesAtIndex on how to intepret this array. + Unlike that function call this function returns a detailed description + of the certificate in question. +*/ +CFArrayRef SecCertificateCopyProperties(SecCertificateRef certificate); + +CFDataRef SecCertificateCopySubjectPublicKeyInfoSHA256Digest(SecCertificateRef certificate); + +/* Returns an array of CFDataRefs for all embedded SCTs */ +CFArrayRef SecCertificateCopySignedCertificateTimestamps(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_9_0); + +/* Return the precert TBSCertificate DER data - used for Certificate Transparency */ +CFDataRef SecCertificateCopyPrecertTBS(SecCertificateRef certificate) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_9_0); #if defined(__cplusplus) } diff --git a/OSX/libsecurity_keychain/lib/SecCertificatePrivP.h b/OSX/libsecurity_keychain/lib/SecCertificatePrivP.h index 1d251601..1ed8e90f 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificatePrivP.h +++ b/OSX/libsecurity_keychain/lib/SecCertificatePrivP.h @@ -35,7 +35,7 @@ #ifndef _SECURITY_SECCERTIFICATEPRIVP_H_ #define _SECURITY_SECCERTIFICATEPRIVP_H_ -//#include +#include #include "SecCertificateP.h" #include #include @@ -47,23 +47,6 @@ extern "C" { #endif -typedef uint32_t SecKeyUsage; -enum { - kSecKeyUsageUnspecified = 0, - kSecKeyUsageDigitalSignature = 1 << 0, - kSecKeyUsageNonRepudiation = 1 << 1, - kSecKeyUsageContentCommitment= 1 << 1, - kSecKeyUsageKeyEncipherment = 1 << 2, - kSecKeyUsageDataEncipherment = 1 << 3, - kSecKeyUsageKeyAgreement = 1 << 4, - kSecKeyUsageKeyCertSign = 1 << 5, - kSecKeyUsageCRLSign = 1 << 6, - kSecKeyUsageEncipherOnly = 1 << 7, - kSecKeyUsageDecipherOnly = 1 << 8, - kSecKeyUsageCritical = 1 << 31, - kSecKeyUsageAll = 0x7FFFFFFF -}; - /* Return a certificate for the DER representation of this certificate. Return NULL if the passed-in data is not a valid DER-encoded X.509 certificate. */ diff --git a/OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp b/OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp index 8dfb57f8..c7d2d855 100644 --- a/OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp +++ b/OSX/libsecurity_keychain/lib/SecFDERecoveryAsymmetricCrypto.cpp @@ -65,7 +65,7 @@ CFDataRef SecFDERecoveryUnwrapCRSKWithPrivKey(SecKeychainRef keychain, const FVP catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } catch (...) { __secapiresult=errSecInternalComponent; } - secdebug("FDERecovery", "SecFDERecoveryUnwrapCRSKWithPrivKey: %d", (int)__secapiresult); + secinfo("FDERecovery", "SecFDERecoveryUnwrapCRSKWithPrivKey: %d", (int)__secapiresult); return result; } @@ -115,7 +115,7 @@ static void encodePrivateKeyHeader(const CssmData &inBlob, CFDataRef certificate outHeader.encryptedBlobSize = (uint32_t)encrypt.encrypt(inBlob, clearBuf, remData.get()); if (outHeader.encryptedBlobSize > sizeof(outHeader.encryptedBlob)) - secdebug("FDERecovery", "encodePrivateKeyHeader: encrypted blob too big: %d", outHeader.encryptedBlobSize); + secinfo("FDERecovery", "encodePrivateKeyHeader: encrypted blob too big: %d", outHeader.encryptedBlobSize); } CFDataRef decodePrivateKeyHeader(SecKeychainRef keychain, const FVPrivateKeyHeader &inHeader) @@ -140,8 +140,9 @@ CFDataRef decodePrivateKeyHeader(SecKeychainRef keychain, const FVPrivateKeyHead CFRef searchRef(_searchRef); SecKeychainItemRef _item; - if (SecKeychainSearchCopyNext(searchRef, &_item)) - return false; + if (SecKeychainSearchCopyNext(searchRef, &_item) != 0) { + return NULL; // XXX possibly should throw here? + } CFRef keyItem(reinterpret_cast(_item)); throwIfError(SecKeyGetCSPHandle(keyItem, &cspHandle)); @@ -161,7 +162,7 @@ CFDataRef decodePrivateKeyHeader(SecKeychainRef keychain, const FVPrivateKeyHead CssmAutoData remData(allocator); size_t bytesDecrypted; CSSM_RETURN crx = CSSM_DecryptData(cc, &cipherBuf, 1, &clearBuf.get(), 1, &bytesDecrypted, &remData.get()); - secdebug("FDERecovery", "decodePrivateKeyHeader: CSSM_DecryptData result: %d", crx); + secinfo("FDERecovery", "decodePrivateKeyHeader: CSSM_DecryptData result: %d", crx); throwIfError(crx); // throwIfError(CSSM_DecryptData(cc, &cipherBuf, 1, &clearBuf.get(), 1, &bytesDecrypted, &remData.get())); clearBuf.length(bytesDecrypted); diff --git a/OSX/libsecurity_keychain/lib/SecFrameworkP.c b/OSX/libsecurity_keychain/lib/SecFrameworkP.c index 64bdd381..febe7c1b 100644 --- a/OSX/libsecurity_keychain/lib/SecFrameworkP.c +++ b/OSX/libsecurity_keychain/lib/SecFrameworkP.c @@ -84,7 +84,7 @@ CFURLRef SecFrameworkCopyResourceURL(CFStringRef resourceName, url = CFBundleCopyResourceURL(kSecFrameworkBundle, resourceName, resourceType, subDirName); if (!url) { - secdebug("SecFramework", "resource: %@.%@ in %@ not found", resourceName, + secinfo("SecFramework", "resource: %@.%@ in %@ not found", resourceName, resourceType, subDirName); } } @@ -102,7 +102,7 @@ CFDataRef SecFrameworkCopyResourceContents(CFStringRef resourceName, SInt32 error; if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, url, &data, NULL, NULL, &error)) { - secdebug("SecFramework", "read: %d", (int)error); + secinfo("SecFramework", "read: %d", (int)error); } CFRelease(url); } @@ -152,108 +152,3 @@ CFDataRef SecDigestCreate(CFAllocatorRef allocator, return digest; } #endif - -#if 0 - -/* Default random ref for /dev/random. */ -const SecRandomRef kSecRandomDefault = NULL; - -/* File descriptor for "/dev/random". */ -static int kSecRandomFD; -static pthread_once_t kSecDevRandomOpen = PTHREAD_ONCE_INIT; - -static void SecDevRandomOpen(void) { - kSecRandomFD = open("/dev/random", O_RDONLY); -} - -int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) { - if (rnd != kSecRandomDefault) - return errSecParam; - pthread_once(&kSecDevRandomOpen, SecDevRandomOpen); - if (kSecRandomFD < 0) - return -1; - while (count) { - ssize_t bytes_read = read(kSecRandomFD, bytes, count); - if (bytes_read == -1) { - if (errno == EINTR) - continue; - return -1; - } - if (bytes_read == 0) { - return -1; - } - count -= bytes_read; - } - - return 0; -} - -#include -#include - -/* FIPS rng declarations. */ -typedef struct __SecRandom *SecRandomRef; -SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength, - const UInt8 *seed); -void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes, UInt8 *outBytes); - -/* FIPS Rng implementation. */ -struct __SecRandom { - CC_SHA1_CTX sha1; - CFIndex bytesLeft; - UInt8 block[64]; -}; - -SecRandomRef SecRandomCreate(CFIndex randomAlg, CFIndex seedLength, - const UInt8 *seed) { - SecRandomRef result = (SecRandomRef)malloc(sizeof(struct __SecRandom)); - CC_SHA1_Init(&result->sha1); - memset(result->block + 20, 0, 44); - result->bytesLeft = 0; - - if (seedLength) { - /* Digest the seed and put it into output. */ - CC_SHA1(seed, seedLength, result->block); - } else { - /* Seed 20 bytes from "/dev/srandom". */ - int fd = open("/dev/srandom", O_RDONLY); - if (fd < 0) - goto errOut; - - if (read(fd, result->block, 20) != 20) - goto errOut; - - close(fd); - } - - CC_SHA1_Update(&result->sha1, result->block, 64); - - return result; - -errOut: - free(result); - return NULL; -} - -void SecRandomCopyBytes(SecRandomRef randomref, CFIndex numBytes, - UInt8 *outBytes) { - while (numBytes > 0) { - if (!randomref->bytesLeft) { - CC_SHA1_Update(&randomref->sha1, randomref->block, 64); - OSWriteBigInt32(randomref->block, 0, randomref->sha1.h0); - OSWriteBigInt32(randomref->block, 4, randomref->sha1.h1); - OSWriteBigInt32(randomref->block, 8, randomref->sha1.h2); - OSWriteBigInt32(randomref->block, 12, randomref->sha1.h3); - OSWriteBigInt32(randomref->block, 16, randomref->sha1.h4); - randomref->bytesLeft = 20; - } - CFIndex outLength = (numBytes > randomref->bytesLeft ? - randomref->bytesLeft : numBytes); - memcpy(outBytes, randomref->block + 20 - randomref->bytesLeft, - outLength); - randomref->bytesLeft -= outLength; - outBytes += outLength; - numBytes -= outLength; - } -} -#endif diff --git a/OSX/libsecurity_keychain/lib/SecIdentity.cpp b/OSX/libsecurity_keychain/lib/SecIdentity.cpp index 7939d6b6..adfe8b74 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentity.cpp +++ b/OSX/libsecurity_keychain/lib/SecIdentity.cpp @@ -121,29 +121,57 @@ SecIdentityCopyCertificate( { BEGIN_SECAPI - SecPointer certificatePtr(Identity::required(identityRef)->certificate()); - Required(certificateRef) = certificatePtr->handle(); - -#if SECTRUST_OSX - /* convert outgoing item to a unified SecCertificateRef */ - CssmData certData = certificatePtr->data(); - CFDataRef data = NULL; - if (certData.Data && certData.Length) { - data = CFDataCreate(NULL, certData.Data, certData.Length); + if (!identityRef || !certificateRef) { + return errSecParam; } - if (!data) { - *certificateRef = NULL; - syslog(LOG_ERR, "ERROR: SecIdentityCopyCertificate failed to retrieve certificate data (length=%ld, data=0x%lX)", - (long)certData.Length, (uintptr_t)certData.Data); - return errSecInternal; + CFTypeID itemType = CFGetTypeID(identityRef); + if (itemType == SecIdentityGetTypeID()) { + SecPointer certificatePtr(Identity::required(identityRef)->certificate()); + Required(certificateRef) = certificatePtr->handle(); +#if SECTRUST_OSX + /* convert outgoing certificate item to a unified SecCertificateRef */ + CssmData certData = certificatePtr->data(); + CFDataRef data = NULL; + if (certData.Data && certData.Length) { + data = CFDataCreate(NULL, certData.Data, certData.Length); + } + if (!data) { + *certificateRef = NULL; + syslog(LOG_ERR, "ERROR: SecIdentityCopyCertificate failed to retrieve certificate data (length=%ld, data=0x%lX)", + (long)certData.Length, (uintptr_t)certData.Data); + return errSecInternal; + } + SecCertificateRef tmpRef = *certificateRef; + *certificateRef = SecCertificateCreateWithKeychainItem(NULL, data, tmpRef); + if (data) { + CFRelease(data); + } + if (tmpRef) { + CFRelease(tmpRef); + } +#endif } - SecCertificateRef tmpRef = *certificateRef; - *certificateRef = SecCertificateCreateWithKeychainItem(NULL, data, tmpRef); - if (data) - CFRelease(data); - if (tmpRef) - CFRelease(tmpRef); + else if (itemType == SecCertificateGetTypeID()) { + // rdar://24483382 + // reconstituting a persistent identity reference could return the certificate + SecCertificateRef certificate = (SecCertificateRef)identityRef; +#if !SECTRUST_OSX + SecPointer certificatePtr(Certificate::required(certificate)); + Required(certificateRef) = certificatePtr->handle(); +#else + /* convert outgoing certificate item to a unified SecCertificateRef, if needed */ + if (SecCertificateIsItemImplInstance(certificate)) { + *certificateRef = SecCertificateCreateFromItemImplInstance(certificate); + } + else { + *certificateRef = (SecCertificateRef) CFRetain(certificate); + } #endif + return errSecSuccess; + } + else { + return errSecParam; + } END_SECAPI } @@ -156,8 +184,7 @@ SecIdentityCopyPrivateKey( { BEGIN_SECAPI - SecPointer keyItemPtr(Identity::required(identityRef)->privateKey()); - Required(privateKeyRef) = keyItemPtr->handle(); + Required(privateKeyRef) = (SecKeyRef)CFRetain(Identity::required(identityRef)->privateKeyRef()); END_SECAPI } @@ -188,11 +215,20 @@ SecIdentityCreate( { SecIdentityRef identityRef = NULL; OSStatus __secapiresult; - SecCertificateRef __itemImplRef=SecCertificateCreateItemImplInstance(certificate); + SecCertificateRef __itemImplRef = NULL; + if (SecCertificateIsItemImplInstance(certificate)) { + __itemImplRef=(SecCertificateRef)CFRetain(certificate); + } + if (!__itemImplRef && certificate) { + __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); + } + if (!__itemImplRef && certificate) { + __itemImplRef=SecCertificateCreateItemImplInstance(certificate); + (void)SecCertificateSetKeychainItem(certificate,__itemImplRef); + } try { SecPointer certificatePtr(Certificate::required(__itemImplRef)); - SecPointer keyItemPtr(KeyItem::required(privateKey)); - SecPointer identityPtr(new Identity(keyItemPtr, certificatePtr)); + SecPointer identityPtr(new Identity(privateKey, certificatePtr)); identityRef = identityPtr->handle(); __secapiresult=errSecSuccess; @@ -201,6 +237,7 @@ SecIdentityCreate( catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } catch (...) { __secapiresult=errSecInternalComponent; } + if (__itemImplRef) { CFRelease(__itemImplRef); } return identityRef; } diff --git a/OSX/libsecurity_keychain/lib/SecIdentity.h b/OSX/libsecurity_keychain/lib/SecIdentity.h index b74d2a50..50278a03 100644 --- a/OSX/libsecurity_keychain/lib/SecIdentity.h +++ b/OSX/libsecurity_keychain/lib/SecIdentity.h @@ -107,8 +107,7 @@ OSStatus SecIdentityCopyPreference(CFStringRef name, CSSM_KEYUSE keyUsage, CFArr @param name A string containing a URI, RFC822 email address, DNS hostname, or other name which uniquely identifies the service requiring an identity. @param keyUsage A CFArrayRef value, containing items defined in SecItem.h Pass NULL to ignore this parameter. (kSecAttrCanEncrypt, kSecAttrCanDecrypt, kSecAttrCanDerive, kSecAttrCanSign, kSecAttrCanVerify, kSecAttrCanWrap, kSecAttrCanUnwrap) @param validIssuers (optional) An array of CFDataRef instances whose contents are the subject names of allowable issuers, as returned by a call to SSLCopyDistinguishedNames (SecureTransport.h). Pass NULL if any issuer is allowed. - @param identity On return, a reference to the preferred identity, or NULL if none was found. You are responsible for releasing this reference by calling the CFRelease function. - @result An identity or NULL. if the preferred identity has not been set. Your code should then typically perform a search for possible identities using the SecItem APIs. + @result An identity or NULL, if the preferred identity has not been set. Your code should then typically perform a search for possible identities using the SecItem APIs. @discussion If a preferred identity has not been set for the supplied name, the returned identity reference will be NULL. Your code should then perform a search for possible identities, using the SecItemCopyMatching API. */ __nullable diff --git a/OSX/libsecurity_keychain/lib/SecImport.cpp b/OSX/libsecurity_keychain/lib/SecImport.cpp index 3a135656..76fedc32 100644 --- a/OSX/libsecurity_keychain/lib/SecImport.cpp +++ b/OSX/libsecurity_keychain/lib/SecImport.cpp @@ -31,7 +31,7 @@ #include #include -#define SecImpInferDbg(args...) secdebug("SecImpInfer", ## args) +#define SecImpInferDbg(args...) secinfo("SecImpInfer", ## args) using namespace Security; using namespace KeychainCore; diff --git a/OSX/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp b/OSX/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp index d066c49c..ac0e4b52 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportOpenSSH.cpp @@ -35,7 +35,7 @@ #include #include -#define SecSSHDbg(args...) secdebug("openssh", ## args) +#define SecSSHDbg(args...) secinfo("openssh", ## args) #define SSHv2_PUB_KEY_NAME "OpenSSHv2 Public Key" #define SSHv1_PUB_KEY_NAME "OpenSSHv1 Public Key" diff --git a/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp b/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp index 13547958..a272a228 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportPkcs8.cpp @@ -57,7 +57,7 @@ #include #include -#define SecPkcs8Dbg(args...) secdebug("SecPkcs8", ## args) +#define SecPkcs8Dbg(args...) secinfo("SecPkcs8", ## args) #pragma mark --- PKCS5 v1.5 Key Derivation --- diff --git a/OSX/libsecurity_keychain/lib/SecImportExportUtils.h b/OSX/libsecurity_keychain/lib/SecImportExportUtils.h index 7b02ac0e..510fa69e 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportUtils.h +++ b/OSX/libsecurity_keychain/lib/SecImportExportUtils.h @@ -69,8 +69,8 @@ extern const char *impExpExtItemTypeStr(SecExternalItemType itemType); #endif /* NDEBUG */ -#define SecImpExpDbg(args...) secdebug("SecImpExp", ## args) -#define SecImpInferDbg(args...) secdebug("SecImpInfer", ## args) +#define SecImpExpDbg(args...) secinfo("SecImpExp", ## args) +#define SecImpInferDbg(args...) secinfo("SecImpInfer", ## args) /* * Parse file extension and attempt to map it to format and type. Returns true diff --git a/OSX/libsecurity_keychain/lib/SecInternal.h b/OSX/libsecurity_keychain/lib/SecInternal.h index 4bae0414..f10a5f15 100644 --- a/OSX/libsecurity_keychain/lib/SecInternal.h +++ b/OSX/libsecurity_keychain/lib/SecInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2007-2015 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -35,6 +35,7 @@ extern "C" { #endif +#define CFRetainSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRetain(_cf); } #define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } #define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ if (_cf) { (CF) = NULL; CFRelease(_cf); } } diff --git a/OSX/libsecurity_keychain/lib/SecItem.cpp b/OSX/libsecurity_keychain/lib/SecItem.cpp index 173eb892..93635785 100644 --- a/OSX/libsecurity_keychain/lib/SecItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecItem.cpp @@ -37,6 +37,9 @@ #include "SecCertificatePriv.h" #include "SecCertificatePrivP.h" #include "TrustAdditions.h" +#include "TrustSettingsSchema.h" +#include +#include "utilities/array_size.h" #include #include @@ -59,9 +62,9 @@ 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); -CFTypeRef SecItemCreateFromAttributeDictionary(CFDictionaryRef refAttributes); -CFTypeRef SecItemCopyMergedResults(CFDictionaryRef query, CFTypeRef result_osx, CFTypeRef result_ios); +CFTypeRef SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes); OSStatus SecItemValidateAppleApplicationGroupAccess(CFStringRef group); CFDictionaryRef SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, bool iOSOut, bool pruneMatch, bool pruneSync, bool pruneReturn, bool pruneData, bool pruneAccess); @@ -2942,12 +2945,11 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error) { OSStatus status; CFTypeRef value = NULL; - SecItemParams *itemParams = (SecItemParams *) malloc(sizeof(SecItemParams)); + SecItemParams *itemParams = (SecItemParams *)calloc(1, sizeof(struct SecItemParams)); require_action(itemParams != NULL, error_exit, status = errSecAllocate); require_action(dict && (CFDictionaryGetTypeID() == CFGetTypeID(dict)), error_exit, status = errSecParam); - memset(itemParams, 0, sizeof(SecItemParams)); itemParams->query = (CFDictionaryRef) CFRetain(dict); // validate input search parameters @@ -2977,6 +2979,25 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error) // validate the payload (password, key or certificate data), used for SecItemAdd but not for finding items require_noerr(status = _ValidateDictionaryEntry(dict, kSecValueData, (const void **)&itemParams->itemData, CFDataGetTypeID(), CFStringGetTypeID()), error_exit); + if (itemParams->itemData && CFGetTypeID(itemParams->itemData) == CFStringGetTypeID()) { + /* If we got a string, convert it into a data object */ + CFStringRef string = (CFStringRef)itemParams->itemData; + CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), kCFStringEncodingUTF8) + 1; + CFMutableDataRef data = CFDataCreateMutable(NULL, maxLength); + require_action(data, error_exit, status = errSecAllocate); + + CFDataSetLength(data, maxLength); + + if (!CFStringGetCString(string, (char *)CFDataGetMutableBytePtr(data), maxLength, kCFStringEncodingUTF8)) { + CFRelease(data); + status = errSecAllocate; + goto error_exit; + } + + CFDataSetLength(data, strlen((const char *)CFDataGetBytePtr(data))); /* dont include NUL in string */ + itemParams->itemData = data; + CFRelease(string); + } // validate item references require_noerr(status = _ValidateDictionaryEntry(dict, kSecValueRef, (const void **)&itemParams->itemRef, SecKeychainItemGetTypeID(), SecIdentityGetTypeID()), error_exit); @@ -3236,7 +3257,9 @@ _FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert) SecTrustRef trust = NULL; SecTrustResultType trustResult; +#if !SECTRUST_OSX CSSM_TP_APPLE_EVIDENCE_INFO *evidence = NULL; +#endif Boolean needChain = false; OSStatus status; if (!policy || !cert) return errSecParam; @@ -3255,12 +3278,14 @@ _FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert) props = SecPolicyCopyProperties(policy); if (props) { CFTypeRef oid = (CFTypeRef) CFDictionaryGetValue(props, kSecPolicyOid); - if (oid && CFEqual(oid, kSecPolicyAppleX509Basic)) { + if (oid && (CFEqual(oid, kSecPolicyAppleX509Basic) || + CFEqual(oid, kSecPolicyAppleRevocation))) { needChain = true; } } if (!needChain) { +#if !SECTRUST_OSX /* To make the evaluation as lightweight as possible, specify an empty array * of keychains which will be searched for certificates. */ @@ -3274,8 +3299,14 @@ _FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert) anchors = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); status = SecTrustSetAnchorCertificates(trust, anchors); if(status) goto cleanup; +#else + status = SecTrustEvaluateLeafOnly(trust, &trustResult); + } else { + status = SecTrustEvaluate(trust, &trustResult); +#endif } +#if !SECTRUST_OSX /* All parameters are locked and loaded, ready to evaluate! */ status = SecTrustEvaluate(trust, &trustResult); if(status) goto cleanup; @@ -3287,6 +3318,7 @@ _FilterWithPolicy(SecPolicyRef policy, CFDateRef date, SecCertificateRef cert) */ status = SecTrustGetResult(trust, &trustResult, &chain, &evidence); if(status) goto cleanup; +#endif if (!(trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified || @@ -3385,7 +3417,7 @@ static SecKeychainItemRef CopyResolvedKeychainItem(CFTypeRef item) { SecKeychainItemRef kcItem = NULL; - OSStatus status; + OSStatus status = errSecSuccess; if (item) { if (CFGetTypeID(item) == CFDataGetTypeID()) { // persistent reference, resolve first @@ -3399,9 +3431,13 @@ CopyResolvedKeychainItem(CFTypeRef item) // ask for the item's class: // will return an error if the item has been deleted SecItemClass itemClass; - SecKeychainItemRef certRef = NULL; - if (CFGetTypeID(kcItem) == SecIdentityGetTypeID()) { - status = SecIdentityCopyCertificate((SecIdentityRef)kcItem, (SecCertificateRef *)&certRef); + SecCertificateRef certRef = NULL; + CFTypeID itemTypeID = CFGetTypeID(kcItem); + if (itemTypeID == SecIdentityGetTypeID()) { + status = SecIdentityCopyCertificate((SecIdentityRef)kcItem, &certRef); + } + else if (itemTypeID == SecCertificateGetTypeID()) { + certRef = (SecCertificateRef) CFRetain(kcItem); } if (certRef) { // can't call SecKeychainItemCopyAttributesAndData on a SecCertificateRef @@ -3898,22 +3934,6 @@ static SInt32 readNumber(CFTypeRef obj) { return NULL; } -// -// Function to ensure the syncable keychain is unlocked. -// Currently, this means unlocking the login keychain, -// which will also unlock the keybag as a side effect. -// -static OSStatus SecItemUnlockSynchronizableKeychain() -{ - SecKeychainRef keychain = NULL; - OSStatus status = SecKeychainCopyLogin(&keychain); - if (!status) { - status = SecKeychainUnlock(keychain, 0, NULL, false); - } - CFReleaseSafe(keychain); - return status; -} - // // Function to check whether the kSecAttrSynchronizable flag is set in the query. // @@ -3926,28 +3946,103 @@ static Boolean SecItemSynchronizable(CFDictionaryRef query) } // -// Function to check whether the kSecAttrNoLegacy flag is set in the query. +// Function to check whether a synchronizable persistent reference was provided. // -static Boolean SecItemNoLegacy(CFDictionaryRef query) +static Boolean SecItemIsIOSPersistentReference(CFTypeRef value) { - CFTypeRef value = CFDictionaryGetValue(query, kSecAttrNoLegacy); - Boolean result = (value && readNumber(value)); - - return result; + if (value) { + /* Synchronizable persistent ref consists of the sqlite rowid and 4-byte class value */ + const CFIndex kSynchronizablePersistentRefLength = sizeof(int64_t) + 4; + return (CFGetTypeID(value) == CFDataGetTypeID() && + CFDataGetLength((CFDataRef)value) == kSynchronizablePersistentRefLength); + } + return false; } +extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); + // -// Function to check whether the kSecAttrSynchronizable flag is set in the query, -// and has the special value of kSecAttrSynchronizableAny. +// Function to find out which keychains are targetted by the query. // -static Boolean SecItemSynchronizableAny(CFDictionaryRef query) +static OSStatus SecItemCategorizeQuery(CFDictionaryRef query, bool &can_target_ios, bool &can_target_osx) { - CFTypeRef value = CFDictionaryGetValue(query, kSecAttrSynchronizable); - if (value) { - return (CFGetTypeID(value) == CFStringGetTypeID() && - CFEqual(value, kSecAttrSynchronizableAny)); + // By default, target both keychain. + can_target_osx = can_target_ios = true; + + // Check no-legacy flag. + CFTypeRef value = CFDictionaryGetValue(query, kSecAttrNoLegacy); + if (value != NULL) { + can_target_ios = readNumber(value) != 0; + can_target_osx = !can_target_ios; + return errSecSuccess; } - return false; + + // Check whether the query contains kSecValueRef and modify can_ flags according to the kind and type of the value. + value = CFDictionaryGetValue(query, kSecValueRef); + if (value != NULL) { + CFTypeID typeID = CFGetTypeID(value); + if (typeID == SecKeyGetTypeID()) { + can_target_osx = SecKeyIsCDSAKey((SecKeyRef)value); + can_target_ios = !can_target_osx; + } else if (typeID == SecCertificateGetTypeID()) { + // All types of certificates can target OSX keychains, but OSX certificates won't work on iOS + can_target_ios &= !SecCertificateIsItemImplInstance((SecCertificateRef)value); + } else if (typeID == SecKeychainItemGetTypeID()) { + // SecKeychainItemRef can target iOS keychain only when it has attached iOS-style persistent reference. + if (_SecItemGetPersistentReference(value) == NULL) { + can_target_ios = false; + } + } + } + + // Check presence of kSecAttrTokenID and kSecAttrAccessControl; they are not defined for CDSA keychain. + if (CFDictionaryContainsKey(query, kSecAttrTokenID) || CFDictionaryContainsKey(query, kSecAttrAccessControl)) { + can_target_osx = false; + } + + // Check for special token access groups. If present, redirect query to iOS keychain. + value = CFDictionaryGetValue(query, kSecAttrAccessGroup); + if (value != NULL && CFEqual(value, kSecAttrAccessGroupToken)) { + can_target_osx = false; + } + + // Synchronizable items should go to iOS keychain only. + if (SecItemSynchronizable(query)) { + can_target_osx = false; + } + + value = CFDictionaryGetValue(query, kSecValuePersistentRef); + if (value != NULL) { + if (SecItemIsIOSPersistentReference(value)) { + can_target_osx = false; + } else { + // Non-iOS-style persistent references should not be fed to iOS keychain queries. + can_target_ios = false; + } + } + + // Presence of following atributes means that query is OSX-only. + static const CFStringRef *osx_only_items[] = { + &kSecMatchItemList, + &kSecMatchSearchList, + &kSecMatchSubjectStartsWith, + &kSecMatchSubjectEndsWith, + &kSecMatchSubjectWholeString, + &kSecMatchDiacriticInsensitive, + &kSecMatchWidthInsensitive, + &kSecUseItemList, + &kSecUseKeychain, + &kSecAttrAccess, + &kSecAttrPRF, + &kSecAttrSalt, + &kSecAttrRounds, + }; + + for (CFIndex i = 0; i < array_size(osx_only_items); i++) { + can_target_ios = can_target_ios && !CFDictionaryContainsKey(query, *osx_only_items[i]); + } + + return (can_target_ios || can_target_osx) ? errSecSuccess : errSecParam; } // @@ -3965,42 +4060,6 @@ static Boolean SecItemHasSynchronizableUpdate(Boolean synchronizable, CFDictiona return (old_sync != new_sync); } -// -// Returns true if keychain syncing is globally enabled. -// -static Boolean SecItemSyncEnabled() -{ - static dispatch_once_t onceToken; - static Boolean syncEnabled = true; - - //sudo defaults write /Library/Preferences/com.apple.security SecItemSynchronizable -bool YES - dispatch_once(&onceToken, ^{ - CFTypeRef sync = (CFNumberRef)CFPreferencesCopyValue(CFSTR("SecItemSynchronizable"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); - - if (sync && CFGetTypeID(sync) == CFBooleanGetTypeID()) { - syncEnabled = CFBooleanGetValue((CFBooleanRef)sync); - CFRelease(sync); - } - }); - - return syncEnabled; -} - -// -// Function to check whether a synchronizable persistent reference was provided. -// -static Boolean SecItemHasSynchronizablePersistentReference(CFDictionaryRef query) -{ - CFTypeRef value = CFDictionaryGetValue(query, kSecValuePersistentRef); - if (value) { - /* Synchronizable persistent ref consists of the sqlite rowid and 4-byte class value */ - const CFIndex kSynchronizablePersistentRefLength = sizeof(int64_t) + 4; - return (CFGetTypeID(value) == CFDataGetTypeID() && - CFDataGetLength((CFDataRef)value) == kSynchronizablePersistentRefLength); - } - return false; -} - // // Function to apply changes to a mutable dictionary. // (CFDictionaryApplierFunction, called by CFDictionaryApplyFunction) @@ -4121,22 +4180,18 @@ static OSStatus SecItemChangeSynchronizability(CFDictionaryRef query, CFDictiona extern "C" { CFTypeRef -SecItemCreateFromAttributeDictionary(CFDictionaryRef refAttributes) { +SecItemCreateFromAttributeDictionary_osx(CFDictionaryRef refAttributes) { CFTypeRef ref = NULL; - CFStringRef key_class_string = (CFStringRef)CFDictionaryGetValue(refAttributes, kSecClass); - SecItemClass key_class; - bool key_class_found = false; + CFStringRef item_class_string = (CFStringRef)CFDictionaryGetValue(refAttributes, kSecClass); + SecItemClass item_class = 0; - if (CFEqual(key_class_string, kSecClassGenericPassword)) { - key_class = kSecGenericPasswordItemClass; - key_class_found = true; - } - if (CFEqual(key_class_string, kSecClassInternetPassword)) { - key_class = kSecInternetPasswordItemClass; - key_class_found = true; + if (CFEqual(item_class_string, kSecClassGenericPassword)) { + item_class = kSecGenericPasswordItemClass; + } else if (CFEqual(item_class_string, kSecClassInternetPassword)) { + item_class = kSecInternetPasswordItemClass; } - if (key_class_found) { + if (item_class != 0) { // we carry v_Data around here so the *_ios calls can find it and locate // their own data. Putting things in the attribute list doesn't help as // the osx keychainitem and item calls bail when they don't see a keychain @@ -4144,71 +4199,21 @@ SecItemCreateFromAttributeDictionary(CFDictionaryRef refAttributes) { // find a way to craft a workable keychain object. #if'ed code left below // in case we need to go down that path. - struct SecKeychainAttributeList *attrs = (struct SecKeychainAttributeList *)malloc(sizeof(struct SecKeychainAttributeList) + sizeof(struct SecKeychainAttribute) * 0); - attrs->attr = (struct SecKeychainAttribute *)(attrs + 1); - attrs->count = 0; - CFTypeRef v; -#if 0 - // The C++ string objects need to last at least as long as the attr struct. - string account; - - v = CFDictionaryGetValue(refAttributes, CFSTR("mdat")); - if (v) { - attrs->attr[attrs->count].tag = kSecModDateItemAttr; - // XXX need to convert to YYYYMMDDhhmmSSZ - attrs->attr[attrs->count].data = (void*)"19690223140232Z"; - attrs->attr[attrs->count].length = strlen((char*)(attrs->attr[attrs->count].data)); - attrs->count++; - } - v = CFDictionaryGetValue(refAttributes, CFSTR("cdat")); - if (v) { - attrs->attr[attrs->count].tag = kSecCreationDateItemAttr; - // XXX need to convert to YYYYMMDDhhmmSSZ - attrs->attr[attrs->count].data = (void*)"19690223140232Z"; - attrs->attr[attrs->count].length = strlen((char*)(attrs->attr[attrs->count].data)); - attrs->count++; - } - - v = CFDictionaryGetValue(refAttributes, CFSTR("acct")); - if (v) { - attrs->attr[attrs->count].tag = kSecAccountItemAttr; - account = cfString((CFStringRef)v); - attrs->attr[attrs->count].data = (void*)(account.c_str()); - attrs->attr[attrs->count].length = account.length(); - attrs->count++; - } - - // class isn't treated as an attribute by the creation API + SecKeychainAttributeList attrs = {}; + SecKeychainAttribute attr = {}; - v = CFDictionaryGetValue(refAttributes, CFSTR("svce")); - if (v) { - attrs->attr[attrs->count].tag = kSecServiceItemAttr; - account = cfString((CFStringRef)v); - attrs->attr[attrs->count].data = (void*)(account.c_str()); - attrs->attr[attrs->count].length = account.length(); - attrs->count++; - } + attrs.attr = &attr; + attrs.count = 0; + CFTypeRef v; - v = CFDictionaryGetValue(refAttributes, CFSTR("acct")); - if (v) { - attrs->attr[attrs->count].tag = kSecLabelItemAttr; - account = cfString((CFStringRef)v); - attrs->attr[attrs->count].data = (void*)(account.c_str()); - attrs->attr[attrs->count].length = account.length(); - attrs->count++; - } -#endif - Item item = Item(key_class, attrs, 0, ""); - ItemImpl *real_item = item.get(); + Item item = Item(item_class, &attrs, 0, ""); v = CFDictionaryGetValue(refAttributes, kSecValuePersistentRef); if (v) { - real_item->setPersistentRef((CFDataRef)v); + item->setPersistentRef((CFDataRef)v); } - ref = real_item->handle(); - } else { - // keys, certs, identities are not currently sync'able. - ref = NULL; + ref = item->handle(); } + return ref; } @@ -4252,6 +4257,203 @@ SecItemValidateAppleApplicationGroupAccess(CFStringRef group) return status; } +static Mutex gParentCertCacheLock; +static CFMutableDictionaryRef gParentCertCache; +static CFMutableArrayRef gParentCertCacheList; +#define PARENT_CACHE_SIZE 100 + +void SecItemParentCachePurge() { + StLock _(gParentCertCacheLock); + CFReleaseNull(gParentCertCache); + CFReleaseNull(gParentCertCacheList); +} + +static CFArrayRef parentCacheRead(SecCertificateRef certificate) { + CFArrayRef parents = NULL; + CFIndex ix; + CFDataRef digest = SecCertificateGetSHA1Digest(certificate); + if (!digest) return NULL; + + StLock _(gParentCertCacheLock); + if (gParentCertCache && gParentCertCacheList) { + if (0 <= (ix = CFArrayGetFirstIndexOfValue(gParentCertCacheList, + CFRangeMake(0, CFArrayGetCount(gParentCertCacheList)), + digest))) { + // Cache hit. Get value and move entry to the top of the list. + parents = (CFArrayRef)CFDictionaryGetValue(gParentCertCache, digest); + CFArrayRemoveValueAtIndex(gParentCertCacheList, ix); + CFArrayAppendValue(gParentCertCacheList, digest); + } + } + CFRetainSafe(parents); + return parents; +} + +static void parentCacheWrite(SecCertificateRef certificate, CFArrayRef parents) { + CFDataRef digest = SecCertificateGetSHA1Digest(certificate); + if (!digest) return; + + StLock _(gParentCertCacheLock); + if (!gParentCertCache || !gParentCertCacheList) { + CFReleaseNull(gParentCertCache); + gParentCertCache = makeCFMutableDictionary(); + CFReleaseNull(gParentCertCacheList); + gParentCertCacheList = makeCFMutableArray(0); + } + + if (gParentCertCache && gParentCertCacheList) { + // check to make sure another thread didn't add this entry to the cache already + if (0 > CFArrayGetFirstIndexOfValue(gParentCertCacheList, + CFRangeMake(0, CFArrayGetCount(gParentCertCacheList)), + digest)) { + CFDictionaryAddValue(gParentCertCache, digest, parents); + if (PARENT_CACHE_SIZE <= CFArrayGetCount(gParentCertCacheList)) { + // Remove least recently used cache entry. + CFArrayRemoveValueAtIndex(gParentCertCacheList, 0); + } + CFArrayAppendValue(gParentCertCacheList, digest); + } + } +} + +/* + * SecItemCopyParentCertificates returns an array of zero of more possible + * issuer certificates for the provided certificate. No cryptographic validation + * of the signature is performed in this function; its purpose is only to + * provide a list of candidate certificates. + */ +CFArrayRef +SecItemCopyParentCertificates(SecCertificateRef certificate, void *context) +{ +#pragma unused (context) /* for now; in future this can reference a container object */ + /* Check for parents in keychain cache */ + CFArrayRef parents = parentCacheRead(certificate); + if (parents) { + return parents; + } + + /* Cache miss. Query for parents. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerContent(certificate, NULL); +#else + CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate); + CFRetainSafe(normalizedIssuer); +#endif + OSStatus status; + CFMutableArrayRef combinedSearchList = NULL; + + /* Define the array of keychains which will be searched for parents. */ + CFArrayRef searchList = NULL; + status = SecKeychainCopySearchList(&searchList); + if (searchList) { + combinedSearchList = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, searchList); + CFRelease(searchList); + } else { + combinedSearchList = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + } + SecKeychainRef rootStoreKeychain = NULL; + status = SecKeychainOpen(SYSTEM_ROOT_STORE_PATH, &rootStoreKeychain); + if (rootStoreKeychain) { + if (combinedSearchList) { + CFArrayAppendValue(combinedSearchList, rootStoreKeychain); + } + CFRelease(rootStoreKeychain); + } + + /* Create and populate a fixed-size query dictionary. */ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 5, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(query, kSecClass, kSecClassCertificate); + CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue); + CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll); + if (combinedSearchList) { + CFDictionaryAddValue(query, kSecMatchSearchList, combinedSearchList); + CFRelease(combinedSearchList); + } + CFDictionaryAddValue(query, kSecAttrSubject, normalizedIssuer); + + /* Get all certificates matching our query. */ + CFTypeRef results = NULL; + status = SecItemCopyMatching_osx(query, &results); + if ((status != errSecSuccess) && (status != errSecItemNotFound)) { + secitemlog(LOG_WARNING, "SecItemCopyParentCertificates: %d", (int)status); + } + CFRelease(query); + + CFMutableArrayRef result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFTypeID resultType = (results) ? CFGetTypeID(results) : 0; + if (resultType == CFArrayGetTypeID()) { + CFIndex index, count = CFArrayGetCount((CFArrayRef)results); + for (index = 0; index < count; index++) { + CFDataRef data = (CFDataRef) CFArrayGetValueAtIndex((CFArrayRef)results, index); + if (data) { + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, data); + if (cert) { + CFArrayAppendValue(result, cert); + CFRelease(cert); + } + } + } + } else if (resultType == CFDataGetTypeID()) { + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)results); + if (cert) { + CFArrayAppendValue(result, cert); + CFRelease(cert); + } + } + CFReleaseSafe(results); + CFReleaseSafe(normalizedIssuer); + + /* Add to cache. */ + parentCacheWrite(certificate, result); + + return result; +} + +SecCertificateRef SecItemCopyStoredCertificate(SecCertificateRef certificate, void *context) +{ +#pragma unused (context) /* for now; in future this can reference a container object */ + + /* Certificates are unique by issuer and serial number. */ +#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) + CFDataRef serialNumber = SecCertificateCopySerialNumber(certificate, NULL); + CFDataRef normalizedIssuer = SecCertificateCopyNormalizedIssuerContent(certificate, NULL); +#else + CFDataRef serialNumber = SecCertificateCopySerialNumber(certificate); + CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate); + CFRetainSafe(normalizedIssuer); +#endif + + const void *keys[] = { + kSecClass, + kSecMatchLimit, + kSecAttrIssuer, + kSecAttrSerialNumber, + kSecReturnRef + }, + *values[] = { + kSecClassCertificate, + kSecMatchLimitOne, + normalizedIssuer, + serialNumber, + kCFBooleanTrue + }; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 5, NULL, NULL); + CFTypeRef result = NULL; + + OSStatus status = SecItemCopyMatching_osx(query, &result); + if ((status != errSecSuccess) && (status != errSecItemNotFound)) { + secitemlog(LOG_WARNING, "SecItemCopyStoredCertificate: %d", (int)status); + CFReleaseNull(result); + } + CFReleaseSafe(query); + CFReleaseSafe(serialNumber); + CFReleaseSafe(normalizedIssuer); + + return (SecCertificateRef)result; +} + /* * SecItemCopyTranslatedAttributes accepts a user-provided attribute dictionary * and attempts to return a sanitized copy for passing to the underlying @@ -4338,11 +4540,6 @@ SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, */ CFDictionaryRemoveValue(result, kSecUseKeychain); - /* Remove kSecMatchPolicy (value is a SecPolicyRef); - * TODO: need a way to externalize and restore a policy instance - */ - CFDictionaryRemoveValue(result, kSecMatchPolicy); - /* Potentially translate kSecAttrAccess (value is a SecAccessRef), * unless kSecAttrAccessGroup has already been specified. */ @@ -4363,15 +4560,20 @@ SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, CFDictionaryRemoveValue(result, kSecAttrAccess); /* If item is specified by direct reference, and this is an iOS search, - * replace it with a persistent reference. + * replace it with a persistent reference, if it was recorded inside ItemImpl. */ - CFTypeRef directRef = CFDictionaryGetValue(result, kSecValueRef); - if (directRef) { - CFDataRef persistentRef = _SecItemGetPersistentReference(directRef); - if (persistentRef) { - CFDictionarySetValue(result, kSecValuePersistentRef, persistentRef); + CFTypeRef directRef = CFDictionaryGetValue(result, kSecValueRef); + if (directRef != NULL) { + CFTypeID typeID = CFGetTypeID(directRef); + if ((typeID != SecKeyGetTypeID() || SecKeyIsCDSAKey((SecKeyRef)directRef)) && + (typeID != SecCertificateGetTypeID() || SecCertificateIsItemImplInstance((SecCertificateRef)directRef)) && + (typeID != SecIdentityGetTypeID())) { + CFDataRef persistentRef = _SecItemGetPersistentReference(directRef); + if (persistentRef) { + CFDictionarySetValue(result, kSecValuePersistentRef, persistentRef); + CFDictionaryRemoveValue(result, kSecValueRef); + } } - CFDictionaryRemoveValue(result, kSecValueRef); } /* If item is specified by persistent reference, and this is an iOS search, @@ -4398,6 +4600,7 @@ SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, /* Remove attributes which are not part of the OS X database schema. */ CFDictionaryRemoveValue(result, kSecAttrAccessible); + CFDictionaryRemoveValue(result, kSecAttrAccessControl); CFDictionaryRemoveValue(result, kSecAttrAccessGroup); CFDictionaryRemoveValue(result, kSecAttrSynchronizable); CFDictionaryRemoveValue(result, kSecAttrTombstone); @@ -4409,35 +4612,73 @@ SecItemCopyTranslatedAttributes(CFDictionaryRef inOSXDict, CFTypeRef itemClass, return result; } -/* - * SecItemCopyMergedResults takes two input objects, which may be containers, - * and returns a retained object which merges the results. Merging depends on the - * result type. If each result is valid and is not an array, then only one match was - * requested; in that case, the syncable (ios) match is preferred. - * - * FIXME: There are some edge cases still to deal with; e.g. if the OSX search specified a - * particular keychain to search, we do not want to merge in any IOS results. Also, may need - * to filter out duplicates if two items differ only in the sync attribute. - */ -CFTypeRef -SecItemCopyMergedResults(CFDictionaryRef query, CFTypeRef result_osx, CFTypeRef result_ios) -{ - CFTypeID id_osx = (result_osx) ? CFGetTypeID(result_osx) : 0; - CFTypeID id_ios = (result_ios) ? CFGetTypeID(result_ios) : 0; - CFTypeID id_array = CFArrayGetTypeID(); - if ((id_osx == id_array) && (id_ios == id_array)) { - // Fold the arrays into one. - CFMutableArrayRef results = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFArrayAppendArray(results, (CFArrayRef)result_ios, CFRangeMake(0, CFArrayGetCount((CFArrayRef)result_ios))); - CFArrayAppendArray(results, (CFArrayRef)result_osx, CFRangeMake(0, CFArrayGetCount((CFArrayRef)result_osx))); - return results; - } - // Result type is not an array, so only one match can be returned. - return (id_ios) ? CFRetain(result_ios) : CFRetain(result_osx); -} - } /* extern "C" */ +static OSStatus +SecItemMergeResults(bool can_target_ios, OSStatus status_ios, CFTypeRef result_ios, + bool can_target_osx, OSStatus status_osx, CFTypeRef result_osx, + CFTypeRef *result) { + // When querying both keychains and iOS keychain fails because of missing + // entitlements, completely ignore iOS keychain result. This is to keep + // backward compatibility with applications which know nothing about iOS keychain + // and use SecItem API to access OSX keychain which does not need any entitlements. + if (can_target_osx && can_target_ios && status_ios == errSecMissingEntitlement) { + can_target_ios = false; + } + + if (can_target_osx && can_target_ios) { + // If both keychains were targetted, examine returning statuses and decide what to do. + if (status_ios != errSecSuccess) { + // iOS keychain failed to produce results because of some error, go with results from OSX keychain. + AssignOrReleaseResult(result_osx, result); + return status_osx; + } else if (status_osx != errSecSuccess) { + if (status_osx != errSecItemNotFound) { + // OSX failed to produce results with some failure mode (else than not_found), but iOS produced results. + // We have to either return OSX failure result and discard iOS results, or vice versa. For now, we just + // ignore OSX error and return just iOS results. + secitemlog(LOG_NOTICE, "SecItemMergeResults: osx_result=%d, ignoring it, iOS succeeded fine", status_osx); + } + + // OSX failed to produce results, but we have success from iOS keychain; go with results from iOS keychain. + AssignOrReleaseResult(result_ios, result); + return errSecSuccess; + } else { + // Both searches succeeded, merge results. + if (result != NULL) { + CFTypeID id_osx = (result_osx) ? CFGetTypeID(result_osx) : 0; + CFTypeID id_ios = (result_ios) ? CFGetTypeID(result_ios) : 0; + CFTypeID id_array = CFArrayGetTypeID(); + if ((id_osx == id_array) && (id_ios == id_array)) { + // Fold the arrays into one. + *result = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendArray((CFMutableArrayRef)*result, (CFArrayRef)result_ios, + CFRangeMake(0, CFArrayGetCount((CFArrayRef)result_ios))); + CFArrayAppendArray((CFMutableArrayRef)*result, (CFArrayRef)result_osx, + CFRangeMake(0, CFArrayGetCount((CFArrayRef)result_osx))); + } else { + // Result type is not an array, so only one match can be returned. + *result = (id_ios) ? result_ios : result_osx; + CFRetainSafe(*result); + } + } + CFReleaseSafe(result_osx); + CFReleaseSafe(result_ios); + return errSecSuccess; + } + } else if (can_target_ios) { + // Only iOS keychain was targetted. + AssignOrReleaseResult(result_ios, result); + return status_ios; + } else if (can_target_osx) { + // Only OSX keychain was targetted. + AssignOrReleaseResult(result_osx, result); + return status_osx; + } else { + // Query could not run at all? + return errSecParam; + } +} OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) @@ -4450,67 +4691,49 @@ SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result) OSStatus status_osx = errSecItemNotFound, status_ios = errSecItemNotFound; CFTypeRef result_osx = NULL, result_ios = NULL; - Boolean ios_only = SecItemNoLegacy(query); - Boolean sync_enabled = SecItemSyncEnabled(); - Boolean search_ios = SecItemSynchronizable(query); - Boolean merge_search = SecItemSynchronizableAny(query); - Boolean persistref_ios = SecItemHasSynchronizablePersistentReference(query); + bool can_target_ios, can_target_osx; + OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx); + if (status != errSecSuccess) { + return status; + } - if (ios_only || (sync_enabled && (merge_search || persistref_ios || search_ios))) { + if (can_target_ios) { CFDictionaryRef attrs_ios = SecItemCopyTranslatedAttributes(query, CFDictionaryGetValue(query, kSecClass), true, false, false, false, true, true); if (!attrs_ios) { status_ios = errSecParam; } else { - SecItemUnlockSynchronizableKeychain(); - status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios); + status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios); + if(status_ios == errSecInteractionNotAllowed) { + // The keybag is locked. Attempt to unlock it... + if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) { + CFReleaseNull(result_ios); + status_ios = SecItemCopyMatching_ios(attrs_ios, &result_ios); + } + } CFRelease(attrs_ios); } secitemlog(LOG_NOTICE, "SecItemCopyMatching_ios result: %d", status_ios); - if (ios_only || !merge_search || persistref_ios) { - AssignOrReleaseResult(result_ios, result); - return status_ios; // no need to search non-syncable keychains - } - } - - CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(query, - CFDictionaryGetValue(query, kSecClass), false, false, true, false, true, true); - if (!attrs_osx) { - status_osx = errSecParam; - } - else { - status_osx = SecItemCopyMatching_osx(attrs_osx, &result_osx); - CFRelease(attrs_osx); } - secitemlog(LOG_NOTICE, "SecItemCopyMatching_osx result: %d", status_osx); - // If one of the searches failed to occur or produce results, we can eliminate it - if (result_ios == NULL) { - AssignOrReleaseResult(result_osx, result); - return status_osx; // we can only have non-syncable results - } - if (result_osx == NULL) { - AssignOrReleaseResult(result_ios, result); - return status_ios; // we can only have syncable results + if (can_target_osx) { + CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(query, + CFDictionaryGetValue(query, kSecClass), false, false, true, false, true, true); + if (!attrs_osx) { + status_osx = errSecParam; + } + else { + status_osx = SecItemCopyMatching_osx(attrs_osx, &result_osx); + CFRelease(attrs_osx); + } + secitemlog(LOG_NOTICE, "SecItemCopyMatching_osx result: %d", status_osx); } - // If we get here, need to merge results - CFTypeRef result_merged = SecItemCopyMergedResults(query, result_osx, result_ios); - CFReleaseSafe(result_osx); - CFReleaseSafe(result_ios); - AssignOrReleaseResult(result_merged, result); - - if (status_osx == status_ios) { - return status_osx; // both searches produced the same result - } - else if (!status_osx || !status_ios) { - return errSecSuccess; // one of the searches succeeded - } - else if (status_osx == errSecItemNotFound) { - return status_ios; // this failure was more interesting - } - return status_osx; + status = SecItemMergeResults(can_target_ios, status_ios, result_ios, + can_target_osx, status_osx, result_osx, result); + secitemlog(LOG_NOTICE, "SecItemCopyMatching result: %d", status); + return status; } OSStatus @@ -4525,46 +4748,48 @@ SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) } secitemshow(attributes, "SecItemAdd attrs:"); - OSStatus status_osx, status_ios; CFTypeRef result_osx = NULL, result_ios = NULL; - Boolean ios_only = SecItemNoLegacy(attributes); - Boolean sync_enabled = SecItemSyncEnabled(); - Boolean add_ios = SecItemSynchronizable(attributes); + bool can_target_ios, can_target_osx; + OSStatus status = SecItemCategorizeQuery(attributes, can_target_ios, can_target_osx); + if (status != errSecSuccess) { + return status; + } - if (ios_only || (sync_enabled && add_ios)) { + // SecItemAdd cannot be really done on both keychains. In order to keep backward compatibility + // with existing applications, we prefer to add items into legacy keychain and fallback + // into iOS (modern) keychain only when the query is not suitable for legacy keychain. + if (!can_target_osx) { CFDictionaryRef attrs_ios = SecItemCopyTranslatedAttributes(attributes, NULL, true, true, false, false, false, false); if (!attrs_ios) { - status_ios = errSecParam; - } - else { - SecItemUnlockSynchronizableKeychain(); - status_ios = SecItemAdd_ios(attrs_ios, &result_ios); + status = errSecParam; + } else { + status = SecItemAdd_ios(attrs_ios, &result_ios); + if(status == errSecInteractionNotAllowed) { + // The keybag is locked. Attempt to unlock it... + if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) { + CFReleaseNull(result_ios); + status = SecItemAdd_ios(attrs_ios, &result_ios); + } + } CFRelease(attrs_ios); } - secitemlog(LOG_NOTICE, "SecItemAdd_ios result: %d", status_ios); - if (result) - *result = result_ios; - else - CFReleaseSafe(result_ios); - return status_ios; - } - - CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(attributes, - NULL, false, false, true, false, false, false); - if (!attrs_osx) { - status_osx = errSecParam; - } - else { - status_osx = SecItemAdd_osx(attrs_osx, &result_osx); - CFRelease(attrs_osx); + secitemlog(LOG_NOTICE, "SecItemAdd_ios result: %d", status); + AssignOrReleaseResult(result_ios, result); + return status; + } else { + CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(attributes, + NULL, false, false, true, false, false, false); + if (!attrs_osx) { + status = errSecParam; + } else { + status = SecItemAdd_osx(attrs_osx, &result_osx); + CFRelease(attrs_osx); + } + secitemlog(LOG_NOTICE, "SecItemAdd_osx result: %d", status); + AssignOrReleaseResult(result_osx, result); + return status; } - secitemlog(LOG_NOTICE, "SecItemAdd_osx result: %d", status_osx); - if (result) - *result = result_osx; - else - CFReleaseSafe(result_osx); - return status_osx; } OSStatus @@ -4578,65 +4803,62 @@ SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) secitemshow(attributesToUpdate, "SecItemUpdate attrs:"); OSStatus status_osx = errSecItemNotFound, status_ios = errSecItemNotFound; - Boolean ios_only = SecItemNoLegacy(query); - Boolean sync_enabled = SecItemSyncEnabled(); - Boolean search_ios = SecItemSynchronizable(query); - Boolean merge_search = SecItemSynchronizableAny(query); - Boolean persistref_ios = SecItemHasSynchronizablePersistentReference(query); + bool can_target_ios, can_target_osx; + OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx); + if (status != errSecSuccess) { + return status; + } - if (ios_only || (sync_enabled && (merge_search || persistref_ios || search_ios))) { + if (can_target_ios) { CFDictionaryRef attrs_ios = SecItemCopyTranslatedAttributes(query, CFDictionaryGetValue(query, kSecClass), true, true, false, true, true, true); if (!attrs_ios) { status_ios = errSecParam; } else { - SecItemUnlockSynchronizableKeychain(); - if (SecItemHasSynchronizableUpdate(true, attributesToUpdate)) + if (SecItemHasSynchronizableUpdate(true, attributesToUpdate)) { status_ios = SecItemChangeSynchronizability(attrs_ios, attributesToUpdate, false); - else + if(status_ios == errSecInteractionNotAllowed) { + // The keybag is locked. Attempt to unlock it... + if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) { + status_ios = SecItemChangeSynchronizability(attrs_ios, attributesToUpdate, false); + } + } + } else { status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate); + if(status_ios == errSecInteractionNotAllowed) { + // The keybag is locked. Attempt to unlock it... + if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) { + status_ios = SecItemUpdate_ios(attrs_ios, attributesToUpdate); + } + } + } CFRelease(attrs_ios); } secitemlog(LOG_NOTICE, "SecItemUpdate_ios result: %d", status_ios); - if (ios_only || !merge_search || persistref_ios) - return status_ios; } - CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(query, - CFDictionaryGetValue(query, kSecClass), false, false, true, true, true, true); - if (!attrs_osx) { - status_osx = errSecParam; - } - else { - if (SecItemHasSynchronizableUpdate(false, attributesToUpdate)) - status_osx = SecItemChangeSynchronizability(attrs_osx, attributesToUpdate, true); - else - status_osx = SecItemUpdate_osx(attrs_osx, attributesToUpdate); - - CFRelease(attrs_osx); - } - secitemlog(LOG_NOTICE, "SecItemUpdate_osx result: %d", status_osx); - if (merge_search) { - // Harmonize the result of the update attempts. - if (status_osx == status_ios) { - // both updates produced the same result - return status_ios; + if (can_target_osx) { + CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(query, + CFDictionaryGetValue(query, kSecClass), false, false, true, true, true, true); + if (!attrs_osx) { + status_osx = errSecParam; } - else if (!status_osx || !status_ios) { - // one of the updates succeeded, but the other failed - if (status_osx == errSecItemNotFound || status_ios == errSecItemNotFound) - return errSecSuccess; // item only found in one keychain + else { + if (SecItemHasSynchronizableUpdate(false, attributesToUpdate)) + status_osx = SecItemChangeSynchronizability(attrs_osx, attributesToUpdate, true); else - return (status_osx) ? status_osx : status_ios; // return the error - } - else if (status_osx == errSecItemNotFound) { - // both updates failed, status_ios failure is more interesting - // since the item was actually found - return status_ios; + status_osx = SecItemUpdate_osx(attrs_osx, attributesToUpdate); + + CFRelease(attrs_osx); } + secitemlog(LOG_NOTICE, "SecItemUpdate_osx result: %d", status_osx); } - return status_osx; + + status = SecItemMergeResults(can_target_ios, status_ios, NULL, + can_target_osx, status_osx, NULL, NULL); + secitemlog(LOG_NOTICE, "SecItemUpdate result: %d", status); + return status; } OSStatus @@ -4649,59 +4871,60 @@ SecItemDelete(CFDictionaryRef query) secitemshow(query, "SecItemDelete query:"); OSStatus status_osx = errSecItemNotFound, status_ios = errSecItemNotFound; - Boolean ios_only = SecItemNoLegacy(query); - Boolean sync_enabled = SecItemSyncEnabled(); - Boolean search_ios = SecItemSynchronizable(query); - Boolean merge_search = SecItemSynchronizableAny(query); - Boolean persistref_ios = SecItemHasSynchronizablePersistentReference(query); + bool can_target_ios, can_target_osx; + OSStatus status = SecItemCategorizeQuery(query, can_target_ios, can_target_osx); + if (status != errSecSuccess) { + return status; + } - if (ios_only || (sync_enabled && (merge_search || persistref_ios || search_ios))) { + if (can_target_ios) { CFDictionaryRef attrs_ios = SecItemCopyTranslatedAttributes(query, NULL, true, true, false, true, true, true); if (!attrs_ios) { status_ios = errSecParam; - } - else { - SecItemUnlockSynchronizableKeychain(); + } else { status_ios = SecItemDelete_ios(attrs_ios); + if(status_ios == errSecInteractionNotAllowed) { + // The keybag is locked. Attempt to unlock it... + if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) { + status_ios = SecItemDelete_ios(attrs_ios); + } + } CFRelease(attrs_ios); } secitemlog(LOG_NOTICE, "SecItemDelete_ios result: %d", status_ios); - if (ios_only || !merge_search || persistref_ios) - return status_ios; - } - - CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(query, - NULL, false, false, true, true, true, true); - if (!attrs_osx) { - status_osx = errSecParam; - } - else { - status_osx = SecItemDelete_osx(attrs_osx); - CFRelease(attrs_osx); } - secitemlog(LOG_NOTICE, "SecItemDelete_osx result: %d", status_osx); - if (merge_search) { - // Harmonize the result of the delete attempts. - if (status_osx == status_ios) { - // both deletes produced the same result - return status_ios; - } - else if (!status_osx || !status_ios) { - // one of the deletes succeeded, but the other failed - if (status_osx == errSecItemNotFound || status_ios == errSecItemNotFound) - return errSecSuccess; // item only found in one keychain - else - return (status_osx) ? status_osx : status_ios; // return the error - } - else if (status_osx == errSecItemNotFound) { - // both deletes failed, status_ios failure is more interesting - // since the item was actually found - return status_ios; + if (can_target_osx) { + CFDictionaryRef attrs_osx = SecItemCopyTranslatedAttributes(query, + NULL, false, false, true, true, true, true); + if (!attrs_osx) { + status_osx = errSecParam; + } else { + status_osx = SecItemDelete_osx(attrs_osx); + CFRelease(attrs_osx); } + secitemlog(LOG_NOTICE, "SecItemDelete_osx result: %d", status_osx); } - return status_osx; + + status = SecItemMergeResults(can_target_ios, status_ios, NULL, + can_target_osx, status_osx, NULL, NULL); + secitemlog(LOG_NOTICE, "SecItemCopyDelete result: %d", status); + return status; +} + +OSStatus +SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes) +{ + OSStatus status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes); + if(status == errSecInteractionNotAllowed) { + // The keybag is locked. Attempt to unlock it... + if(errSecSuccess == SecKeychainVerifyKeyStorePassphrase(3)) { + status = SecItemUpdateTokenItems_ios(tokenID, tokenItemsAttributes); + } + } + secitemlog(LOG_NOTICE, "SecItemUpdateTokenItems_ios result: %d", status); + return status; } OSStatus @@ -4799,7 +5022,11 @@ SecItemAdd_osx( // but in any case it should try to add the certificate. See . require_action(!itemParams->returnIdentity, error_exit, status = errSecItemInvalidValue); - if (!itemParams->useItems) { + if (itemParams->useItems == NULL) { + + require_action(itemParams->itemData == NULL || CFGetTypeID(itemParams->itemData) == CFDataGetTypeID(), + error_exit, status = errSecItemInvalidValue); + // create a single keychain item specified by the input attributes status = SecKeychainItemCreateFromContent(itemParams->itemClass, itemParams->attrList, @@ -4927,7 +5154,7 @@ SecItemUpdate_osx( // run the provided query to get a list of items to update CFTypeRef results = NULL; - OSStatus status = SecItemCopyMatching(query, &results); + OSStatus status = SecItemCopyMatching_osx(query, &results); if (status != errSecSuccess) return status; // nothing was matched, or the query was bad diff --git a/OSX/libsecurity_keychain/lib/SecItem.h b/OSX/libsecurity_keychain/lib/SecItem.h index 7893e2b5..9d325aff 100644 --- a/OSX/libsecurity_keychain/lib/SecItem.h +++ b/OSX/libsecurity_keychain/lib/SecItem.h @@ -517,6 +517,8 @@ extern const CFStringRef kSecAttrCanWrap __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); extern const CFStringRef kSecAttrCanUnwrap __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); +extern const CFStringRef kSecAttrTokenID + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_9_0); /*! @enum kSecAttrAccessible Value Constants @@ -742,6 +744,7 @@ extern const CFStringRef kSecAttrKeyClassSymmetric @constant kSecAttrKeyTypeCAST @constant kSecAttrKeyTypeECDSA (deprecated; use kSecAttrKeyTypeEC instead.) @constant kSecAttrKeyTypeEC + @constant kSecAttrKeyTypeECSECPrimeRandom */ extern const CFStringRef kSecAttrKeyTypeRSA __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); @@ -763,6 +766,8 @@ extern const CFStringRef kSecAttrKeyTypeECDSA __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecAttrKeyTypeEC __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); +extern const CFStringRef kSecAttrKeyTypeECSECPrimeRandom + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); /*! @enum kSecAttrPRF Value Constants @@ -1009,6 +1014,37 @@ extern const CFStringRef kSecUseAuthenticationUIFail extern const CFStringRef kSecUseAuthenticationUISkip __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); +#if !RC_HIDE_J79 && !RC_HIDE_J80 +/*! + @enum kSecAttrTokenID Value Constants + @discussion Predefined item attribute constant used to get or set values + in a dictionary. The kSecAttrTokenID constant is the key and its value + can be kSecAttrTokenIDSecureEnclave. + @constant kSecAttrTokenIDSecureEnclave Specifies well-known identifier of the + token implemented using device's Secure Enclave. The only keychain items + supported by the Secure Enclave token are 256-bit elliptic curve keys + (kSecAttrKeyTypeEC). Keys must be generated on the secure enclave using + SecKeyGenerateKeyPair call with kSecAttrTokenID set to + kSecAttrTokenIDSecureEnclave in the parameters dictionary, it is not + possible to import pregenerated keys to kSecAttrTokenIDSecureEnclave token. +*/ +extern const CFStringRef kSecAttrTokenIDSecureEnclave + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_9_0); +#endif + +/*! + @enum kSecAttrAccessGroup Value Constants + @constant kSecAttrAccessGroupToken Represents well-known access group + which contains items provided by external token (typically smart card). + This may be used as a value for kSecAttrAccessGroup attribute. Every + application has access to this access group so it is not needed to + explicitly list it in keychain-access-groups entitlement, but application + must explicitly state this access group in keychain queries in order to + be able to access items from external tokens. +*/ +extern const CFStringRef kSecAttrAccessGroupToken + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); + /*! @function SecItemCopyMatching @abstract Returns one or more items which match a search query. diff --git a/OSX/libsecurity_keychain/lib/SecItemConstants.c b/OSX/libsecurity_keychain/lib/SecItemConstants.c index 994a1fea..92e55064 100644 --- a/OSX/libsecurity_keychain/lib/SecItemConstants.c +++ b/OSX/libsecurity_keychain/lib/SecItemConstants.c @@ -112,6 +112,10 @@ SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna"); SEC_CONST_DECL (kSecAttrTombstone, "tomb"); SEC_CONST_DECL (kSecAttrNoLegacy, "nleg"); SEC_CONST_DECL (kSecAttrMultiUser, "musr"); +SEC_CONST_DECL (kSecAttrTokenOID, "toid"); + +/* Predefined access groups constants */ +SEC_CONST_DECL (kSecAttrAccessGroupToken, "com.apple.token"); /* Search Constants */ SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); @@ -158,6 +162,9 @@ SEC_CONST_DECL (kSecAttrAccessibleWhenUnlockedThisDeviceOnly, "aku"); SEC_CONST_DECL (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, "cku"); SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnly, "dku"); SEC_CONST_DECL (kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, "akpu"); +/* kSecAttrAccessible Value Constants (Private). */ +SEC_CONST_DECL (kSecAttrAccessibleAlwaysPrivate, "dk"); +SEC_CONST_DECL (kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate, "dku"); /* kSecAttrProtocol Value Constants. */ SEC_CONST_DECL (kSecAttrProtocolFTP, "ftp "); @@ -221,6 +228,7 @@ SEC_CONST_DECL (kSecAttrKeyTypeDSA, "43"); SEC_CONST_DECL (kSecAttrKeyTypeCAST, "56"); SEC_CONST_DECL (kSecAttrKeyTypeECDSA, "73"); SEC_CONST_DECL (kSecAttrKeyTypeEC, "73"); /* rdar://13326326 */ +SEC_CONST_DECL (kSecAttrKeyTypeECSECPrimeRandom, "73"); SEC_CONST_DECL (kSecAttrKeyTypeAES, "2147483649"); /* */ SEC_CONST_DECL (kSecAttrPRFHmacAlgSHA1, "hsha1"); diff --git a/OSX/libsecurity_keychain/lib/SecItemPriv.h b/OSX/libsecurity_keychain/lib/SecItemPriv.h index 57593b81..c8065f0c 100644 --- a/OSX/libsecurity_keychain/lib/SecItemPriv.h +++ b/OSX/libsecurity_keychain/lib/SecItemPriv.h @@ -2,14 +2,14 @@ * Copyright (c) 2006-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, @@ -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@ */ @@ -34,6 +34,7 @@ #include #include #include +#include #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) #include @@ -280,10 +281,23 @@ extern const CFStringRef kSecAttrNoLegacy __OSX_AVAILABLE(10.11) __IOS_AVAILABLE(9.3) __TVOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.3); extern const CFStringRef kSecAttrSyncViewHint __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); -extern const CFStringRef kSecAttrTokenID - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); extern const CFStringRef kSecAttrMultiUser __OSX_AVAILABLE(10.11.5) __IOS_AVAILABLE(9.3) __TVOS_AVAILABLE(9.3) __WATCHOS_AVAILABLE(2.3); +extern const CFStringRef kSecAttrTokenOID + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + + +/*! + @enum kSecAttrAccessible Value Constants (Private) + @constant kSecAttrAccessibleAlwaysPrivate Private alias for kSecAttrAccessibleAlways, + which is going to be deprecated for 3rd party use. + @constant kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate for kSecAttrAccessibleAlwaysThisDeviceOnly, + which is going to be deprecated for 3rd party use. +*/ +extern const CFStringRef kSecAttrAccessibleAlwaysPrivate +;//%%% __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecAttrAccessibleAlwaysThisDeviceOnlyPrivate +;//%%% __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); /* View Hint Constants */ @@ -297,10 +311,13 @@ extern const CFStringRef kSecAttrViewHintPCSMailDrop; extern const CFStringRef kSecAttrViewHintPCSiCloudBackup; extern const CFStringRef kSecAttrViewHintPCSNotes; extern const CFStringRef kSecAttrViewHintPCSiMessage; +extern const CFStringRef kSecAttrViewHintPCSSharing; extern const CFStringRef kSecAttrViewHintAppleTV; extern const CFStringRef kSecAttrViewHintHomeKit; extern const CFStringRef kSecAttrViewHintThumper; +extern const CFStringRef kSecAttrViewHintContinuityUnlock; +extern const CFStringRef kSecAttrViewHintAccessoryPairing; /*! @enum Other Constants (Private) @@ -365,6 +382,42 @@ OSStatus SecItemCopyDisplayNames(CFArrayRef items, CFArrayRef *displayNames); */ OSStatus SecItemDeleteAll(void); + +/*! + @function SecItemParentCachePurge + @abstract Clear the cache of parent certificates used in SecItemCopyParentCertificates. + */ +void SecItemParentCachePurge(); + +/*! + @function SecItemCopyParentCertificates + @abstract Retrieve an array of possible issuing certificates for a given certificate. + @param certificate A reference to a certificate whose issuers are being sought. + @param context Pass NULL in this parameter to indicate that the default certificate + source(s) should be searched. The default is to search all available keychains. + Values of context other than NULL are currently ignored. + @result An array of zero or more certificates whose normalized subject matches the + normalized issuer of the provided certificate. Note that no cryptographic validation + of the signature is performed by this function; its purpose is only to provide a list + of candidate certificates. +*/ +CFArrayRef SecItemCopyParentCertificates(SecCertificateRef certificate, void *context) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); + +/*! + @function SecItemCopyStoredCertificate + @abstract Retrieve the first stored instance of a given certificate. + @param certificate A reference to a certificate. + @param context Pass NULL in this parameter to indicate that the default certificate + source(s) should be searched. The default is to search all available keychains. + Values of context other than NULL are currently ignored. + @result Returns a certificate reference if the given certificate exists in a keychain, + or NULL if the certificate cannot be found in any keychain. The caller is responsible + for releasing the returned certificate reference when finished with it. +*/ +SecCertificateRef SecItemCopyStoredCertificate(SecCertificateRef certificate, void *context) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); + /* Ensure the escrow keybag has been used to unlock the system keybag before calling either of these APIs. @@ -388,7 +441,7 @@ CFArrayRef _SecKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *er CFDataRef _SecItemGetPersistentReference(CFTypeRef raw_item); #endif -/* Returns an OSStatus value for the given CFErrorRef, returns errSecInternal if the +/* Returns an OSStatus value for the given CFErrorRef, returns errSecInternal if the domain of the provided error is not recognized. Passing NULL returns errSecSuccess (0). */ OSStatus SecErrorGetOSStatus(CFErrorRef error); @@ -398,6 +451,8 @@ CFDictionaryRef _SecSecuritydCopyWhoAmI(CFErrorRef *error); bool _SecSyncBubbleTransfer(CFArrayRef services, CFErrorRef *error); bool _SecSystemKeychainTransfer(CFErrorRef *error); +OSStatus SecItemUpdateTokenItems(CFTypeRef tokenID, CFArrayRef tokenItemsAttributes); + __END_DECLS #endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecKey.cpp b/OSX/libsecurity_keychain/lib/SecKey.cpp index cd703686..a80fe3be 100644 --- a/OSX/libsecurity_keychain/lib/SecKey.cpp +++ b/OSX/libsecurity_keychain/lib/SecKey.cpp @@ -44,29 +44,756 @@ #include #include +#include +#include +#include #include "SecImportExportCrypto.h" -/* Since there are currently two implementations of SecKey present, - * we need a specific function to return the registered type of the - * CFClass implementation, so we can determine which type we have. - */ -CFTypeID -SecKeyGetCFClassTypeID(void) -{ - BEGIN_SECAPI +static OSStatus +SecCDSAKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { + key->key = const_cast(reinterpret_cast(keyData)); + key->key->initializeWithSecKeyRef(key); + return errSecSuccess; +} + +static void +SecCDSAKeyDestroy(SecKeyRef keyRef) { + // Note: If this key is holding the last strong reference to its keychain, the keychain will be released during this operation. + // If we hold the keychain's mutex (the key's 'mutexForObject') during this destruction, pthread gets upset. + // Hold a reference to the keychain (if it exists) until after we release the keychain's mutex. + + KeyItem *keyItem = keyRef->key; + if (keyItem == NULL) { + // KeyImpl::attachSecKeyRef disconnected us from KeyItem instance, there is nothing to do for us. + return; + } + + Keychain kc = keyItem->keychain(); + + { + StMaybeLock _(keyItem->getMutexForObject()); + keyItem = keyRef->key; + if (keyItem == NULL) { + // Second version of the check above, the definitive one because this one is performed with locked object's mutex, therefore we can be sure that KeyImpl is still connected to this keyRef instance. + return; + } + + keyItem->aboutToDestruct(); + delete keyItem; + } + + (void) kc; // Tell the compiler we're actually using this variable. At destruction time, it'll release the keychain. +} + +static size_t +SecCDSAKeyGetBlockSize(SecKeyRef key) { + + CFErrorRef *error = NULL; + BEGIN_SECKEYAPI(size_t,0) + + const CssmKey::Header keyHeader = key->key->unverifiedKeyHeader(); + switch(keyHeader.algorithm()) + { + case CSSM_ALGID_RSA: + case CSSM_ALGID_DSA: + result = keyHeader.LogicalKeySizeInBits / 8; + break; + case CSSM_ALGID_ECDSA: + { + /* Block size is up to 9 bytes of DER encoding for sequence of 2 integers, + * plus both coordinates for the point used */ +#define ECDSA_KEY_SIZE_IN_BYTES(bits) (((bits) + 7) / 8) +#define ECDSA_MAX_COORD_SIZE_IN_BYTES(n) (ECDSA_KEY_SIZE_IN_BYTES(n) + 1) + size_t coordSize = ECDSA_MAX_COORD_SIZE_IN_BYTES(keyHeader.LogicalKeySizeInBits); + assert(coordSize < 256); /* size must fit in a byte for DER */ + size_t coordDERLen = (coordSize > 127) ? 2 : 1; + size_t coordLen = 1 + coordDERLen + coordSize; + + size_t pointSize = 2 * coordLen; + assert(pointSize < 256); /* size must fit in a byte for DER */ + size_t pointDERLen = (pointSize > 127) ? 2 : 1; + size_t pointLen = 1 + pointDERLen + pointSize; + + result = pointLen; + } + break; + case CSSM_ALGID_AES: + result = 16; /* all AES keys use 128-bit blocks */ + break; + case CSSM_ALGID_DES: + case CSSM_ALGID_3DES_3KEY: + result = 8; /* all DES keys use 64-bit blocks */ + break; + default: + assert(0); /* some other key algorithm */ + result = 16; /* FIXME: revisit this */ + break; + } + + END_SECKEYAPI +} - return gTypes().KeyItem.typeID; +static CFIndex +SecCDSAKeyGetAlgorithmId(SecKeyRef key) { + + CFErrorRef *error = NULL; + BEGIN_SECKEYAPI(CFIndex, 0) + + result = kSecNullAlgorithmID; + switch (key->key->unverifiedKeyHeader().AlgorithmId) { + case CSSM_ALGID_RSA: + result = kSecRSAAlgorithmID; + break; + case CSSM_ALGID_DSA: + result = kSecDSAAlgorithmID; + break; + case CSSM_ALGID_ECDSA: + result = kSecECDSAAlgorithmID; + break; + default: + assert(0); /* other algorithms TBA */ + } + + END_SECKEYAPI +} + +static CFDataRef SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(CFDataRef pubKeyInfo) { + // First of all, consider x509 format and try to strip SubjPubKey envelope. If it fails, do not panic + // and export data as is. + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), CFDataGetLength(pubKeyInfo) }, pubKeyItem; + DERByte numUnused; + DERSubjPubKeyInfo subjPubKey; + if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs, + DERSubjPubKeyInfoItemSpecs, + &subjPubKey, sizeof(subjPubKey)) == DR_Success && + DERParseBitString(&subjPubKey.pubKey, &pubKeyItem, &numUnused) == DR_Success) { + return CFDataCreate(kCFAllocatorDefault, pubKeyItem.data, pubKeyItem.length); + } + + return CFDataRef(CFRetain(pubKeyInfo)); +} + +static CFDataRef SecCDSAKeyCopyPublicKeyDataWithSubjectInfo(CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CFDataRef pubKeyInfo) { + // First check, whether X509 pubkeyinfo is already present. If not, add it according to the key type. + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(pubKeyInfo), CFDataGetLength(pubKeyInfo) }; + DERSubjPubKeyInfo subjPubKey; + if (DERParseSequence(&keyItem, DERNumSubjPubKeyInfoItemSpecs, + DERSubjPubKeyInfoItemSpecs, + &subjPubKey, sizeof(subjPubKey)) == DR_Success) { + return CFDataRef(CFRetain(pubKeyInfo)); + } + + // We have always size rounded to full bytes so bitstring encodes leading 00. + CFRef bitStringPubKey = CFDataCreateMutable(kCFAllocatorDefault, 0); + CFDataSetLength(bitStringPubKey, 1); + CFDataAppendBytes(bitStringPubKey, CFDataGetBytePtr(pubKeyInfo), CFDataGetLength(pubKeyInfo)); + subjPubKey.pubKey.data = static_cast(const_cast(CFDataGetBytePtr(bitStringPubKey))); + subjPubKey.pubKey.length = CFDataGetLength(bitStringPubKey); + + // Encode algId according to algorithm used. + static const DERByte oidRSA[] = { + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + }; + static const DERByte oidECsecp256[] = { + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + }; + static const DERByte oidECsecp384[] = { + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, + }; + static const DERByte oidECsecp521[] = { + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, + }; + subjPubKey.algId.length = 0; + if (algorithm == CSSM_ALGID_RSA) { + subjPubKey.algId.data = const_cast(oidRSA); + subjPubKey.algId.length = sizeof(oidRSA); + } else if (algorithm == CSSM_ALGID_ECDSA) { + if (keySizeInBits == 256) { + subjPubKey.algId.data = const_cast(oidECsecp256); + subjPubKey.algId.length = sizeof(oidECsecp256); + } else if (keySizeInBits == 384) { + subjPubKey.algId.data = const_cast(oidECsecp384); + subjPubKey.algId.length = sizeof(oidECsecp256); + } if (keySizeInBits == 521) { + subjPubKey.algId.data = const_cast(oidECsecp521); + subjPubKey.algId.length = sizeof(oidECsecp256); + } + } + DERSize size = DERLengthOfEncodedSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey, + DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs); + CFRef keyData = CFDataCreateMutable(kCFAllocatorDefault, size); + CFDataSetLength(keyData, size); + if (DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &subjPubKey, + DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, + static_cast(CFDataGetMutableBytePtr(keyData)), &size) == DR_Success) { + CFDataSetLength(keyData, size); + } else { + keyData.release(); + } + + return keyData.yield(); +} + +static OSStatus SecCDSAKeyCopyPublicBytes(SecKeyRef key, CFDataRef *serialization) { + + CFErrorRef *error = NULL; + BEGIN_SECKEYAPI(OSStatus, errSecSuccess) + + const CssmKey::Header &header = key->key->key().header(); + switch (header.algorithm()) { + case CSSM_ALGID_RSA: { + switch (header.keyClass()) { + case CSSM_KEYCLASS_PRIVATE_KEY: { + CFRef privKeyData; + result = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, privKeyData.take()); + if (result == errSecSuccess) { + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(privKeyData), CFDataGetLength(privKeyData) }; + DERRSAKeyPair keyPair; + if (DERParseSequence(&keyItem, DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs, + &keyPair, sizeof(keyPair)) == DR_Success) { + DERRSAPubKeyPKCS1 pubKey = { keyPair.n, keyPair.e }; + DERSize size = DERLengthOfEncodedSequence(ASN1_SEQUENCE, &pubKey, + DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs); + CFRef keyData = CFDataCreateMutable(kCFAllocatorDefault, size); + CFDataSetLength(keyData, size); + UInt8 *data = CFDataGetMutableBytePtr(keyData); + if (DEREncodeSequence(ASN1_SEQUENCE, &pubKey, + DERNumRSAPubKeyPKCS1ItemSpecs, DERRSAPubKeyPKCS1ItemSpecs, + data, &size) == DR_Success) { + CFDataSetLength(keyData, size); + *data = ONE_BYTE_ASN1_CONSTR_SEQUENCE; + *serialization = keyData.yield(); + } else { + *serialization = NULL; + result = errSecParam; + } + } + } + break; + } + case CSSM_KEYCLASS_PUBLIC_KEY: + result = SecItemExport(key, kSecFormatBSAFE, 0, NULL, serialization); + break; + } + break; + } + case CSSM_ALGID_ECDSA: { + *serialization = NULL; + CFRef tempPublicData; + result = SecItemExport(key, kSecFormatOpenSSL, 0, NULL, tempPublicData.take()); + if (result == errSecSuccess) { + *serialization = SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(tempPublicData); + } + break; + } + default: + result = errSecUnimplemented; + } - END_SECAPI1(_kCFRuntimeNotATypeID) + END_SECKEYAPI } -CFTypeID -SecKeyGetTypeID(void) +typedef struct { + DERItem privateKey; + DERItem publicKey; +} DERECPrivateKey; + +static const DERItemSpec DERECPrivateKeyItemSpecs[] = +{ + { 0, + ASN1_INTEGER, + DER_DEC_SKIP }, + { DER_OFFSET(DERECPrivateKey, privateKey), + ASN1_OCTET_STRING, + DER_DEC_NO_OPTS | DER_ENC_NO_OPTS }, + { 0, + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0, + DER_DEC_SKIP | DER_ENC_NO_OPTS }, + { DER_OFFSET(DERECPrivateKey, publicKey), + ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1, + DER_DEC_NO_OPTS | DER_ENC_SIGNED_INT }, +}; +static const DERSize DERNumECPrivateKeyItemSpecs = +sizeof(DERECPrivateKeyItemSpecs) / sizeof(DERItemSpec); + +typedef struct { + DERItem bitString; +} DERECPrivateKeyPublicKey; + +static const DERItemSpec DERECPrivateKeyPublicKeyItemSpecs[] = { - return SecKeyGetCFClassTypeID(); + { DER_OFFSET(DERECPrivateKeyPublicKey, bitString), + ASN1_BIT_STRING, + DER_DEC_NO_OPTS | DER_ENC_NO_OPTS }, +}; +static const DERSize DERNumECPrivateKeyPublicKeyItemSpecs = +sizeof(DERECPrivateKeyPublicKeyItemSpecs) / sizeof(DERItemSpec); + +static CFDataRef +SecCDSAKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) { + + BEGIN_SECKEYAPI(CFDataRef, NULL) + + result = NULL; + const CssmKey::Header header = key->key->unverifiedKeyHeader(); + CFRef keyData; + switch (header.algorithm()) { + case CSSM_ALGID_RSA: + MacOSError::check(SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take())); + break; + case CSSM_ALGID_ECDSA: { + MacOSError::check(SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take())); + if (header.keyClass() == CSSM_KEYCLASS_PRIVATE_KEY) { + // Convert DER format into x9.63 format, which is expected for exported key. + DERItem keyItem = { (DERByte *)CFDataGetBytePtr(keyData), CFDataGetLength(keyData) }; + DERECPrivateKey privateKey; + DERECPrivateKeyPublicKey privateKeyPublicKey; + DERByte numUnused; + DERItem pubKeyItem; + if (DERParseSequence(&keyItem, DERNumECPrivateKeyItemSpecs, DERECPrivateKeyItemSpecs, + &privateKey, sizeof(privateKey)) == DR_Success && + DERParseSequenceContent(&privateKey.publicKey, DERNumECPrivateKeyPublicKeyItemSpecs, + DERECPrivateKeyPublicKeyItemSpecs, + &privateKeyPublicKey, sizeof(privateKeyPublicKey)) == DR_Success && + DERParseBitString(&privateKeyPublicKey.bitString, &pubKeyItem, &numUnused) == DR_Success) { + CFRef key = CFDataCreateMutable(kCFAllocatorDefault, + pubKeyItem.length + privateKey.privateKey.length); + CFDataSetLength(key, pubKeyItem.length + privateKey.privateKey.length); + CFDataReplaceBytes(key, CFRangeMake(0, pubKeyItem.length), pubKeyItem.data, pubKeyItem.length); + CFDataReplaceBytes(key, CFRangeMake(pubKeyItem.length, privateKey.privateKey.length), + privateKey.privateKey.data, privateKey.privateKey.length); + keyData = key.as(); + } + } + break; + } + default: + MacOSError::throwMe(errSecUnimplemented); + } + + if (header.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) { + result = SecCDSAKeyCopyPublicKeyDataFromSubjectInfo(keyData); + } else { + result = keyData.yield(); + } + + END_SECKEYAPI +} + +static CFDataRef SecCDSAKeyCopyLabel(SecKeyRef key) { + CFDataRef label = NULL; + if (key->key->isPersistent()) { + UInt32 tags[] = { kSecKeyLabel }, formats[] = { CSSM_DB_ATTRIBUTE_FORMAT_BLOB }; + SecKeychainAttributeInfo info = { 1, tags, formats }; + SecKeychainAttributeList *list = NULL; + key->key->getAttributesAndData(&info, NULL, &list, NULL, NULL); + if (list->count == 1) { + SecKeychainAttribute *attr = list->attr; + label = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)attr->data, (CFIndex)attr->length); + } + key->key->freeAttributesAndData(list, NULL); + } + return label; +} + +static CFDictionaryRef +SecCDSAKeyCopyAttributeDictionary(SecKeyRef key) { + + CFErrorRef *error = NULL; + BEGIN_SECKEYAPI(CFDictionaryRef, NULL) + + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionarySetValue(dict, kSecClass, kSecClassKey); + + const CssmKey::Header header = key->key->unverifiedKeyHeader(); + CFIndex sizeValue = header.LogicalKeySizeInBits; + CFRef sizeInBits = CFNumberCreate(NULL, kCFNumberCFIndexType, &sizeValue); + CFDictionarySetValue(dict, kSecAttrKeySizeInBits, sizeInBits); + CFDictionarySetValue(dict, kSecAttrEffectiveKeySize, sizeInBits); + + CFRef label = SecCDSAKeyCopyLabel(key); + if (!label) { + // For floating keys, calculate label as SHA1 of pubkey bytes. + CFRef pubKeyBlob; + if (SecCDSAKeyCopyPublicBytes(key, pubKeyBlob.take()) == errSecSuccess) { + uint8_t pubKeyHash[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(CFDataGetBytePtr(pubKeyBlob), CC_LONG(CFDataGetLength(pubKeyBlob)), pubKeyHash); + label.take(CFDataCreate(kCFAllocatorDefault, pubKeyHash, sizeof(pubKeyHash))); + } + } + + if (label) { + CFDictionarySetValue(dict, kSecAttrApplicationLabel, label); + } + + CSSM_KEYATTR_FLAGS attrs = header.attributes(); + CFDictionarySetValue(dict, kSecAttrIsPermanent, (attrs & CSSM_KEYATTR_PERMANENT) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrIsPrivate, (attrs & CSSM_KEYATTR_PRIVATE) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrIsModifiable, (attrs & CSSM_KEYATTR_MODIFIABLE) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrIsSensitive, (attrs & CSSM_KEYATTR_SENSITIVE) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrIsExtractable, (attrs & CSSM_KEYATTR_EXTRACTABLE) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrWasAlwaysSensitive, (attrs & CSSM_KEYATTR_ALWAYS_SENSITIVE) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrWasNeverExtractable, (attrs & CSSM_KEYATTR_NEVER_EXTRACTABLE) ? kCFBooleanTrue : kCFBooleanFalse); + + CFDictionarySetValue(dict, kSecAttrCanEncrypt, (header.useFor(CSSM_KEYUSE_ENCRYPT)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanDecrypt, (header.useFor(CSSM_KEYUSE_DECRYPT)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanSign, (header.useFor(CSSM_KEYUSE_SIGN)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanVerify, (header.useFor(CSSM_KEYUSE_VERIFY)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanSignRecover, (header.useFor(CSSM_KEYUSE_SIGN_RECOVER)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanVerifyRecover, (header.useFor(CSSM_KEYUSE_VERIFY_RECOVER)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanWrap, (header.useFor(CSSM_KEYUSE_WRAP)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanUnwrap, (header.useFor(CSSM_KEYUSE_UNWRAP)) ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(dict, kSecAttrCanDerive, (header.useFor(CSSM_KEYUSE_DERIVE)) ? kCFBooleanTrue : kCFBooleanFalse); + + switch (header.keyClass()) { + case CSSM_KEYCLASS_PUBLIC_KEY: + CFDictionarySetValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPublic); + break; + case CSSM_KEYCLASS_PRIVATE_KEY: + CFDictionarySetValue(dict, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + break; + } + + switch (header.algorithm()) { + case CSSM_ALGID_RSA: + CFDictionarySetValue(dict, kSecAttrKeyType, kSecAttrKeyTypeRSA); + break; + case CSSM_ALGID_ECDSA: + CFDictionarySetValue(dict, kSecAttrKeyType, kSecAttrKeyTypeECDSA); + break; + } + + CFRef keyData; + if (SecItemExport(key, kSecFormatOpenSSL, 0, NULL, keyData.take()) == errSecSuccess) { + CFDictionarySetValue(dict, kSecValueData, keyData); + } + + if (header.algorithm() == CSSM_ALGID_RSA && header.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY && + header.blobType() == CSSM_KEYBLOB_RAW) { + const CssmData &keyData = key->key->key()->keyData(); + DERItem keyItem = { static_cast(keyData.data()), keyData.length() }; + DERRSAPubKeyPKCS1 decodedKey; + if (DERParseSequence(&keyItem, DERNumRSAPubKeyPKCS1ItemSpecs, + DERRSAPubKeyPKCS1ItemSpecs, + &decodedKey, sizeof(decodedKey)) == DR_Success) { + CFRef modulus = CFDataCreate(kCFAllocatorDefault, decodedKey.modulus.data, + decodedKey.modulus.length); + CFDictionarySetValue(dict, CFSTR("_rsam"), modulus); + CFRef exponent = CFDataCreate(kCFAllocatorDefault, decodedKey.pubExponent.data, + decodedKey.pubExponent.length); + CFDictionarySetValue(dict, CFSTR("_rsae"), exponent); + } + } + + result = dict; + + END_SECKEYAPI +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" +static CSSM_DB_NAME_ATTR(kInfoKeyLabel, kSecKeyLabel, (char*) "Label", 0, NULL, BLOB); +#pragma clang diagnostic pop + +static SecKeyRef SecCDSAKeyCopyPublicKey(SecKeyRef privateKey) { + CFErrorRef *error; + BEGIN_SECKEYAPI(SecKeyRef, NULL) + + result = NULL; + KeyItem *key = privateKey->key; + CFRef label = SecCDSAKeyCopyLabel(privateKey); + if (label) { + // Lookup public key in the database. + DbUniqueRecord uniqueId; + SSDb ssDb(dynamic_cast(&(*key->keychain()->database()))); + SSDbCursor dbCursor(ssDb, 1); + dbCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY); + dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, CssmData(CFDataRef(label))); + if (dbCursor->next(NULL, NULL, uniqueId)) { + Item publicKey = key->keychain()->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, uniqueId); + result = reinterpret_cast(publicKey->handle()); + } + } else if (key->publicKey()) { + KeyItem *publicKey = new KeyItem(key->publicKey()); + result = reinterpret_cast(publicKey->handle()); + } + + END_SECKEYAPI +} + +static KeyItem *SecCDSAKeyPrepareParameters(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, + CSSM_ALGORITHMS &baseAlgorithm, CSSM_ALGORITHMS &secondaryAlgorithm, + CSSM_ALGORITHMS &paddingAlgorithm) { + KeyItem *keyItem = key->key; + CSSM_KEYCLASS keyClass = keyItem->key()->header().keyClass(); + baseAlgorithm = keyItem->key()->header().algorithm(); + switch (baseAlgorithm) { + case CSSM_ALGID_RSA: + if ((keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeSign) || + (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeVerify)) { + if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRaw)) { + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_NONE; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw)) { + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1)) { + secondaryAlgorithm = CSSM_ALGID_SHA1; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224)) { + secondaryAlgorithm = CSSM_ALGID_SHA224; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256)) { + secondaryAlgorithm = CSSM_ALGID_SHA256; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384)) { + secondaryAlgorithm = CSSM_ALGID_SHA384; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512)) { + secondaryAlgorithm = CSSM_ALGID_SHA512; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5)) { + secondaryAlgorithm = CSSM_ALGID_MD5; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else { + return NULL; + } + } else if ((keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeDecrypt) || + (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeEncrypt)) { + if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionRaw)) { + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_NONE; + } else if (CFEqual(algorithm, kSecKeyAlgorithmRSAEncryptionPKCS1)) { + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else { + return NULL; + } + } else { + return NULL; + } + break; + case CSSM_ALGID_ECDSA: + if ((keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeSign) || + (keyClass == CSSM_KEYCLASS_PUBLIC_KEY && operation == kSecKeyOperationTypeVerify)) { + if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureRFC4754)) { + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_SIGRAW; + } else if (CFEqual(algorithm, kSecKeyAlgorithmECDSASignatureDigestX962)) { + secondaryAlgorithm = CSSM_ALGID_NONE; + paddingAlgorithm = CSSM_PADDING_PKCS1; + } else { + return NULL; + } + } else if (keyClass == CSSM_KEYCLASS_PRIVATE_KEY && operation == kSecKeyOperationTypeKeyExchange) { + if (CFEqual(algorithm,kSecKeyAlgorithmECDHKeyExchangeStandard) || + CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactor)) { + baseAlgorithm = CSSM_ALGID_ECDH; + } else if (CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1) || + CFEqual(algorithm, kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1)) { + baseAlgorithm = CSSM_ALGID_ECDH_X963_KDF; + } else { + return NULL; + } + } else { + return NULL; + } + break; + default: + MacOSError::throwMe(errSecParam); + } + return keyItem; +} + +static CFDataRef +SecCDSAKeyCopyPaddedPlaintext(SecKeyRef key, CFDataRef plaintext, SecKeyAlgorithm algorithm) { + CFIndex blockSize = key->key->key().header().LogicalKeySizeInBits / 8; + CFIndex plaintextLength = CFDataGetLength(plaintext); + if ((algorithm == kSecKeyAlgorithmRSAEncryptionRaw || algorithm == kSecKeyAlgorithmRSASignatureRaw) + && plaintextLength < blockSize) { + // Pre-pad with zeroes. + CFMutableDataRef result(CFDataCreateMutable(kCFAllocatorDefault, blockSize)); + CFDataSetLength(result, blockSize); + CFDataReplaceBytes(result, CFRangeMake(blockSize - plaintextLength, plaintextLength), + CFDataGetBytePtr(plaintext), plaintextLength); + return result; + } else { + return CFDataRef(CFRetain(plaintext)); + } } +static CFTypeRef SecCDSAKeyCopyOperationResult(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, + CFArrayRef allAlgorithms, SecKeyOperationMode mode, + CFTypeRef in1, CFTypeRef in2, CFErrorRef *error) { + BEGIN_SECKEYAPI(CFTypeRef, kCFNull) + CSSM_ALGORITHMS baseAlgorithm, secondaryAlgorithm, paddingAlgorithm; + KeyItem *keyItem = SecCDSAKeyPrepareParameters(key, operation, algorithm, baseAlgorithm, secondaryAlgorithm, paddingAlgorithm); + if (keyItem == NULL) { + // Operation/algorithm/key combination is not supported. + return kCFNull; + } else if (mode == kSecKeyOperationModeCheckIfSupported) { + // Operation is supported and caller wants to just know that. + return kCFBooleanTrue; + } + + switch (operation) { + case kSecKeyOperationTypeSign: { + CssmClient::Sign signContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm); + signContext.key(keyItem->key()); + signContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault)); + signContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm); + CFRef input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef::check(in1, errSecParam), algorithm); + CssmAutoData signature(signContext.allocator()); + signContext.sign(CssmData(CFDataRef(input)), signature.get()); + result = CFDataCreate(NULL, static_cast(signature.data()), CFIndex(signature.length())); + break; + } + case kSecKeyOperationTypeVerify: { + CssmClient::Verify verifyContext(keyItem->csp(), baseAlgorithm, secondaryAlgorithm); + verifyContext.key(keyItem->key()); + verifyContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, kSecCredentialTypeDefault)); + verifyContext.add(CSSM_ATTRIBUTE_PADDING, paddingAlgorithm); + CFRef input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef::check(in1, errSecParam), algorithm); + verifyContext.verify(CssmData(CFDataRef(input)), CssmData(CFRef::check(in2, errSecParam))); + result = kCFBooleanTrue; + break; + } + case kSecKeyOperationTypeEncrypt: { + CssmClient::Encrypt encryptContext(keyItem->csp(), baseAlgorithm); + encryptContext.key(keyItem->key()); + encryptContext.padding(paddingAlgorithm); + encryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, kSecCredentialTypeDefault)); + CFRef input = SecCDSAKeyCopyPaddedPlaintext(key, CFRef::check(in1, errSecParam), algorithm); + CssmAutoData output(encryptContext.allocator()), remainingData(encryptContext.allocator()); + size_t length = encryptContext.encrypt(CssmData(CFDataRef(input)), output.get(), remainingData.get()); + result = CFDataCreateMutable(kCFAllocatorDefault, output.length() + remainingData.length()); + CFDataAppendBytes(CFMutableDataRef(result), static_cast(output.data()), output.length()); + CFDataAppendBytes(CFMutableDataRef(result), static_cast(remainingData.data()), remainingData.length()); + CFDataSetLength(CFMutableDataRef(result), length); + break; + } + case kSecKeyOperationTypeDecrypt: { + CssmClient::Decrypt decryptContext(keyItem->csp(), baseAlgorithm); + decryptContext.key(keyItem->key()); + decryptContext.padding(paddingAlgorithm); + decryptContext.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault)); + CssmAutoData output(decryptContext.allocator()), remainingData(decryptContext.allocator()); + size_t length = decryptContext.decrypt(CssmData(CFRef::check(in1, errSecParam)), + output.get(), remainingData.get()); + result = CFDataCreateMutable(kCFAllocatorDefault, output.length() + remainingData.length()); + CFDataAppendBytes(CFMutableDataRef(result), static_cast(output.data()), output.length()); + CFDataAppendBytes(CFMutableDataRef(result), static_cast(remainingData.data()), remainingData.length()); + CFDataSetLength(CFMutableDataRef(result), length); + break; + } + case kSecKeyOperationTypeKeyExchange: { + CFIndex requestedLength = 0; + CssmData sharedInfo; + switch (baseAlgorithm) { + case CSSM_ALGID_ECDH: + requestedLength = (keyItem->key().header().LogicalKeySizeInBits + 7) / 8; + break; + case CSSM_ALGID_ECDH_X963_KDF: + CFDictionaryRef params = CFRef::check(in2, errSecParam); + CFTypeRef value = params ? CFDictionaryGetValue(params, kSecKeyKeyExchangeParameterRequestedSize) : NULL; + if (value == NULL || CFGetTypeID(value) != CFNumberGetTypeID() || + !CFNumberGetValue(CFNumberRef(value), kCFNumberCFIndexType, &requestedLength)) { + MacOSError::throwMe(errSecParam); + } + value = CFDictionaryGetValue(params, kSecKeyKeyExchangeParameterSharedInfo); + if (value != NULL && CFGetTypeID(value) == CFDataGetTypeID()) { + sharedInfo = CssmData(CFDataRef(value)); + } + break; + } + + CssmClient::DeriveKey derive(keyItem->csp(), baseAlgorithm, CSSM_ALGID_AES, uint32(requestedLength * 8)); + derive.key(keyItem->key()); + derive.cred(keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DERIVE, kSecCredentialTypeDefault)); + derive.salt(sharedInfo); + CssmData param(CFRef::check(in1, errSecParam)); + Key derivedKey = derive(¶m, KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE)); + + // Export raw data of newly derived key (by wrapping with an empty key). + CssmClient::WrapKey wrapper(keyItem->csp(), CSSM_ALGID_NONE); + Key wrappedKey = wrapper(derivedKey); + result = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)wrappedKey->data(), CFIndex(wrappedKey->length())); + break; + } + default: + break; + } + + END_SECKEYAPI +} + +static Boolean SecCDSAIsEqual(SecKeyRef key1, SecKeyRef key2) { + CFErrorRef *error; + BEGIN_SECKEYAPI(Boolean, false) + + result = key1->key->equal(*key2->key); + + END_SECKEYAPI +} + +const SecKeyDescriptor kSecCDSAKeyDescriptor = { + .version = kSecKeyDescriptorVersion, + .name = "CDSAKey", + + .init = SecCDSAKeyInit, + .destroy = SecCDSAKeyDestroy, + .blockSize = SecCDSAKeyGetBlockSize, + .getAlgorithmID = SecCDSAKeyGetAlgorithmId, + .copyDictionary = SecCDSAKeyCopyAttributeDictionary, + .copyPublic = SecCDSAKeyCopyPublicBytes, + .copyExternalRepresentation = SecCDSAKeyCopyExternalRepresentation, + .copyPublicKey = SecCDSAKeyCopyPublicKey, + .copyOperationResult = SecCDSAKeyCopyOperationResult, + .isEqual = SecCDSAIsEqual, +}; + +namespace Security { + namespace KeychainCore { + SecCFObject *KeyItem::fromSecKeyRef(CFTypeRef ptr) { + if (ptr == NULL || CFGetTypeID(ptr) != SecKeyGetTypeID()) { + return NULL; + } + + SecKeyRef key = static_cast(const_cast(ptr)); + if (key->key_class == &kSecCDSAKeyDescriptor) { + return static_cast(key->key); + } + + if (key->cdsaKey == NULL) { + // Create CDSA key from exported data of existing key. + CFRef keyData = SecKeyCopyExternalRepresentation(key, NULL); + CFRef keyAttributes = SecKeyCopyAttributes(key); + if (keyData && keyAttributes) { + key->cdsaKey = SecKeyCreateFromData(keyAttributes, keyData, NULL); + } + } + + return (key->cdsaKey != NULL) ? key->cdsaKey->key : NULL; + } + + // You need to hold this key's MutexForObject when you run this + void KeyItem::attachSecKeyRef() const { + SecKeyRef key = SecKeyCreate(NULL, &kSecCDSAKeyDescriptor, reinterpret_cast(this), 0, 0); + key->key->mWeakSecKeyRef = key; + } + + } +} + +extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); +Boolean SecKeyIsCDSAKey(SecKeyRef ref) { + return ref->key_class == &kSecCDSAKeyDescriptor; +} + + static OSStatus SecKeyCreatePairInternal( SecKeychainRef keychainRef, CSSM_ALGORITHMS algorithm, @@ -82,24 +809,18 @@ static OSStatus SecKeyCreatePairInternal( { BEGIN_SECAPI - Keychain keychain = Keychain::optional(keychainRef); - SecPointer theAccess(initialAccess ? Access::required(initialAccess) : new Access("")); - SecPointer pubItem, privItem; - - Mutex *keychainMutex = keychain->getKeychainMutex(); - StLock _(*keychainMutex); - - KeyItem::createPair(keychain, - algorithm, - keySizeInBits, - contextHandle, - publicKeyUsage, - publicKeyAttr, - privateKeyUsage, - privateKeyAttr, - theAccess, - pubItem, - privItem); + Keychain keychain; + SecPointer theAccess(initialAccess ? Access::required(initialAccess) : new Access("")); + SecPointer pubItem, privItem; + if (((publicKeyAttr | privateKeyAttr) & CSSM_KEYATTR_PERMANENT) != 0) { + keychain = Keychain::optional(keychainRef); + StLock _(*keychain->getKeychainMutex()); + KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr, + privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem); + } else { + KeyItem::createPair(keychain, algorithm, keySizeInBits, contextHandle, publicKeyUsage, publicKeyAttr, + privateKeyUsage, privateKeyAttr, theAccess, pubItem, privItem); + } // Return the generated keys. if (publicKeyRef) @@ -164,48 +885,12 @@ SecKeyGetAlgorithmID(SecKeyRef keyRef, const CSSM_X509_ALGORITHM_IDENTIFIER **al { BEGIN_SECAPI -#if SECTRUST_OSX - if (!keyRef || (CFGetTypeID(keyRef) != SecKeyGetCFClassTypeID())) - return errSecParam; -#endif SecPointer keyItem(KeyItem::required(keyRef)); Required(algid) = &keyItem->algorithmIdentifier(); END_SECAPI } -/* new for 10.8 */ -CFIndex -SecKeyGetAlgorithmId(SecKeyRef key) -{ -#if SECTRUST_OSX - if (!key) { - return kSecNullAlgorithmID; - } - else if (CFGetTypeID(key) != SecKeyGetCFClassTypeID()) { - return SecKeyGetAlgorithmIdentifier(key); - } - // else fall through, we have a CSSM-based key -#endif - - const CSSM_KEY *cssmKey; - - if (SecKeyGetCSSMKey(key, &cssmKey) != errSecSuccess) - return kSecNullAlgorithmID; - - switch (cssmKey->KeyHeader.AlgorithmId) { - case CSSM_ALGID_RSA: - return kSecRSAAlgorithmID; - case CSSM_ALGID_DSA: - return kSecDSAAlgorithmID; - case CSSM_ALGID_ECDSA: - return kSecECDSAAlgorithmID; - default: - assert(0); /* other algorithms TBA */ - return kSecNullAlgorithmID; - } -} - OSStatus SecKeyGetStrengthInBits(SecKeyRef keyRef, const CSSM_X509_ALGORITHM_IDENTIFIER *algid, unsigned int *strength) { @@ -318,30 +1003,6 @@ SecKeyGenerate( initialAccess, keyRef); } - -/* new in 10.6 */ -/* Create a key from supplied data and parameters */ -SecKeyRef -SecKeyCreate(CFAllocatorRef allocator, - const SecKeyDescriptor *keyClass, - const uint8_t *keyData, - CFIndex keyDataLength, - SecKeyEncoding encoding) -{ - SecKeyRef keyRef = NULL; - OSStatus __secapiresult; - try { - //FIXME: needs implementation - - __secapiresult=errSecSuccess; - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } - return keyRef; -} - /* new in 10.6 */ /* Generate a floating key reference from a CSSM_KEY */ OSStatus @@ -363,7 +1024,7 @@ SecKeyCreateWithCSSMKey(const CSSM_KEY *cssmKey, // Return the generated key. if (keyRef) - *keyRef = item->handle(); + *keyRef = SecKeyCreate(NULL, &kSecCDSAKeyDescriptor, (const uint8_t *)item, 0, 0); END_SECAPI } @@ -658,7 +1319,9 @@ static OSStatus GetKeyParameters(CFDictionaryRef parameters, int keySize, bool i attrs = 0; } - attrs |= CSSM_KEYATTR_PERMANENT; + if (isPermanent) { + attrs |= CSSM_KEYATTR_PERMANENT; + } return errSecSuccess; } @@ -785,11 +1448,26 @@ static OSStatus SetKeyLabelAndTag(SecKeyRef keyRef, CFTypeRef label, CFDataRef t } +static CFTypeRef GetAttributeFromParams(CFDictionaryRef parameters, CFTypeRef attr, CFTypeRef subParams) { + if (subParams != NULL) { + CFDictionaryRef subParamsDict = (CFDictionaryRef)CFDictionaryGetValue(parameters, subParams); + if (subParamsDict != NULL) { + CFTypeRef value = CFDictionaryGetValue(subParamsDict, attr); + if (value != NULL) { + return value; + } + } + } + return CFDictionaryGetValue(parameters, attr); +} + +extern "C" OSStatus SecKeyGeneratePair_ios(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey); /* new in 10.6 */ /* Generate a private/public keypair. */ -OSStatus -SecKeyGeneratePair( +static OSStatus +SecKeyGeneratePairInternal( + bool alwaysPermanent, CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey) @@ -797,8 +1475,25 @@ SecKeyGeneratePair( BEGIN_SECAPI Required(parameters); - Required(publicKey); - Required(privateKey); + Required(publicKey); + Required(privateKey); + + CFTypeRef tokenID = GetAttributeFromParams(parameters, kSecAttrTokenID, NULL); + CFTypeRef noLegacy = GetAttributeFromParams(parameters, kSecAttrNoLegacy, NULL); + CFTypeRef sync = GetAttributeFromParams(parameters, kSecAttrSynchronizable, kSecPrivateKeyAttrs); + CFTypeRef accessControl = GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPrivateKeyAttrs) ?: + GetAttributeFromParams(parameters, kSecAttrAccessControl, kSecPublicKeyAttrs); + CFTypeRef accessGroup = GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPrivateKeyAttrs) ?: + GetAttributeFromParams(parameters, kSecAttrAccessGroup, kSecPublicKeyAttrs); + + // If any of these attributes are present, forward the call to iOS implementation (and create keys in iOS keychain). + if (tokenID != NULL || + (noLegacy != NULL && CFBooleanGetValue((CFBooleanRef)noLegacy)) || + (sync != NULL && CFBooleanGetValue((CFBooleanRef)sync)) || + accessControl != NULL || (accessGroup != NULL && CFEqual(accessGroup, kSecAttrAccessGroupToken))) { + // Generate keys in iOS keychain. + return SecKeyGeneratePair_ios(parameters, publicKey, privateKey); + } CSSM_ALGORITHMS algorithms; uint32 keySizeInBits; @@ -817,62 +1512,49 @@ SecKeyGeneratePair( publicKeyAttributeTagRef, privateKeyUse, privateKeyAttr, privateKeyLabelRef, privateKeyAttributeTagRef, initialAccess); - if (result != errSecSuccess) - { + if (result != errSecSuccess) { return result; } // verify keychain parameter - keychain = NULL; - if (!CFDictionaryGetValueIfPresent(parameters, kSecUseKeychain, (const void **)&keychain)) - keychain = NULL; - else if (SecKeychainGetTypeID() != CFGetTypeID(keychain)) + keychain = (SecKeychainRef)CFDictionaryGetValue(parameters, kSecUseKeychain); + if (keychain != NULL && SecKeychainGetTypeID() != CFGetTypeID(keychain)) { keychain = NULL; + } + + if (alwaysPermanent) { + publicKeyAttr |= CSSM_KEYATTR_PERMANENT; + privateKeyAttr |= CSSM_KEYATTR_PERMANENT; + } // do the key generation result = SecKeyCreatePair(keychain, algorithms, keySizeInBits, 0, publicKeyUse, publicKeyAttr, privateKeyUse, privateKeyAttr, initialAccess, publicKey, privateKey); - if (result != errSecSuccess) - { + if (result != errSecSuccess) { return result; } // set the label and print attributes on the keys - SetKeyLabelAndTag(*publicKey, publicKeyLabelRef, publicKeyAttributeTagRef); - SetKeyLabelAndTag(*privateKey, privateKeyLabelRef, privateKeyAttributeTagRef); + SetKeyLabelAndTag(*publicKey, publicKeyLabelRef, publicKeyAttributeTagRef); + SetKeyLabelAndTag(*privateKey, privateKeyLabelRef, privateKeyAttributeTagRef); return result; END_SECAPI } -/* new in 10.6 */ OSStatus -SecKeyRawSign( - SecKeyRef key, - SecPadding padding, - const uint8_t *dataToSign, - size_t dataToSignLen, - uint8_t *sig, - size_t *sigLen) -{ - BEGIN_SECAPI - - Required(key); - SecPointer keyItem(KeyItem::required(key)); - CSSM_DATA dataInput; - - dataInput.Data = (uint8_t*) dataToSign; - dataInput.Length = dataToSignLen; - - CSSM_DATA output; - output.Data = sig; - output.Length = *sigLen; - - const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault); - - keyItem->RawSign(padding, dataInput, credentials, output); - *sigLen = output.Length; +SecKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey) { + return SecKeyGeneratePairInternal(true, parameters, publicKey, privateKey); +} - END_SECAPI +SecKeyRef +SecKeyCreateRandomKey(CFDictionaryRef parameters, CFErrorRef *error) { + SecKeyRef privateKey = NULL, publicKey = NULL; + OSStatus status = SecKeyGeneratePairInternal(false, parameters, &publicKey, &privateKey); + SecError(status, error, CFSTR("failed to generate asymmetric keypair")); + if (publicKey != NULL) { + CFRelease(publicKey); + } + return privateKey; } OSStatus SecKeyRawVerifyOSX( @@ -886,146 +1568,6 @@ OSStatus SecKeyRawVerifyOSX( return SecKeyRawVerify(key,padding,signedData,signedDataLen,sig,sigLen); } -/* new in 10.6 */ -OSStatus -SecKeyRawVerify( - SecKeyRef key, - SecPadding padding, - const uint8_t *signedData, - size_t signedDataLen, - const uint8_t *sig, - size_t sigLen) -{ - BEGIN_SECAPI - - Required(key); - - SecPointer keyItem(KeyItem::required(key)); - CSSM_DATA dataInput; - - dataInput.Data = (uint8_t*) signedData; - dataInput.Length = signedDataLen; - - CSSM_DATA signature; - signature.Data = (uint8_t*) sig; - signature.Length = sigLen; - - const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ANY, kSecCredentialTypeDefault); - - keyItem->RawVerify(padding, dataInput, credentials, signature); - - END_SECAPI -} - -/* new in 10.6 */ -OSStatus -SecKeyEncrypt( - SecKeyRef key, - SecPadding padding, - const uint8_t *plainText, - size_t plainTextLen, - uint8_t *cipherText, - size_t *cipherTextLen) -{ - BEGIN_SECAPI - - SecPointer keyItem(KeyItem::required(key)); - CSSM_DATA inData, outData; - inData.Data = (uint8*) plainText; - inData.Length = plainTextLen; - outData.Data = cipherText; - outData.Length = *cipherTextLen; - - const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_ENCRYPT, kSecCredentialTypeDefault); - - keyItem->Encrypt(padding, inData, credentials, outData); - *cipherTextLen = outData.Length; - - END_SECAPI -} - -/* new in 10.6 */ -OSStatus -SecKeyDecrypt( - SecKeyRef key, /* Private key */ - SecPadding padding, /* kSecPaddingNone, kSecPaddingPKCS1, kSecPaddingOAEP */ - const uint8_t *cipherText, - size_t cipherTextLen, /* length of cipherText */ - uint8_t *plainText, - size_t *plainTextLen) /* IN/OUT */ -{ - BEGIN_SECAPI - - SecPointer keyItem(KeyItem::required(key)); - CSSM_DATA inData, outData; - inData.Data = (uint8*) cipherText; - inData.Length = cipherTextLen; - outData.Data = plainText; - outData.Length = *plainTextLen; - - const AccessCredentials* credentials = keyItem->getCredentials(CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeDefault); - - keyItem->Decrypt(padding, inData, credentials, outData); - *plainTextLen = outData.Length; - - END_SECAPI -} - -/* new in 10.6 */ -size_t -SecKeyGetBlockSize(SecKeyRef key) -{ - size_t blockSize = 0; - OSStatus __secapiresult; - try { - CSSM_KEY cssmKey = KeyItem::required(key)->key(); - switch(cssmKey.KeyHeader.AlgorithmId) - { - case CSSM_ALGID_RSA: - case CSSM_ALGID_DSA: - blockSize = cssmKey.KeyHeader.LogicalKeySizeInBits / 8; - break; - case CSSM_ALGID_ECDSA: - { - /* Block size is up to 9 bytes of DER encoding for sequence of 2 integers, - * plus both coordinates for the point used */ - #define ECDSA_KEY_SIZE_IN_BYTES(bits) (((bits) + 7) / 8) - #define ECDSA_MAX_COORD_SIZE_IN_BYTES(n) (ECDSA_KEY_SIZE_IN_BYTES(n) + 1) - size_t coordSize = ECDSA_MAX_COORD_SIZE_IN_BYTES(cssmKey.KeyHeader.LogicalKeySizeInBits); - assert(coordSize < 256); /* size must fit in a byte for DER */ - size_t coordDERLen = (coordSize > 127) ? 2 : 1; - size_t coordLen = 1 + coordDERLen + coordSize; - - size_t pointSize = 2 * coordLen; - assert(pointSize < 256); /* size must fit in a byte for DER */ - size_t pointDERLen = (pointSize > 127) ? 2 : 1; - size_t pointLen = 1 + pointDERLen + pointSize; - - blockSize = pointLen; - } - break; - case CSSM_ALGID_AES: - blockSize = 16; /* all AES keys use 128-bit blocks */ - break; - case CSSM_ALGID_DES: - case CSSM_ALGID_3DES_3KEY: - blockSize = 8; /* all DES keys use 64-bit blocks */ - break; - default: - assert(0); /* some other key algorithm */ - blockSize = 16; /* FIXME: revisit this */ - break; - } - __secapiresult=errSecSuccess; - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } - return blockSize; -} - - /* M4 Additions */ @@ -1310,14 +1852,19 @@ SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef * memset(&iparam, 0, sizeof(iparam)); iparam.keyUsage = keyUsage; + CFRef data; SecExternalItemType itype; switch (keyClass) { case CSSM_KEYCLASS_PRIVATE_KEY: itype = kSecItemTypePrivateKey; break; - case CSSM_KEYCLASS_PUBLIC_KEY: + case CSSM_KEYCLASS_PUBLIC_KEY: { itype = kSecItemTypePublicKey; - break; + // Public key import expects public key in SubjPublicKey X509 format. We want to accept both bare and x509 format, + // so we have to detect bare format here and extend to full X509 if detected. + data.take(SecCDSAKeyCopyPublicKeyDataWithSubjectInfo(algorithm, keySizeInBits, keyData)); + break; + } case CSSM_KEYCLASS_SESSION_KEY: itype = kSecItemTypeSessionKey; break; @@ -1328,7 +1875,7 @@ SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef * CFMutableArrayRef ka = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // NOTE: if we had a way to specify values other then kSecFormatUnknown we might be more useful. - crtn = impExpImportRawKey(keyData, kSecFormatUnknown, itype, algorithm, NULL, cspHandle, 0, NULL, NULL, ka); + crtn = impExpImportRawKey(data ? CFDataRef(data) : keyData, kSecFormatUnknown, itype, algorithm, NULL, cspHandle, 0, NULL, NULL, ka); if (crtn == CSSM_OK && CFArrayGetCount((CFArrayRef)ka)) { SecKeyRef sk = (SecKeyRef)CFArrayGetValueAtIndex((CFArrayRef)ka, 0); CFRetain(sk); @@ -1483,806 +2030,3 @@ SecKeyUnwrapSymmetric(CFDataRef *keyToUnwrap, SecKeyRef unwrappingKey, CFDiction *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, errSecUnimplemented, NULL); return NULL; } - - -/* iOS SecKey shim functions */ - -#define MAX_DIGEST_LEN (CC_SHA512_DIGEST_LENGTH) - -/* Currently length of SHA512 oid + 1 */ -#define MAX_OID_LEN (10) - -#define DER_MAX_DIGEST_INFO_LEN (10 + MAX_DIGEST_LEN + MAX_OID_LEN) - -/* Encode the digestInfo header into digestInfo and return the offset from - digestInfo at which to put the actual digest. Returns 0 if digestInfo - won't fit within digestInfoLength bytes. - - 0x30, topLen, - 0x30, algIdLen, - 0x06, oid.Len, oid.Data, - 0x05, 0x00 - 0x04, digestLen - digestData - */ -static size_t DEREncodeDigestInfoPrefix(const SecAsn1Oid *oid, - size_t digestLength, - uint8_t *digestInfo, - size_t digestInfoLength) -{ - size_t algIdLen = oid->Length + 4; - size_t topLen = algIdLen + digestLength + 4; - size_t totalLen = topLen + 2; - - if (totalLen > digestInfoLength) { - return 0; - } - - size_t ix = 0; - digestInfo[ix++] = (SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED); - digestInfo[ix++] = topLen; - digestInfo[ix++] = (SEC_ASN1_SEQUENCE | SEC_ASN1_CONSTRUCTED); - digestInfo[ix++] = algIdLen; - digestInfo[ix++] = SEC_ASN1_OBJECT_ID; - digestInfo[ix++] = oid->Length; - memcpy(&digestInfo[ix], oid->Data, oid->Length); - ix += oid->Length; - digestInfo[ix++] = SEC_ASN1_NULL; - digestInfo[ix++] = 0; - digestInfo[ix++] = SEC_ASN1_OCTET_STRING; - digestInfo[ix++] = digestLength; - - return ix; -} - -static OSStatus SecKeyGetDigestInfo(SecKeyRef key, const SecAsn1AlgId *algId, - const uint8_t *data, size_t dataLen, bool digestData, - uint8_t *digestInfo, size_t *digestInfoLen /* IN/OUT */) -{ - unsigned char *(*digestFcn)(const void *, CC_LONG, unsigned char *); - CFIndex keyAlgID = kSecNullAlgorithmID; - const SecAsn1Oid *digestOid; - size_t digestLen; - size_t offset = 0; - - /* Since these oids all have the same prefix, use switch. */ - if ((algId->algorithm.Length == CSSMOID_RSA.Length) && - !memcmp(algId->algorithm.Data, CSSMOID_RSA.Data, - algId->algorithm.Length - 1)) { - keyAlgID = kSecRSAAlgorithmID; - switch (algId->algorithm.Data[algId->algorithm.Length - 1]) { -#if 0 - case 2: /* oidMD2WithRSA */ - digestFcn = CC_MD2; - digestLen = CC_MD2_DIGEST_LENGTH; - digestOid = &CSSMOID_MD2; - break; - case 3: /* oidMD4WithRSA */ - digestFcn = CC_MD4; - digestLen = CC_MD4_DIGEST_LENGTH; - digestOid = &CSSMOID_MD4; - break; - case 4: /* oidMD5WithRSA */ - digestFcn = CC_MD5; - digestLen = CC_MD5_DIGEST_LENGTH; - digestOid = &CSSMOID_MD5; - break; -#endif /* 0 */ - case 5: /* oidSHA1WithRSA */ - digestFcn = CC_SHA1; - digestLen = CC_SHA1_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA1; - break; - case 11: /* oidSHA256WithRSA */ - digestFcn = CC_SHA256; - digestLen = CC_SHA256_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA256; - break; - case 12: /* oidSHA384WithRSA */ - /* pkcs1 12 */ - digestFcn = CC_SHA384; - digestLen = CC_SHA384_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA384; - break; - case 13: /* oidSHA512WithRSA */ - digestFcn = CC_SHA512; - digestLen = CC_SHA512_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA512; - break; - case 14: /* oidSHA224WithRSA */ - digestFcn = CC_SHA224; - digestLen = CC_SHA224_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA224; - break; - default: - secdebug("key", "unsupported rsa signature algorithm"); - return errSecUnsupportedAlgorithm; - } - } else if ((algId->algorithm.Length == CSSMOID_ECDSA_WithSHA224.Length) && - !memcmp(algId->algorithm.Data, CSSMOID_ECDSA_WithSHA224.Data, - algId->algorithm.Length - 1)) { - keyAlgID = kSecECDSAAlgorithmID; - switch (algId->algorithm.Data[algId->algorithm.Length - 1]) { - case 1: /* oidSHA224WithECDSA */ - digestFcn = CC_SHA224; - digestLen = CC_SHA224_DIGEST_LENGTH; - break; - case 2: /* oidSHA256WithECDSA */ - digestFcn = CC_SHA256; - digestLen = CC_SHA256_DIGEST_LENGTH; - break; - case 3: /* oidSHA384WithECDSA */ - /* pkcs1 12 */ - digestFcn = CC_SHA384; - digestLen = CC_SHA384_DIGEST_LENGTH; - break; - case 4: /* oidSHA512WithECDSA */ - digestFcn = CC_SHA512; - digestLen = CC_SHA512_DIGEST_LENGTH; - break; - default: - secdebug("key", "unsupported ecdsa signature algorithm"); - return errSecUnsupportedAlgorithm; - } - } else if (SecAsn1OidCompare(&algId->algorithm, &CSSMOID_ECDSA_WithSHA1)) { - keyAlgID = kSecECDSAAlgorithmID; - digestFcn = CC_SHA1; - digestLen = CC_SHA1_DIGEST_LENGTH; - } else if (SecAsn1OidCompare(&algId->algorithm, &CSSMOID_SHA1)) { - digestFcn = CC_SHA1; - digestLen = CC_SHA1_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA1; - } else if ((algId->algorithm.Length == CSSMOID_SHA224.Length) && - !memcmp(algId->algorithm.Data, CSSMOID_SHA224.Data, algId->algorithm.Length - 1)) - { - switch (algId->algorithm.Data[algId->algorithm.Length - 1]) { - case 4: /* OID_SHA224 */ - digestFcn = CC_SHA224; - digestLen = CC_SHA224_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA224; - break; - case 1: /* OID_SHA256 */ - digestFcn = CC_SHA256; - digestLen = CC_SHA256_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA256; - break; - case 2: /* OID_SHA384 */ - /* pkcs1 12 */ - digestFcn = CC_SHA384; - digestLen = CC_SHA384_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA384; - break; - case 3: /* OID_SHA512 */ - digestFcn = CC_SHA512; - digestLen = CC_SHA512_DIGEST_LENGTH; - digestOid = &CSSMOID_SHA512; - break; - default: - secdebug("key", "unsupported sha-2 signature algorithm"); - return errSecUnsupportedAlgorithm; - } - } else if (SecAsn1OidCompare(&algId->algorithm, &CSSMOID_MD5)) { - digestFcn = CC_MD5; - digestLen = CC_MD5_DIGEST_LENGTH; - digestOid = &CSSMOID_MD5; - } else { - secdebug("key", "unsupported digesting algorithm"); - return errSecUnsupportedAlgorithm; - } - - /* check key is appropriate for signature (superfluous for digest only oid) */ - { - CFIndex supportedKeyAlgID = kSecNullAlgorithmID; - #if TARGET_OS_EMBEDDED - supportedKeyAlgID = SecKeyGetAlgorithmID(key); - #else - const CSSM_KEY* temporaryKey; - SecKeyGetCSSMKey(key, &temporaryKey); - CSSM_ALGORITHMS tempAlgorithm = temporaryKey->KeyHeader.AlgorithmId; - if (CSSM_ALGID_RSA == tempAlgorithm) { - supportedKeyAlgID = kSecRSAAlgorithmID; - } else if (CSSM_ALGID_ECDSA == tempAlgorithm) { - supportedKeyAlgID = kSecECDSAAlgorithmID; - } - #endif - - if (keyAlgID == kSecNullAlgorithmID) { - keyAlgID = supportedKeyAlgID; - } - else if (keyAlgID != supportedKeyAlgID) { - return errSecUnsupportedAlgorithm; - } - } - - switch(keyAlgID) { - case kSecRSAAlgorithmID: - offset = DEREncodeDigestInfoPrefix(digestOid, digestLen, - digestInfo, *digestInfoLen); - if (!offset) - return errSecBufferTooSmall; - break; - case kSecDSAAlgorithmID: - if (digestOid != &CSSMOID_SHA1) - return errSecUnsupportedAlgorithm; - break; - case kSecECDSAAlgorithmID: - break; - default: - secdebug("key", "unsupported signature algorithm"); - return errSecUnsupportedAlgorithm; - } - - if (digestData) { - if(dataLen>UINT32_MAX) /* Check for overflow with CC_LONG cast */ - return errSecParam; - digestFcn(data, (CC_LONG)dataLen, &digestInfo[offset]); - *digestInfoLen = offset + digestLen; - } else { - if (dataLen != digestLen) - return errSecParam; - memcpy(&digestInfo[offset], data, dataLen); - *digestInfoLen = offset + dataLen; - } - - return errSecSuccess; -} - -OSStatus SecKeyVerifyDigest( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *digestData, /* signature over this digest */ - size_t digestDataLen, /* length of dataToDigest */ - const uint8_t *sig, /* signature to verify */ - size_t sigLen) /* length of sig */ -{ - size_t digestInfoLength = DER_MAX_DIGEST_INFO_LEN; - uint8_t digestInfo[digestInfoLength]; - OSStatus status; - - status = SecKeyGetDigestInfo(key, algId, digestData, digestDataLen, false /* data is digest */, - digestInfo, &digestInfoLength); - if (status) - return status; - return SecKeyRawVerify(key, kSecPaddingPKCS1, - digestInfo, digestInfoLength, sig, sigLen); -} - -OSStatus SecKeySignDigest( - SecKeyRef key, /* Private key */ - const SecAsn1AlgId *algId, /* algorithm oid/params */ - const uint8_t *digestData, /* signature over this digest */ - size_t digestDataLen, /* length of digestData */ - uint8_t *sig, /* signature, RETURNED */ - size_t *sigLen) /* IN/OUT */ -{ - size_t digestInfoLength = DER_MAX_DIGEST_INFO_LEN; - uint8_t digestInfo[digestInfoLength]; - OSStatus status; - - status = SecKeyGetDigestInfo(key, algId, digestData, digestDataLen, false, - digestInfo, &digestInfoLength); - if (status) - return status; - return SecKeyRawSign(key, kSecPaddingPKCS1, - digestInfo, digestInfoLength, sig, sigLen); -} - -/* It's debatable whether this belongs here or in the ssl code since the - curve values come from a tls related rfc4492. */ -SecECNamedCurve SecECKeyGetNamedCurve(SecKeyRef key) -{ - try { - SecPointer keyItem(KeyItem::required(key)); - switch (keyItem->key().header().LogicalKeySizeInBits) { -#if 0 - case 192: - return kSecECCurveSecp192r1; - case 224: - return kSecECCurveSecp224r1; -#endif - case 256: - return kSecECCurveSecp256r1; - case 384: - return kSecECCurveSecp384r1; - case 521: - return kSecECCurveSecp521r1; - } - } - catch (...) {} - return kSecECCurveNone; -} - -static inline CFDataRef _CFDataCreateReferenceFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) -{ - return CFDataCreateWithBytesNoCopy(allocator, - CFDataGetBytePtr(sourceData) + range.location, range.length, - kCFAllocatorNull); -} - -static inline CFDataRef _CFDataCreateCopyFromRange(CFAllocatorRef allocator, CFDataRef sourceData, CFRange range) -{ - return CFDataCreate(allocator, CFDataGetBytePtr(sourceData) + range.location, range.length); -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" -static inline bool _CFDataEquals(CFDataRef left, CFDataRef right) -{ - return (left != NULL) && - (right != NULL) && - (CFDataGetLength(left) == CFDataGetLength(right)) && - (0 == memcmp(CFDataGetBytePtr(left), CFDataGetBytePtr(right), (size_t)CFDataGetLength(left))); -} -#pragma clang diagnostic pop - -#if ECDSA_DEBUG -void secdump(const unsigned char *data, unsigned long len) -{ - unsigned long i; - char s[128]; - char t[32]; - s[0]=0; - for(i=0;imodulusLength; - DERSize e_size = params->exponentLength; - const DERSize seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) + - DERLengthOfItem(ASN1_INTEGER, e_size); - const DERSize result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size); - DERSize r_size, remaining_size = result_size; - DERReturn drtn; - - CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); - if (pkcs1 == NULL) { - return NULL; - } - CFDataSetLength(pkcs1, result_size); - uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); - - *bytes++ = ASN1_CONSTR_SEQUENCE; - remaining_size--; - r_size = 4; - drtn = DEREncodeLength(seq_size, bytes, &r_size); - if (r_size <= remaining_size) { - bytes += r_size; - remaining_size -= r_size; - } - r_size = remaining_size; - drtn = DEREncodeItem(ASN1_INTEGER, m_size, (const DERByte *)params->modulus, (DERByte *)bytes, &r_size); - if (r_size <= remaining_size) { - bytes += r_size; - remaining_size -= r_size; - } - r_size = remaining_size; - drtn = DEREncodeItem(ASN1_INTEGER, e_size, (const DERByte *)params->exponent, (DERByte *)bytes, &r_size); - - pubKeyData = pkcs1; - - } else { - /* unsupported encoding */ - return NULL; - } - SecKeyRef publicKey = SecKeyCreateFromPublicData(allocator, kSecRSAAlgorithmID, pubKeyData); - CFRelease(pubKeyData); - return publicKey; -} - -#if !TARGET_OS_EMBEDDED -// -// Given a CSSM public key, copy its modulus and/or exponent data. -// Caller is responsible for releasing the returned CFDataRefs. -// -static -OSStatus _SecKeyCopyRSAPublicModulusAndExponent(SecKeyRef key, CFDataRef *modulus, CFDataRef *exponent) -{ - const CSSM_KEY *pubKey; - const CSSM_KEYHEADER *hdr; - CSSM_DATA pubKeyBlob; - OSStatus result; - - result = SecKeyGetCSSMKey(key, &pubKey); - if(result != errSecSuccess) { - return result; - } - hdr = &pubKey->KeyHeader; - if(hdr->KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) { - return errSSLInternal; - } - if(hdr->AlgorithmId != CSSM_ALGID_RSA) { - return errSSLInternal; - } - switch(hdr->BlobType) { - case CSSM_KEYBLOB_RAW: - pubKeyBlob.Length = pubKey->KeyData.Length; - pubKeyBlob.Data = pubKey->KeyData.Data; - break; - case CSSM_KEYBLOB_REFERENCE: - // FIXME: currently SSL only uses raw public keys, obtained from the CL - default: - return errSSLInternal; - } - assert(hdr->BlobType == CSSM_KEYBLOB_RAW); - // at this point we should have a PKCS1-encoded blob - - DERItem keyItem = {(DERByte *)pubKeyBlob.Data, pubKeyBlob.Length}; - DERRSAPubKeyPKCS1 decodedKey; - if(DERParseSequence(&keyItem, DERNumRSAPubKeyPKCS1ItemSpecs, - DERRSAPubKeyPKCS1ItemSpecs, - &decodedKey, sizeof(decodedKey)) != DR_Success) { - return errSecDecode; - } - if(modulus) { - *modulus = CFDataCreate(kCFAllocatorDefault, decodedKey.modulus.data, decodedKey.modulus.length); - if(*modulus == NULL) { - return errSecDecode; - } - } - if(exponent) { - *exponent = CFDataCreate(kCFAllocatorDefault, decodedKey.pubExponent.data, decodedKey.pubExponent.length); - if(*exponent == NULL) { - return errSecDecode; - } - } - - return errSecSuccess; -} -#endif /* !TARGET_OS_EMBEDDED */ - -CFDataRef SecKeyCopyModulus(SecKeyRef key) -{ -#if TARGET_OS_EMBEDDED - ccrsa_pub_ctx_t pubkey; - pubkey.pub = key->key; - - size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey)); - - CFAllocatorRef allocator = CFGetAllocator(key); - CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size); - - if (modulusData == NULL) - return NULL; - - CFDataSetLength(modulusData, m_size); - - ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData)); -#else - CFDataRef modulusData; - OSStatus status = _SecKeyCopyRSAPublicModulusAndExponent(key, &modulusData, NULL); - if(status != errSecSuccess) { - modulusData = NULL; - } -#endif - - return modulusData; -} - -CFDataRef SecKeyCopyExponent(SecKeyRef key) -{ -#if TARGET_OS_EMBEDDED - ccrsa_pub_ctx_t pubkey; - pubkey.pub = key->key; - - size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey)); - - CFAllocatorRef allocator = CFGetAllocator(key); - CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size); - - if (exponentData == NULL) - return NULL; - - CFDataSetLength(exponentData, e_size); - - ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, CFDataGetMutableBytePtr(exponentData)); -#else - CFDataRef exponentData; - OSStatus status = _SecKeyCopyRSAPublicModulusAndExponent(key, NULL, &exponentData); - if(status != errSecSuccess) { - exponentData = NULL; - } -#endif - - return exponentData; -} - -SecKeyRef SecKeyCreatePublicFromPrivate(SecKeyRef privateKey) { - OSStatus status = errSecParam; - - CFDataRef serializedPublic = NULL; - - status = SecKeyCopyPublicBytes(privateKey, &serializedPublic); - if ((status == errSecSuccess) && (serializedPublic != NULL)) { - SecKeyRef publicKeyRef = SecKeyCreateFromPublicData(kCFAllocatorDefault, SecKeyGetAlgorithmId(privateKey), serializedPublic); - CFRelease(serializedPublic); - if (publicKeyRef != NULL) { - return publicKeyRef; - } - } - - const void *keys[] = { kSecClass, kSecValueRef, kSecReturnAttributes }; - const void *values[] = { kSecClassKey, privateKey, kCFBooleanTrue }; - CFDictionaryRef query= CFDictionaryCreate(NULL, keys, values, - (sizeof(values) / sizeof(*values)), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFTypeRef foundItem = NULL; - status = SecItemCopyMatching(query, &foundItem); - - if (status == errSecSuccess) { - if (CFGetTypeID(foundItem) == CFDictionaryGetTypeID()) { - CFMutableDictionaryRef query2 = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(query2, kSecClass, kSecClassKey); - CFDictionaryAddValue(query2, kSecAttrKeyClass, kSecAttrKeyClassPublic); - CFDictionaryAddValue(query2, kSecAttrApplicationLabel, CFDictionaryGetValue((CFDictionaryRef)foundItem, kSecAttrApplicationLabel)); - CFDictionaryAddValue(query2, kSecReturnRef, kCFBooleanTrue); - - CFTypeRef foundKey = NULL; - status = SecItemCopyMatching(query2, &foundKey); - if (status == errSecSuccess) { - if (CFGetTypeID(foundKey) == SecKeyGetTypeID()) { - CFRelease(query); - CFRelease(query2); - CFRelease(foundItem); - return (SecKeyRef)foundKey; - } else { - status = errSecItemNotFound; - } - } - CFRelease(query2); - - } else { - status = errSecItemNotFound; - } - CFRelease(foundItem); - } - - CFRelease(query); - return NULL; -} - diff --git a/OSX/libsecurity_keychain/lib/SecKey.h b/OSX/libsecurity_keychain/lib/SecKey.h index 5ac4080d..28b30bec 100644 --- a/OSX/libsecurity_keychain/lib/SecKey.h +++ b/OSX/libsecurity_keychain/lib/SecKey.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #if defined(__cplusplus) @@ -264,7 +265,7 @@ CFTypeID SecKeyGetTypeID(void) @discussion This API is deprecated for 10.7. Please use the SecKeyGeneratePair API instead. */ OSStatus SecKeyCreatePair( - SecKeychainRef __nullable keychainRef, + SecKeychainRef _Nullable keychainRef, CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CSSM_CC_HANDLE contextHandle, @@ -272,9 +273,9 @@ OSStatus SecKeyCreatePair( uint32 publicKeyAttr, CSSM_KEYUSE privateKeyUsage, uint32 privateKeyAttr, - SecAccessRef __nullable initialAccess, - SecKeyRef* __nullable CF_RETURNS_RETAINED publicKey, - SecKeyRef* __nullable CF_RETURNS_RETAINED privateKey) + SecAccessRef _Nullable initialAccess, + SecKeyRef* _Nullable CF_RETURNS_RETAINED publicKey, + SecKeyRef* _Nullable CF_RETURNS_RETAINED privateKey) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /*! @@ -292,14 +293,14 @@ OSStatus SecKeyCreatePair( @discussion This API is deprecated for 10.7. Please use the SecKeyGenerateSymmetric API instead. */ OSStatus SecKeyGenerate( - SecKeychainRef __nullable keychainRef, + SecKeychainRef _Nullable keychainRef, CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CSSM_CC_HANDLE contextHandle, CSSM_KEYUSE keyUsage, uint32 keyAttr, - SecAccessRef __nullable initialAccess, - SecKeyRef* __nullable CF_RETURNS_RETAINED keyRef) + SecAccessRef _Nullable initialAccess, + SecKeyRef* _Nullable CF_RETURNS_RETAINED keyRef) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /*! @@ -310,7 +311,7 @@ OSStatus SecKeyGenerate( @result A result code. See "Security Error Codes" (SecBase.h). @discussion The CSSM_KEY is valid until the key item reference is released. This API is deprecated in 10.7. Its use should no longer be needed. */ -OSStatus SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY * __nullable * __nonnull cssmKey) +OSStatus SecKeyGetCSSMKey(SecKeyRef key, const CSSM_KEY * _Nullable * __nonnull cssmKey) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;; /*! @@ -337,7 +338,7 @@ OSStatus SecKeyGetCredentials( SecKeyRef keyRef, CSSM_ACL_AUTHORIZATION_TAG operation, SecCredentialType credentialType, - const CSSM_ACCESS_CREDENTIALS * __nullable * __nonnull outCredentials) + const CSSM_ACCESS_CREDENTIALS * _Nullable * __nonnull outCredentials) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; /*! @@ -378,7 +379,7 @@ size_t SecKeyGetBlockSize(SecKeyRef key) * kSecAttrLabel (a user-visible label whose value is a CFStringRef, e.g. "My App's Encryption Key") * kSecAttrApplicationLabel (a label defined by your application, whose - value is a CFStringRef and which can be used to find this key in a + value is a CFDataRef and which can be used to find this key in a subsequent call to SecItemCopyMatching, e.g. "ID-1234567890-9876-0151") To specify the generated key's access control settings, set this key: @@ -393,7 +394,7 @@ size_t SecKeyGetBlockSize(SecKeyRef key) * kSecAttrCanUnwrap (defaults to true if not explicitly specified) */ -__nullable +_Nullable SecKeyRef SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); @@ -422,7 +423,7 @@ SecKeyRef SecKeyGenerateSymmetric(CFDictionaryRef parameters, CFErrorRef *error) * kSecAttrCanUnwrap (defaults to true if not explicitly specified) */ -__nullable +_Nullable SecKeyRef SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); @@ -467,7 +468,7 @@ SecKeyRef SecKeyCreateFromData(CFDictionaryRef parameters, */ OSStatus SecKeyGeneratePair(CFDictionaryRef parameters, - SecKeyRef * __nullable CF_RETURNS_RETAINED publicKey, SecKeyRef * __nullable CF_RETURNS_RETAINED privateKey) + SecKeyRef * _Nullable CF_RETURNS_RETAINED publicKey, SecKeyRef * _Nullable CF_RETURNS_RETAINED privateKey) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); /*! @@ -488,7 +489,6 @@ typedef void (^SecKeyGeneratePairBlock)(SecKeyRef publicKey, SecKeyRef privateKe @param parameters A dictionary containing one or more key-value pairs. @param deliveryQueue A dispatch queue to be used to deliver the results. @param result A callback function to result when the operation has completed. - @result On success the function returns NULL. @discussion In order to generate a keypair the parameters dictionary must at least contain the following keys: @@ -555,7 +555,7 @@ void SecKeyGeneratePairAsync(CFDictionaryRef parameters, error parameter contains the reason. */ -__nullable +_Nullable CF_RETURNS_RETAINED SecKeyRef SecKeyDeriveFromPassword(CFStringRef password, CFDictionaryRef parameters, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); @@ -576,7 +576,7 @@ SecKeyRef SecKeyDeriveFromPassword(CFStringRef password, * kSecSalt - a CFData for the salt value for the encrypt. */ -__nullable +_Nullable CFDataRef SecKeyWrapSymmetric(SecKeyRef keyToWrap, SecKeyRef wrappingKey, CFDictionaryRef parameters, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); @@ -597,11 +597,660 @@ CFDataRef SecKeyWrapSymmetric(SecKeyRef keyToWrap, * kSecSalt - a CFData for the salt value for the decrypt. */ -__nullable -SecKeyRef SecKeyUnwrapSymmetric(CFDataRef __nullable * __nonnull keyToUnwrap, +_Nullable +SecKeyRef SecKeyUnwrapSymmetric(CFDataRef _Nullable * __nonnull keyToUnwrap, SecKeyRef unwrappingKey, CFDictionaryRef parameters, CFErrorRef *error) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +/*! + @function SecKeyCreateRandomKey + @abstract Generates a new public/private key pair. + @param parameters A dictionary containing one or more key-value pairs. + See the discussion sections below for a complete overview of options. + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @return Newly generated private key. To get associated public key, use SecKeyCopyPublicKey(). + @discussion In order to generate a keypair the parameters dictionary must + at least contain the following keys: + + * kSecAttrKeyType with a value being kSecAttrKeyTypeRSA or any other + kSecAttrKeyType defined in SecItem.h + * kSecAttrKeySizeInBits with a value being a CFNumberRef or CFStringRef + containing the requested key size in bits. Example sizes for RSA + keys are: 512, 768, 1024, 2048. + + The values below may be set either in the top-level dictionary or in a + dictionary that is the value of the kSecPrivateKeyAttrs or + kSecPublicKeyAttrs key in the top-level dictionary. Setting these + attributes explicitly will override the defaults below. See SecItem.h + for detailed information on these attributes including the types of + the values. + + * kSecAttrLabel default NULL + * kSecAttrIsPermanent if this key is present and has a Boolean value of true, + the key or key pair will be added to the default keychain. + * kSecAttrTokenID if this key should be generated on specified token. This + attribute can contain CFStringRef and can be present only in the top-level + parameters dictionary. + * kSecAttrApplicationTag default NULL + * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits + * kSecAttrCanEncrypt default false for private keys, true for public keys + * kSecAttrCanDecrypt default true for private keys, false for public keys + * kSecAttrCanDerive default true + * kSecAttrCanSign default true for private keys, false for public keys + * kSecAttrCanVerify default false for private keys, true for public keys + * kSecAttrCanWrap default false for private keys, true for public keys + * kSecAttrCanUnwrap default true for private keys, false for public keys + */ +SecKeyRef _Nullable SecKeyCreateRandomKey(CFDictionaryRef parameters, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCreateWithData + @abstract Create a SecKey from a well-defined external representation. + @param keyData CFData representing the key. The format of the data depends on the type of key being created. + @param attributes Dictionary containing attributes describing the key to be imported. The keys in this dictionary + are kSecAttr* constants from SecItem.h. Mandatory attributes are: + * kSecAttrKeyType + * kSecAttrKeyClass + * kSecAttrKeySizeInBits + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @result A SecKey object representing the key, or NULL on failure. + @discussion This function does not add keys to any keychain, but the SecKey object it returns can be added + to keychain using the SecItemAdd function. + The requested data format depend on the type of key (kSecAttrKeyType) being created: + * kSecAttrKeyTypeRSA PKCS#1 format + * kSecAttrKeyTypeECSECPrimeRandom SEC1 format (www.secg.org) + */ +SecKeyRef _Nullable SecKeyCreateWithData(CFDataRef keyData, CFDictionaryRef attributes, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCopyExternalRepresentation + @abstract Create an external representation for the given key suitable for the key's type. + @param key The key to be exported. + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @result A CFData representing the key in a format suitable for that key type. + @discussion This function may fail if the key is not exportable (e.g., bound to a smart card or Secure Enclave). + The format in which the key will be exported depends on the type of key: + * kSecAttrKeyTypeRSA PKCS#1 format + * kSecAttrKeyTypeECSECPrimeRandom SEC1 format (www.secg.org) + */ +CFDataRef _Nullable SecKeyCopyExternalRepresentation(SecKeyRef key, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCopyAttributes + @abstract Retrieve keychain attributes of a key. + @param key The key whose attributes are to be retrieved. + @result Dictionary containing attributes of the key. The keys that populate this dictionary are defined + and discussed in SecItem.h. + @discussion The attributes provided by this function are: + * kSecAttrCanEncrypt + * kSecAttrCanDecrypt + * kSecAttrCanDerive + * kSecAttrCanSign + * kSecAttrCanVerify + * kSecAttrKeyClass + * kSecAttrKeyType + * kSecAttrKeySizeInBits + * kSecAttrTokenID + * kSecAttrApplicationLabel + Other values returned in that dictionary are RFU. + */ +CFDictionaryRef _Nullable SecKeyCopyAttributes(SecKeyRef key) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCopyPublicKey + @abstract Retrieve the public key from a key pair or private key. + @param key The key from which to retrieve a public key. + @result The public key or NULL if public key is not available for specified key. + @discussion Fails if key does not contain a public key or no public key can be computed from it. + */ +SecKeyRef _Nullable SecKeyCopyPublicKey(SecKeyRef key) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @enum SecKeyAlgorithm + @abstract Available algorithms for performing cryptographic operations with SecKey object. String representation + of constant can be used for logging or debugging purposes, because they contain human readable names of the algorithm. + + @constant kSecKeyAlgorithmRSASignatureRaw + Raw RSA sign/verify operation, size of input data must be the same as value returned by SecKeyGetBlockSize(). + + @constant kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw + RSA sign/verify operation, assumes that input data is digest and OID and digest algorithm as specified in PKCS# v1.5. + This algorithm is typically not used directly, instead use algorithm with specified digest, like + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256. + + @constant kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 + RSA signature with PKCS#1 padding, input data must be SHA-1 generated digest. + + @constant kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224 + RSA signature with PKCS#1 padding, input data must be SHA-224 generated digest. + + @constant kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 + RSA signature with PKCS#1 padding, input data must be SHA-256 generated digest. + + @constant kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 + RSA signature with PKCS#1 padding, input data must be SHA-384 generated digest. + + @constant kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 + 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. + + @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224 + RSA signature with PKCS#1 padding, SHA-224 digest is generated 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. + + @constant kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384 + RSA signature with PKCS#1 padding, SHA-384 digest is generated 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. + + @constant kSecKeyAlgorithmECDSASignatureRFC4754 + ECDSA algorithm, signature is concatenated r and s, big endian, data is message digest. + + @constant kSecKeyAlgorithmECDSASignatureDigestX962 + ECDSA algorithm, signature is in DER x9.62 encoding, input data is message digest. + + @constant kSecKeyAlgorithmECDSASignatureDigestX962SHA1 + ECDSA algorithm, signature is in DER x9.62 encoding, input data is 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 kSecKeyAlgorithmECDSASignatureDigestX962SHA1 + ECDSA algorithm, signature is in DER x9.62 encoding, input data is 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 kSecKeyAlgorithmECDSASignatureDigestX962SHA1 + ECDSA algorithm, signature is in DER x9.62 encoding, input data is 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. + + @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA224 + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-224 digest is generated 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. + + @constant kSecKeyAlgorithmECDSASignatureMessageX962SHA384 + ECDSA algorithm, signature is in DER x9.62 encoding, SHA-384 digest is generated 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. + + @constant kSecKeyAlgorithmRSAEncryptionRaw + Raw RSA encryption or decryption, size of data must match RSA key modulus size. Note that direct + use of this algorithm without padding is cryptographically very weak, it is important to always introduce + some kind of padding. Input data size must be less or equal to the key block size and returned block has always + the same size as block size, as returned by SecKeyGetBlockSize(). + + @constant kSecKeyAlgorithmRSAEncryptionPKCS1 + RSA encryption or decryption, data is padded using PKCS#1 padding scheme. This algorithm should be used only for + backward compatibility with existing protocols and data. New implementations should choose cryptographically + stronger algorithm instead (see kSecKeyAlgorithmRSAEncryptionOAEP). Input data must be at most + "key block size - 11" bytes long and returned block has always the same size as block size, as returned + by SecKeyGetBlockSize(). + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA1 + RSA encryption or decryption, data is padded using OAEP padding scheme internally using SHA1. Input data must be at most + "key block size - 42" bytes long and returned block has always the same size as block size, as returned + by SecKeyGetBlockSize(). Use kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM to be able to encrypt and decrypt arbitrary long data. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA224 + RSA encryption or decryption, data is padded using OAEP padding scheme internally using SHA224. Input data must be at most + "key block size - 58" bytes long and returned block has always the same size as block size, as returned + by SecKeyGetBlockSize(). Use kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM to be able to encrypt and decrypt arbitrary long data. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA256 + RSA encryption or decryption, data is padded using OAEP padding scheme internally using SHA256. Input data must be at most + "key block size - 66" bytes long and returned block has always the same size as block size, as returned + by SecKeyGetBlockSize(). Use kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM to be able to encrypt and decrypt arbitrary long data. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA384 + RSA encryption or decryption, data is padded using OAEP padding scheme internally using SHA384. Input data must be at most + "key block size - 98" bytes long and returned block has always the same size as block size, as returned + by SecKeyGetBlockSize(). Use kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM to be able to encrypt and decrypt arbitrary long data. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA512 + RSA encryption or decryption, data is padded using OAEP padding scheme internally using SHA512. Input data must be at most + "key block size - 130" bytes long and returned block has always the same size as block size, as returned + by SecKeyGetBlockSize(). Use kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM to be able to encrypt and decrypt arbitrary long data. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM + Randomly generated AES session key is encrypted by RSA with OAEP padding. User data are encrypted using session key in GCM + mode with all-zero 16 bytes long IV (initialization vector). Finally 16 byte AES-GCM tag is appended to ciphertext. + 256bit AES key is used if RSA key is 4096bit or bigger, otherwise 128bit AES key is used. Raw public key data is used + as authentication data for AES-GCM encryption. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM + Randomly generated AES session key is encrypted by RSA with OAEP padding. User data are encrypted using session key in GCM + mode with all-zero 16 bytes long IV (initialization vector). Finally 16 byte AES-GCM tag is appended to ciphertext. + 256bit AES key is used if RSA key is 4096bit or bigger, otherwise 128bit AES key is used. Raw public key data is used + as authentication data for AES-GCM encryption. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM + Randomly generated AES session key is encrypted by RSA with OAEP padding. User data are encrypted using session key in GCM + mode with all-zero 16 bytes long IV (initialization vector). Finally 16 byte AES-GCM tag is appended to ciphertext. + 256bit AES key is used if RSA key is 4096bit or bigger, otherwise 128bit AES key is used. Raw public key data is used + as authentication data for AES-GCM encryption. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM + Randomly generated AES session key is encrypted by RSA with OAEP padding. User data are encrypted using session key in GCM + mode with all-zero 16 bytes long IV (initialization vector). Finally 16 byte AES-GCM tag is appended to ciphertext. + 256bit AES key is used if RSA key is 4096bit or bigger, otherwise 128bit AES key is used. Raw public key data is used + as authentication data for AES-GCM encryption. + + @constant kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM + Randomly generated AES session key is encrypted by RSA with OAEP padding. User data are encrypted using session key in GCM + mode with all-zero 16 bytes long IV (initialization vector). Finally 16 byte AES-GCM tag is appended to ciphertext. + 256bit AES key is used if RSA key is 4096bit or bigger, otherwise 128bit AES key is used. Raw public key data is used + as authentication data for AES-GCM encryption. + + @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM + ECIES encryption or decryption. This algorithm does not limit the size of the message to be encrypted or decrypted. + Encryption is done using AES-GCM with key negotiated by kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1. AES Key size + is 128bit for EC keys <=256bit and 256bit for bigger EC keys. Ephemeral public key data is used as sharedInfo for KDF, + and static public key data is used as authenticationData for AES-GCM processing. AES-GCM uses 16 bytes long TAG and + all-zero 16 byte long IV (initialization vector). + + @constant kSecKeyAlgorithmECDHKeyExchangeCofactor + Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys. + This algorithm does not accept any parameters, length of output raw shared secret is given by the length of the key. + + @constant kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1 + Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA1 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224 + Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA224 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256 + Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA256 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384 + Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA384 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512 + Compute shared secret using ECDH cofactor algorithm, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA512 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeStandard + Compute shared secret using ECDH algorithm without cofactor, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys. + This algorithm does not accept any parameters, length of output raw shared secret is given by the length of the key. + + @constant kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1 + Compute shared secret using ECDH algorithm without cofactor, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA1 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224 + Compute shared secret using ECDH algorithm without cofactor, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA224 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256 + Compute shared secret using ECDH algorithm without cofactor, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA256 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384 + Compute shared secret using ECDH algorithm without cofactor, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA384 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + + @constant kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512 + Compute shared secret using ECDH algorithm without cofactor, suitable only for kSecAttrKeyTypeECSECPrimeRandom keys + and apply ANSI X9.63 KDF with SHA512 as hashing function. Requires kSecKeyKeyExchangeParameterRequestedSize and allows + kSecKeyKeyExchangeParameterSharedInfo parameters to be used. + */ + +typedef CFStringRef SecKeyAlgorithm CF_STRING_ENUM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureRaw +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureRFC4754 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureMessageX962SHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionRaw +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionPKCS1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA1AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA224AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA384AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionCofactorX963SHA512AESGCM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandard +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactor +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyAlgorithm kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512 +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCreateSignature + @abstract Given a private key and data to sign, generate a digital signature. + @param key Private key with which to sign. + @param algorithm One of SecKeyAlgorithm constants suitable to generate signature with this key. + @param dataToSign The data to be signed, typically the digest of the actual data. + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @result The signature over dataToSign represented as a CFData, or NULL on failure. + @discussion Computes digital signature using specified key over input data. The operation algorithm + further defines the exact format of input data, operation to be performed and output signature. + */ +CFDataRef _Nullable SecKeyCreateSignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef dataToSign, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyVerifySignature + @abstract Given a public key, data which has been signed, and a signature, verify the signature. + @param key Public key with which to verify the signature. + @param algorithm One of SecKeyAlgorithm constants suitable to verify signature with this key. + @param signedData The data over which sig is being verified, typically the digest of the actual data. + @param signature The signature to verify. + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @result True if the signature was valid, False otherwise. + @discussion Verifies digital signature operation using specified key and signed data. The operation algorithm + further defines the exact format of input data, signature and operation to be performed. + */ +Boolean SecKeyVerifySignature(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef signedData, CFDataRef signature, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCreateEncryptedData + @abstract Encrypt a block of plaintext. + @param key Public key with which to encrypt the data. + @param algorithm One of SecKeyAlgorithm constants suitable to perform encryption with this key. + @param plaintext The data to encrypt. The length and format of the data must conform to chosen algorithm, + typically be less or equal to the value returned by SecKeyGetBlockSize(). + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @result The ciphertext represented as a CFData, or NULL on failure. + @discussion Encrypts plaintext data using specified key. The exact type of the operation including the format + of input and output data is specified by encryption algorithm. + */ +CFDataRef _Nullable SecKeyCreateEncryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef plaintext, + CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCreateDecryptedData + @abstract Decrypt a block of ciphertext. + @param key Private key with which to decrypt the data. + @param algorithm One of SecKeyAlgorithm constants suitable to perform decryption with this key. + @param ciphertext The data to decrypt. The length and format of the data must conform to chosen algorithm, + typically be less or equal to the value returned by SecKeyGetBlockSize(). + @param error On error, will be populated with an error object describing the failure. + See "Security Error Codes" (SecBase.h). + @result The plaintext represented as a CFData, or NULL on failure. + @discussion Decrypts ciphertext data using specified key. The exact type of the operation including the format + of input and output data is specified by decryption algorithm. + */ +CFDataRef _Nullable SecKeyCreateDecryptedData(SecKeyRef key, SecKeyAlgorithm algorithm, CFDataRef ciphertext, + CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @enum SecKeyKeyExchangeParameter SecKey Key Exchange parameters + @constant kSecKeyKeyExchangeParameterRequestedSize Contains CFNumberRef with requested result size in bytes. + @constant kSecKeyKeyExchangeParameterSharedInfo Contains CFDataRef with additional shared info + for KDF (key derivation function). + */ +typedef CFStringRef SecKeyKeyExchangeParameter CF_STRING_ENUM +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyKeyExchangeParameter kSecKeyKeyExchangeParameterRequestedSize +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); +extern const SecKeyKeyExchangeParameter kSecKeyKeyExchangeParameterSharedInfo +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCopyKeyExchangeResult + @abstract Perform Diffie-Hellman style of key exchange operation, optionally with additional key-derivation steps. + @param algorithm One of SecKeyAlgorithm constants suitable to perform this operation. + @param publicKey Remote party's public key. + @param parameters Dictionary with parameters, see SecKeyKeyExchangeParameter constants. Used algorithm + determines the set of required and optional parameters to be used. + @param error Pointer to an error object on failure. + See "Security Error Codes" (SecBase.h). + @result Result of key exchange operation as a CFDataRef, or NULL on failure. + */ +CFDataRef _Nullable SecKeyCopyKeyExchangeResult(SecKeyRef privateKey, SecKeyAlgorithm algorithm, SecKeyRef publicKey, CFDictionaryRef parameters, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @enum SecKeyOperationType + @abstract Defines types of cryptographic operations available with SecKey instance. + + @constant kSecKeyOperationTypeSign + Represents SecKeyCreateSignature() + + @constant kSecKeyOperationTypeVerify + Represents SecKeyVerifySignature() + + @constant kSecKeyOperationTypeEncrypt + Represents SecKeyCreateEncryptedData() + + @constant kSecKeyOperationTypeDecrypt + Represents SecKeyCreateDecryptedData() + + @constant kSecKeyOperationTypeKeyExchange + Represents SecKeyCopyKeyExchangeResult() + */ +typedef CF_ENUM(CFIndex, SecKeyOperationType) { + kSecKeyOperationTypeSign = 0, + kSecKeyOperationTypeVerify = 1, + kSecKeyOperationTypeEncrypt = 2, + kSecKeyOperationTypeDecrypt = 3, + kSecKeyOperationTypeKeyExchange = 4, +} __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyIsAlgorithmSupported + @abstract Checks whether key supports specified algorithm for specified operation. + @param key Key to query + @param operation Operation type for which the key is queried + @param algorithm Algorithm which is queried + @return True if key supports specified algorithm for specified operation, False otherwise. + */ +Boolean SecKeyIsAlgorithmSupported(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_keychain/lib/SecKeyPriv.h b/OSX/libsecurity_keychain/lib/SecKeyPriv.h index 26d9cb9b..e2b1ebc5 100644 --- a/OSX/libsecurity_keychain/lib/SecKeyPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeyPriv.h @@ -39,6 +39,7 @@ #include #include #include +#include #if defined(__cplusplus) extern "C" { @@ -66,14 +67,42 @@ enum { to a SecRSAPublicKeyParams and keyDataLength is sizeof(SecRSAPublicKeyParams). */ kSecKeyEncodingRSAPublicParams = 3, + + /* RSA public key in SecRSAPublicKeyParams format. keyData is a pointer + to a SecRSAPublicKeyParams and keyDataLength is + sizeof(SecRSAPublicKeyParams). */ + kSecDERKeyEncoding = 4, + + /* Internal "encodings to send other data" */ + kSecGenerateKey = 5, + kSecExtractPublicFromPrivate = 6, + + /* Encoding came from SecKeyCopyPublicBytes for a public key, + or internally from a private key */ + kSecKeyEncodingBytes = 7, + + /* Handing in a private key from corecrypto directly. */ + kSecKeyCoreCrypto = 8, +}; + +typedef uint32_t SecKeyWrapType; +enum { + /* wrap key in RFC3394 (AESWrap) */ + kSecKeyWrapRFC3394 = 0, + + /* wrap key in PGP style (support EC keys only right now) */ + kSecKeyWrapPublicKeyPGP = 1, + +}; + +typedef CF_ENUM(CFIndex, SecKeyOperationMode) { + kSecKeyOperationModePerform = 0, + kSecKeyOperationModeCheckIfSupported = 1, }; typedef OSStatus (*SecKeyInitMethod)(SecKeyRef, const uint8_t *, CFIndex, SecKeyEncoding); -typedef void *(*SecKeyCopyMethod)(SecKeyRef); typedef void (*SecKeyDestroyMethod)(SecKeyRef); -typedef void (*SecKeyDeleteMethod)(SecKeyRef); -typedef void (*SecKeyShowMethod)(SecKeyRef); typedef OSStatus (*SecKeyRawSignMethod)(SecKeyRef key, SecPadding padding, const uint8_t *dataToSign, size_t dataToSignLen, uint8_t *sig, size_t *sigLen); @@ -86,28 +115,88 @@ typedef OSStatus (*SecKeyEncryptMethod)(SecKeyRef key, SecPadding padding, typedef OSStatus (*SecKeyDecryptMethod)(SecKeyRef key, SecPadding padding, const uint8_t *cipherText, size_t cipherTextLen, uint8_t *plainText, size_t *plainTextLen); +typedef OSStatus (*SecKeyComputeMethod)(SecKeyRef key, + const uint8_t *pub_key, size_t pub_key_len, + uint8_t *computed_key, size_t *computed_key_len); typedef size_t (*SecKeyBlockSizeMethod)(SecKeyRef key); typedef CFDictionaryRef (*SecKeyCopyDictionaryMethod)(SecKeyRef key); +typedef CFIndex (*SecKeyGetAlgorithmIDMethod)(SecKeyRef key); +typedef OSStatus (*SecKeyCopyPublicBytesMethod)(SecKeyRef key, CFDataRef *serialization); +typedef CFDataRef (*SecKeyCopyWrapKeyMethod)(SecKeyRef key, SecKeyWrapType type, CFDataRef unwrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error); +typedef CFDataRef (*SecKeyCopyUnwrapKeyMethod)(SecKeyRef key, SecKeyWrapType type, CFDataRef wrappedKey, CFDictionaryRef parameters, CFDictionaryRef *outParam, CFErrorRef *error); +typedef CFStringRef (*SecKeyDescribeMethod)(SecKeyRef key); + +typedef CFDataRef (*SecKeyCopyExternalRepresentationMethod)(SecKeyRef key, CFErrorRef *error); +typedef SecKeyRef (*SecKeyCopyPublicKeyMethod)(SecKeyRef key); +typedef Boolean (*SecKeyIsEqualMethod)(SecKeyRef key1, SecKeyRef key2); +/*! + @abstract Performs cryptographic operation with the key. + @param key Key to perform the operation on. + @param operation Type of operation to be performed. + @param algorithm Algorithm identifier for the operation. Determines format of input and output data. + @param allAlgorithms Array of algorithms which were traversed until we got to this operation. The last member of this array is always the same as @c algorithm parameter. + @param mode Mode in which the operation is performed. Two available modes are checking only if the operation can be performed or actually performing the operation. + @param in1 First input parameter for the operation, meaningful only in ModePerform. + @param in2 Second input parameter for the operation, meaningful only in ModePerform. + @param error Error details when NULL is returned. + @return NULL if some failure occured. kCFNull if operation/algorithm/key combination is not supported, otherwise the result of the operation or kCFBooleanTrue in ModeCheckIfSupported. + */ +typedef CFTypeRef(*SecKeyCopyOperationResultMethod)(SecKeyRef key, SecKeyOperationType operation, SecKeyAlgorithm algorithm, CFArrayRef allAlgorithms, SecKeyOperationMode mode, CFTypeRef in1, CFTypeRef in2, CFErrorRef *error); + +#define kSecKeyDescriptorVersion (4) + +typedef struct __SecKeyDescriptor { + /* Version of this SecKeyDescriptor. Must be kSecKeyDescriptorVersion. */ + uint32_t version; -typedef struct { + /* Name of this key class for use by SecKeyShow(). */ const char *name; + + /* If nonzero, SecKeyCreate will allocate this many bytes for the key + field in the SecKeyRef it creates. If zero key is NULL and the + implementor can choose to dynamically allocate it in the init + function and free it in the destroy function. */ + uint32_t extraBytes; + + /* Called by SecKeyCreate(). */ SecKeyInitMethod init; - SecKeyCopyMethod copy; + /* Called by destructor (final CFRelease() or gc if using). */ SecKeyDestroyMethod destroy; - SecKeyDeleteMethod remove; - SecKeyShowMethod show; + /* Called by SecKeyRawSign(). */ SecKeyRawSignMethod rawSign; + /* Called by SecKeyRawVerify(). */ SecKeyRawVerifyMethod rawVerify; + /* Called by SecKeyEncrypt(). */ SecKeyEncryptMethod encrypt; + /* Called by SecKeyDecrypt(). */ SecKeyDecryptMethod decrypt; + /* Reserved for future use. */ + SecKeyComputeMethod compute; + /* Called by SecKeyGetBlockSize(). */ SecKeyBlockSizeMethod blockSize; + /* Called by SecKeyCopyAttributeDictionary(), which is private. */ SecKeyCopyDictionaryMethod copyDictionary; - /* If known, the number of bytes to allocate for the key field in the SecKey struct. */ - int extraBytes; + /* Called by SecKeyDescribeMethod(). */ + SecKeyDescribeMethod describe; +#if kSecKeyDescriptorVersion > 0 + /* Called by SecKeyCopyAttributeDictionary(), which is private. */ + SecKeyGetAlgorithmIDMethod getAlgorithmID; +#endif +#if kSecKeyDescriptorVersion > 1 + SecKeyCopyPublicBytesMethod copyPublic; +#endif +#if kSecKeyDescriptorVersion > 2 + SecKeyCopyWrapKeyMethod copyWrapKey; + SecKeyCopyUnwrapKeyMethod copyUnwrapKey; +#endif +#if kSecKeyDescriptorVersion > 3 + SecKeyCopyExternalRepresentationMethod copyExternalRepresentation; + SecKeyCopyPublicKeyMethod copyPublicKey; + SecKeyCopyOperationResultMethod copyOperationResult; + SecKeyIsEqualMethod isEqual; +#endif } SecKeyDescriptor; -CFTypeID SecKeyGetCFClassTypeID(void); - /*! @function SecKeyGetAlgorithmID @abstract Returns a pointer to a CSSM_X509_ALGORITHM_IDENTIFIER structure for the given key. @@ -389,6 +478,77 @@ OSStatus SecKeyRawVerifyOSX( const uint8_t *sig, size_t sigLen); +/*! + @enum SecKeyAttestationKeyType + @abstract Defines types of builtin attestation keys. +*/ +typedef CF_ENUM(uint32_t, SecKeyAttestationKeyType) +{ + kSecKeyAttestationKeyTypeSIK = 0, + kSecKeyAttestationKeyTypeGID +} __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCopyAttestationKey + @abstract Returns a copy of a builtin attestation key. + + @param keyType Type of the requested builtin key. + @param error An optional pointer to a CFErrorRef. This value is set if an error occurred. + + @result On success a SecKeyRef containing the requested key is returned, on failure it returns NULL. +*/ +SecKeyRef SecKeyCopyAttestationKey(SecKeyAttestationKeyType keyType, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeyCreateAttestation + @abstract Attests a key with another key. + + @param key The attesting key. + @param keyToAttest The key which is to be attested. + @param error An optional pointer to a CFErrorRef. This value is set if an error occurred. + + @result On success a CFDataRef containing the attestation data is returned, on failure it returns NULL. + + @discussion Key attestation only works for CTK SEP keys, i.e. keys created with kSecAttrTokenID=kSecAttrTokenIDSecureEnclave. +*/ +CFDataRef SecKeyCreateAttestation(SecKeyRef key, SecKeyRef keyToAttest, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecKeySetParameter + @abstract Sets unspecified key parameter for the backend. + + @param key Key to set the parameter to. + @param name Identifies parameter to be set. + @param value New value for the parameter. + @param error Error which gathers more information when something went wrong. + + @discussion Serves as channel between SecKey client and backend for passing additional sideband data send from SecKey caller + to SecKey implementation backend (currently only CTK-based token backend is supported). Parameter names and types are + a contract between SecKey user (application) and backend and are not interpreted by SecKey layer in any way. + */ +Boolean SecKeySetParameter(SecKeyRef key, CFStringRef name, CFPropertyListRef value, CFErrorRef *error) +__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + Algorithms for converting between bigendian and core-crypto ccunit data representation. + */ +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureRawCCUnit; +extern const SecKeyAlgorithm kSecKeyAlgorithmRSAEncryptionRawCCUnit; + +/*! + Internal algorithm for RSA-MD5. We do not want to export MD5 in new API, but we need it + for implementing legacy interfaces. + */ +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5; +extern const SecKeyAlgorithm kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5; + +/*! + Algorithms for interoperability with libaks smartcard support. + */ +extern const SecKeyAlgorithm kSecKeyAlgorithmECIESEncryptionAKSSmartCard; + #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecKeychain.cpp b/OSX/libsecurity_keychain/lib/SecKeychain.cpp index 9580a994..d307e2bd 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychain.cpp @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include "TokenLogin.h" OSStatus SecKeychainMDSInstall() @@ -96,7 +99,7 @@ SecKeychainOpenWithGuid(const CSSM_GUID *guid, uint32 subserviceId, uint32 subse DLDbIdentifier dLDbIdentifier(ssuid, dbName, dbLocation); // make a keychain from the supplied info - RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false)->handle (); + RequiredParam(keychain) = globals().storageManager.makeKeychain(dLDbIdentifier, false, false)->handle (); END_SECAPI } @@ -109,7 +112,7 @@ SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void *passw BEGIN_SECAPI KCThrowParamErrIf_(!pathName); - Keychain keychain = globals().storageManager.make(pathName); + Keychain keychain = globals().storageManager.make(pathName, true, true); // @@@ the call to StorageManager::make above leaves keychain the the cache. // If the create below fails we should probably remove it. @@ -246,7 +249,7 @@ OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Bool globals().storageManager.resetKeychain(resetSearchList); // Create the login keychain without UI - globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password); + globals().storageManager.login((UInt32)userName.length(), userName.c_str(), passwordLength, password, true); // Set it as the default Keychain keychain = globals().storageManager.loginKeychain(); @@ -256,7 +259,7 @@ OSStatus SecKeychainResetLogin(UInt32 passwordLength, const void* password, Bool { // Create the login keychain, prompting for password // (implicitly calls resetKeychain, login, and defaultKeychain) - globals().storageManager.makeLoginAuthUI(NULL); + globals().storageManager.makeLoginAuthUI(NULL, true); } // Post a "list changed" event after a reset, so apps can refresh their list. @@ -420,6 +423,35 @@ SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version) END_SECAPI } +OSStatus +SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename) +{ + BEGIN_SECAPI + + RequiredParam(masterKeyFilename); + Keychain kc = Keychain::optional(keychain); + + SecurityServer::SystemKeychainKey keychainKey(masterKeyFilename); + if(keychainKey.valid()) { + // We've managed to read the key; now, create credentials using it + string path = kc->name(); + + CssmClient::Key keychainMasterKey(kc->csp(), keychainKey.key(), true); + CssmClient::AclFactory::MasterKeyUnlockCredentials creds(keychainMasterKey, Allocator::standard(Allocator::sensitive)); + + // Attempt the migrate, using our master key as the ACL override + bool result = kc->keychainMigration(path, kc->database()->dbBlobVersion(), path, version, creds.getAccessCredentials()); + if(!result) { + return errSecBadReq; + } + return (kc->database()->dbBlobVersion() == version ? errSecSuccess : errSecBadReq); + } else { + return errSecBadReq; + } + + END_SECAPI +} + // @@@ Deprecated UInt16 @@ -627,9 +659,13 @@ SecKeychainFindInternetPassword(CFTypeRef keychainOrArray, UInt32 serverNameLeng { CssmDataContainer outData; item->getData(outData); - *passwordLength=(UInt32)outData.length(); + if (passwordLength) { + *passwordLength=(UInt32)outData.length(); + } outData.Length=0; - *passwordData=outData.data(); + if (passwordData) { + *passwordData=outData.data(); + } outData.Data=NULL; } @@ -726,9 +762,13 @@ SecKeychainFindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLeng { CssmDataContainer outData; item->getData(outData); - *passwordLength=(UInt32)outData.length(); + if (passwordLength) { + *passwordLength=(UInt32)outData.length(); + } outData.Length=0; - *passwordData=outData.data(); + if (passwordData) { + *passwordData=outData.data(); + } outData.Data=NULL; } @@ -845,7 +885,7 @@ SecKeychainLogin(UInt32 nameLength, const void* name, UInt32 passwordLength, con try { if (password) { - globals().storageManager.login(nameLength, name, passwordLength, password); + globals().storageManager.login(nameLength, name, passwordLength, password, false); } else { globals().storageManager.stashLogin(); } @@ -1187,9 +1227,9 @@ static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRe cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), new(alloc) ListElement(StringData(passphrase))); - db->accessCredentials(&cred); - - CSSM_DL_DB_HANDLE dlDb = db->handle(); + db->authenticate(CSSM_DB_ACCESS_READ, &cred); + + CSSM_DL_DB_HANDLE dlDb = db->handle(); CssmData dlDbData = CssmData::wrap(dlDb); CssmKey refKey; KeySpec spec(CSSM_KEYUSE_ANY, @@ -1208,6 +1248,81 @@ static OSStatus SecKeychainGetMasterKey(SecKeychainRef userKeychainRef, CFDataRe END_SECAPI } +static const char *kAutologinPWFilePath = "/etc/kcpassword"; +static const uint32_t kObfuscatedPasswordSizeMultiple = 12; +static const uint32_t buffer_size = 512; +static const uint8_t kObfuscationKey[] = {0x7d, 0x89, 0x52, 0x23, 0xd2, 0xbc, 0xdd, 0xea, 0xa3, 0xb9, 0x1f}; + +static void obfuscate(void *buffer, size_t bufferLength) +{ + uint8_t *pBuf = (uint8_t *) buffer; + const uint8_t *pKey = kObfuscationKey, *eKey = pKey + sizeof( kObfuscationKey ); + + while (bufferLength--) { + *pBuf = *pBuf ^ *pKey; + ++pKey; + ++pBuf; + if (pKey == eKey) + pKey = kObfuscationKey; + } +} + +static bool _SASetAutologinPW(CFStringRef inAutologinPW) +{ + bool result = false; + struct stat sb; + + // Delete the kcpassword file if it exists already + if (stat(kAutologinPWFilePath, &sb) == 0) + unlink( kAutologinPWFilePath ); + + // NIL incoming password ==> clear auto login password (above) without setting a new one. In other words: turn auto login off. + if (inAutologinPW != NULL) { + char buffer[buffer_size]; + const char *pwAsUTF8String = CFStringGetCStringPtr(inAutologinPW, kCFStringEncodingUTF8); + if (pwAsUTF8String == NULL) { + if (CFStringGetCString(inAutologinPW, buffer, buffer_size, kCFStringEncodingUTF8)) pwAsUTF8String = buffer; + } + + if (pwAsUTF8String != NULL) { + size_t pwLength = strlen(pwAsUTF8String) + 1; + size_t obfuscatedPWLength; + char *obfuscatedPWBuffer; + + // The size of the obfuscated password should be the smallest multiple of + // kObfuscatedPasswordSizeMultiple greater than or equal to pwLength. + obfuscatedPWLength = (((pwLength - 1) / kObfuscatedPasswordSizeMultiple) + 1) * kObfuscatedPasswordSizeMultiple; + obfuscatedPWBuffer = (char *) malloc(obfuscatedPWLength); + + // Copy the password (including null terminator) to beginning of obfuscatedPWBuffer + bcopy(pwAsUTF8String, obfuscatedPWBuffer, pwLength); + + // Pad remainder of obfuscatedPWBuffer with random bytes + { + char *p; + char *endOfBuffer = obfuscatedPWBuffer + obfuscatedPWLength; + + for (p = obfuscatedPWBuffer + pwLength; p < endOfBuffer; ++p) + *p = random() & 0x000000FF; + } + + obfuscate(obfuscatedPWBuffer, obfuscatedPWLength); + + int pwFile = open(kAutologinPWFilePath, O_CREAT | O_WRONLY | O_NOFOLLOW, S_IRUSR | S_IWUSR); + if (pwFile >= 0) { + size_t wrote = write(pwFile, obfuscatedPWBuffer, obfuscatedPWLength); + if (wrote == obfuscatedPWLength) + result = true; + close(pwFile); + } + + chmod(kAutologinPWFilePath, S_IRUSR | S_IWUSR); + free(obfuscatedPWBuffer); + } + } + + return result; +} OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) { SecTrustedApplicationRef itemPath; @@ -1215,6 +1330,14 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe OSStatus result = errSecParam; + if (userKeychainRef == NULL) { + // We don't have a specific user keychain, fall back + if (_SASetAutologinPW(password)) + result = errSecSuccess; + + return result; + } + CFDataRef masterKey = NULL; result = SecKeychainGetMasterKey(userKeychainRef, &masterKey, password); if (errSecSuccess != result) { @@ -1223,18 +1346,21 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe result = SecKeychainStash(); if (errSecSuccess != result) { - if (NULL != masterKey) CFRelease(masterKey); + if (masterKey != NULL) CFRelease(masterKey); return result; } CFMutableArrayRef trustedApplications = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - if ( noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath ) + if (noErr == SecTrustedApplicationCreateApplicationGroup("com.apple.security.auto-login", NULL, &itemPath) && itemPath) CFArrayAppendValue(trustedApplications, itemPath); - if ( trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) { + if (trustedApplications && (CFArrayGetCount(trustedApplications) > 0)) { if (errSecSuccess == (result = SecAccessCreate(CFSTR("Auto-Login applications"), trustedApplications, &ourAccessRef))) { + SecKeychainRef internalSystemKeychainRef = NULL; if (NULL == systemKeychainRef) { - SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &systemKeychainRef); + SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &internalSystemKeychainRef); + } else { + internalSystemKeychainRef = systemKeychainRef; } const void *queryKeys[] = { kSecClass, @@ -1245,7 +1371,7 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe const void *queryValues[] = { kSecClassGenericPassword, CFSTR("com.apple.loginwindow.auto-login"), username, - systemKeychainRef, + internalSystemKeychainRef, }; const void *updateKeys[] = { kSecAttrAccess, @@ -1271,7 +1397,7 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe const void *addValues[] = { kSecClassGenericPassword, CFSTR("com.apple.loginwindow.auto-login"), username, - systemKeychainRef, + internalSystemKeychainRef, ourAccessRef, masterKey, }; @@ -1283,13 +1409,122 @@ OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRe if (NULL != query) CFRelease(query); if (NULL != update) CFRelease(update); + + // If the caller wanted us to locate the system keychain reference, it's okay to go ahead and free our magically created one + if (systemKeychainRef == NULL) CFRelease(internalSystemKeychainRef); } } if (NULL != masterKey) CFRelease(masterKey); if (NULL != trustedApplications) CFRelease(trustedApplications); if (NULL != ourAccessRef) CFRelease(ourAccessRef); - if (NULL != systemKeychainRef) CFRelease(systemKeychainRef); return result; } + +OSStatus SecKeychainGetUserPromptAttempts(uint32_t * attempts) +{ + BEGIN_SECAPI + + if(attempts) { + SecurityServer::ClientSession().getUserPromptAttempts(*attempts); + } + + END_SECAPI +} + +OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash, + SecKeychainRef userKeychain, CFStringRef password) +{ + CFRef pwd; + OSStatus result; + + if (password == NULL || CFStringGetLength(password) == 0) { + AuthorizationRef authorizationRef; + result = AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorizationRef); + if (result != errAuthorizationSuccess) { + secinfo("SecKeychain", "failed to create authorization"); + return result; + } + + AuthorizationItem myItems = {"com.apple.ctk.pair", 0, NULL, 0}; + AuthorizationRights myRights = {1, &myItems}; + AuthorizationRights *authorizedRights = NULL; + + char pathName[PATH_MAX]; + UInt32 pathLength = PATH_MAX; + result = SecKeychainGetPath(userKeychain, &pathLength, pathName); + if (result != errSecSuccess) { + secinfo("SecKeychain", "Failed to get kc path: %d", (int) result); + return result; + } + + Boolean checkPwd = TRUE; + AuthorizationItem envItems[] = { + {AGENT_HINT_KEYCHAIN_PATH, pathLength, pathName, 0}, + {AGENT_HINT_KEYCHAIN_CHECK, sizeof(checkPwd), &checkPwd} + }; + + AuthorizationEnvironment environment = {2, envItems}; + AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; + result = AuthorizationCopyRights(authorizationRef, &myRights, &environment, flags, &authorizedRights); + if (authorizedRights) + AuthorizationFreeItemSet(authorizedRights); + + if (result == errAuthorizationSuccess) { + AuthorizationItemSet *items; + result = AuthorizationCopyInfo(authorizationRef, kAuthorizationEnvironmentPassword, &items); + if (result == errAuthorizationSuccess) { + if (items->count > 0) { + pwd = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)items->items[0].value, kCFStringEncodingUTF8); + } + AuthorizationFreeItemSet(items); + } + } + AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); + if (result != errAuthorizationSuccess) { + secinfo("SecKeychain", "did not get authorization to pair the card"); + return result; + } + } else { + pwd.take(password); + } + + if (!pwd) { + secinfo("SecKeychain", "did not get kcpass"); + return errSecInternalComponent; + } + + CFRef masterKey; + result = SecKeychainGetMasterKey(userKeychain, masterKey.take(), pwd); + if (result != errSecSuccess) { + secnotice("SecKeychain", "Failed to get master key: %d", (int) result); + return result; + } + + CFRef scBlob; + result = TokenLoginGetScBlob(wrapPubKeyHash, tokenID, pwd, scBlob.take()); + if (result != errSecSuccess) { + secnotice("SecKeychain", "Failed to get stash: %d", (int) result); + return result; + } + + result = TokenLoginCreateLoginData(tokenID, pubKeyHash, wrapPubKeyHash, masterKey, scBlob); + if (result != errSecSuccess) { + secnotice("SecKeychain", "Failed to create login data: %d", (int) result); + return result; + } + + secnotice("SecKeychain", "SecKeychainStoreUnlockKeyWithPubKeyHash result %d", (int) result); + return result; +} + +OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash) +{ + 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 9062d613..a27af901 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.h +++ b/OSX/libsecurity_keychain/lib/SecKeychain.h @@ -416,7 +416,7 @@ OSStatus SecKeychainGetStatus(SecKeychainRef __nullable keychain, SecKeychainSta @function SecKeychainGetPath @abstract Get the path of the specified keychain. @param keychain A reference to a keychain. - @param ioPathLength On input, a pointer to the size or the buffer pointed to by pathName. On return, the size of the buffer without the zero termination. + @param ioPathLength On input, a pointer to the size of the buffer pointed to by pathName. On return, the size of the buffer without the zero termination. @param pathName On return, the POSIX path to the keychain. @result A result code. See "Security Error Codes" (SecBase.h). */ @@ -603,7 +603,7 @@ OSStatus SecKeychainGetDLDBHandle(SecKeychainRef __nullable keychain, CSSM_DL_DB @function SecKeychainCopyAccess @abstract Retrieves the access for a keychain. @param keychain A reference to the keychain from which to copy the access. - @param accessRef On return, a pointer to the access reference. + @param access On return, a pointer to the access reference. @result A result code. See "Security Error Codes" (SecBase.h). */ OSStatus SecKeychainCopyAccess(SecKeychainRef __nullable keychain, SecAccessRef * __nonnull CF_RETURNS_RETAINED access); @@ -612,7 +612,7 @@ OSStatus SecKeychainCopyAccess(SecKeychainRef __nullable keychain, SecAccessRef @function SecKeychainSetAccess @abstract Sets the access for a keychain. @param keychain A reference to the keychain for which to set the access. - @param accessRef An access reference. + @param access An access reference. @result A result code. See "Security Error Codes" (SecBase.h). */ OSStatus SecKeychainSetAccess(SecKeychainRef __nullable keychain, SecAccessRef access); diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp index e606a191..fedf2f1f 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2011-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,7 @@ #include "Access.h" #include "SecKeychainItemExtendedAttributes.h" +extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); // // Given a polymorphic Sec type object, return @@ -59,7 +61,7 @@ RefPointer aclBearer(CFTypeRef itemRef) // keychain item. If it's in a protected group, return the group key if (SSGroup group = ItemImpl::required(SecKeychainItemRef(itemRef))->group()) return &*group; - } else if (id == gTypes().KeyItem.typeID) { + } else if (id == SecKeyGetTypeID() && SecKeyIsCDSAKey((SecKeyRef)itemRef)) { // key item, return the key itself. if (CssmClient::Key key = KeyItem::required(SecKeyRef(itemRef))->key()) return &*key; @@ -88,29 +90,32 @@ SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeLis UInt32 length, const void *data, SecKeychainRef keychainRef, SecAccessRef initialAccess, SecKeychainItemRef *itemRef) { - BEGIN_SECAPI - KCThrowParamErrIf_(length!=0 && data==NULL); - Item item(itemClass, attrList, length, data); - if (initialAccess) - item->setAccess(Access::required(initialAccess)); - - 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); - } + BEGIN_SECAPI + + KCThrowParamErrIf_(length!=0 && data==NULL); + Item item(itemClass, attrList, length, data); + if (initialAccess) { + item->setAccess(Access::required(initialAccess)); + } + 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); + } + + keychain->add(item); + if (itemRef) { + *itemRef = item->handle(); + } - keychain->add(item); - if (itemRef) - *itemRef = item->handle(); END_SECAPI } @@ -118,69 +123,24 @@ SecKeychainItemCreateFromContent(SecItemClass itemClass, SecKeychainAttributeLis OSStatus SecKeychainItemModifyContent(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) { - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - item->modifyContent(attrList, length, data); - END_SECAPI + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + item->modifyContent(attrList, length, data); + + END_SECKCITEMAPI } OSStatus SecKeychainItemCopyContent(SecKeychainItemRef itemRef, SecItemClass *itemClass, SecKeychainAttributeList *attrList, UInt32 *length, void **outData) { -#if !SECTRUST_OSX - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - item->getContent(itemClass, attrList, length, outData); - END_SECAPI -#else - OSStatus __secapiresult; - bool isCertificate = false; - SecKeychainItemRef itemImplRef; - if (itemRef && CFGetTypeID(itemRef) == SecCertificateGetTypeID()) { - // TODO: determine whether we need to actually look up the cert in a keychain here - itemImplRef = (SecKeychainItemRef) SecCertificateCopyKeychainItem((SecCertificateRef)itemRef); - if (!itemImplRef) { - itemImplRef = (SecKeychainItemRef) SecCertificateCreateItemImplInstance((SecCertificateRef)itemRef); - } - isCertificate = true; - } - else { - itemImplRef = (SecKeychainItemRef)((itemRef) ? CFRetain(itemRef) : NULL); - } + BEGIN_SECKCITEMAPI - try - { - Item item = ItemImpl::required(itemImplRef); - item->getContent(itemClass, attrList, (isCertificate) ? NULL : length, (isCertificate) ? NULL : outData); - __secapiresult=0; - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } + Item item = ItemImpl::required(__itemImplRef); + item->getContent(itemClass, attrList, length, outData); - if (isCertificate && outData && *outData == NULL) { - // copy the data here - __secapiresult = errSecAllocate; - CFDataRef dataRef = SecCertificateCopyData((SecCertificateRef)itemRef); - if (dataRef) { - CFIndex dataLen = CFDataGetLength(dataRef); - const UInt8 *bytePtr = CFDataGetBytePtr(dataRef); - if ((bytePtr != NULL) && (dataLen > 0)) { - *outData = malloc(dataLen); - memcpy(*outData, bytePtr, dataLen); - *length = (UInt32)dataLen; - __secapiresult = errSecSuccess; - } - CFRelease(dataRef); - } - } - if (itemImplRef) { - CFRelease(itemImplRef); - } - return __secapiresult; -#endif + END_SECKCITEMAPI } @@ -188,7 +148,9 @@ OSStatus SecKeychainItemFreeContent(SecKeychainAttributeList *attrList, void *data) { BEGIN_SECAPI - ItemImpl::freeContent(attrList, data); + + ItemImpl::freeContent(attrList, data); + END_SECAPI } @@ -196,52 +158,24 @@ SecKeychainItemFreeContent(SecKeychainAttributeList *attrList, void *data) OSStatus SecKeychainItemModifyAttributesAndData(SecKeychainItemRef itemRef, const SecKeychainAttributeList *attrList, UInt32 length, const void *data) { - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - item->modifyAttributesAndData(attrList, length, data); - END_SECAPI + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + item->modifyAttributesAndData(attrList, length, data); + + END_SECKCITEMAPI } OSStatus SecKeychainItemCopyAttributesAndData(SecKeychainItemRef itemRef, SecKeychainAttributeInfo *info, SecItemClass *itemClass, SecKeychainAttributeList **attrList, UInt32 *length, void **outData) { -#if !SECTRUST_OSX - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - item->getAttributesAndData(info, itemClass, attrList, length, outData); - END_SECAPI -#else - // if the item is a SecCertificateRef, must convert to an ItemImpl-based instance - // TODO: determine whether we need to actually look up the cert in a keychain here - OSStatus __secapiresult; - SecKeychainItemRef itemImplRef; - if (itemRef && CFGetTypeID(itemRef) == SecCertificateGetTypeID()) { - itemImplRef = (SecKeychainItemRef) SecCertificateCopyKeychainItem((SecCertificateRef)itemRef); - if (!itemImplRef) { - itemImplRef = (SecKeychainItemRef) SecCertificateCreateItemImplInstance((SecCertificateRef)itemRef); - } - } - else { - itemImplRef = (SecKeychainItemRef)((itemRef) ? CFRetain(itemRef) : NULL); - } + BEGIN_SECKCITEMAPI - try - { - Item item = ItemImpl::required(itemImplRef); - item->getAttributesAndData(info, itemClass, attrList, length, outData); - __secapiresult=0; - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } + Item item = ItemImpl::required(__itemImplRef); + item->getAttributesAndData(info, itemClass, attrList, length, outData); - if (itemImplRef) { - CFRelease(itemImplRef); - } - return __secapiresult; -#endif + END_SECKCITEMAPI } @@ -249,7 +183,9 @@ OSStatus SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *data) { BEGIN_SECAPI - ItemImpl::freeAttributesAndData(attrList, data); + + ItemImpl::freeAttributesAndData(attrList, data); + END_SECAPI } @@ -257,136 +193,50 @@ SecKeychainItemFreeAttributesAndData(SecKeychainAttributeList *attrList, void *d OSStatus SecKeychainItemDelete(SecKeychainItemRef itemRef) { -#if !SECTRUST_OSX - BEGIN_SECAPI - Item item = ItemImpl::required( itemRef ); - Keychain keychain = item->keychain(); - // item must be persistent. - KCThrowIf_( !keychain, errSecInvalidItemRef ); - - /* - * Before deleting the item, delete any existing Extended Attributes. - */ - OSStatus ortn; - CFArrayRef attrNames = NULL; - ortn = SecKeychainItemCopyAllExtendedAttributes(itemRef, &attrNames, NULL); - if(ortn == errSecSuccess) { - CFIndex numAttrs = CFArrayGetCount(attrNames); - for(CFIndex dex=0; dex delete */ - SecKeychainItemSetExtendedAttribute(itemRef, attrName, NULL); - } - } - - /* now delete the item */ - keychain->deleteItem( item ); - END_SECAPI -#else - // if the item is a SecCertificateRef, must convert to an ItemImpl-based instance - // TODO: determine whether we need to actually look up the cert in a keychain here - OSStatus __secapiresult; - SecKeychainItemRef itemImplRef; - if (itemRef && CFGetTypeID(itemRef) == SecCertificateGetTypeID()) { - itemImplRef = (SecKeychainItemRef) SecCertificateCopyKeychainItem((SecCertificateRef)itemRef); - if (!itemImplRef) { - itemImplRef = (SecKeychainItemRef) SecCertificateCreateItemImplInstance((SecCertificateRef)itemRef); + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + Keychain keychain = item->keychain(); + // item must be persistent. + KCThrowIf_( !keychain, errSecInvalidItemRef ); + + /* + * Before deleting the item, delete any existing Extended Attributes. + */ + OSStatus ortn; + CFArrayRef attrNames = NULL; + ortn = SecKeychainItemCopyAllExtendedAttributes(__itemImplRef, &attrNames, NULL); + if(ortn == errSecSuccess) { + CFIndex numAttrs = CFArrayGetCount(attrNames); + for(CFIndex dex=0; dex delete */ + SecKeychainItemSetExtendedAttribute(__itemImplRef, attrName, NULL); } } - else { - itemImplRef = (SecKeychainItemRef)((itemRef) ? CFRetain(itemRef) : NULL); - } - - try - { - Item item = ItemImpl::required( itemImplRef ); - Keychain keychain = item->keychain(); - // item must be persistent. - KCThrowIf_( !keychain, errSecInvalidItemRef ); - - /* - * Before deleting the item, delete any existing Extended Attributes. - */ - OSStatus ortn; - CFArrayRef attrNames = NULL; - ortn = SecKeychainItemCopyAllExtendedAttributes(itemImplRef, &attrNames, NULL); - if(ortn == errSecSuccess) { - CFIndex numAttrs = CFArrayGetCount(attrNames); - for(CFIndex dex=0; dex delete */ - SecKeychainItemSetExtendedAttribute(itemImplRef, attrName, NULL); - } - } - /* now delete the item */ - keychain->deleteItem( item ); - __secapiresult=0; - } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } + /* now delete the item */ + keychain->deleteItem( item ); - if (itemImplRef) { - CFRelease(itemImplRef); - } - return __secapiresult; -#endif + END_SECKCITEMAPI } OSStatus SecKeychainItemCopyKeychain(SecKeychainItemRef itemRef, SecKeychainRef* keychainRef) { -#if !SECTRUST_OSX - BEGIN_SECAPI - // make sure this item has a keychain - Keychain kc = ItemImpl::required(itemRef)->keychain (); - if (kc == NULL) - { - MacOSError::throwMe(errSecNoSuchKeychain); - } - - Required(keychainRef) = kc->handle(); - END_SECAPI -#else - // if the item is a SecCertificateRef, must convert to an ItemImpl-based instance - // TODO: determine whether we need to actually look up the cert in a keychain here - OSStatus __secapiresult; - SecKeychainItemRef itemImplRef; - if (itemRef && CFGetTypeID(itemRef) == SecCertificateGetTypeID()) { - itemImplRef = (SecKeychainItemRef) SecCertificateCopyKeychainItem((SecCertificateRef)itemRef); - if (!itemImplRef) { - itemImplRef = (SecKeychainItemRef) SecCertificateCreateItemImplInstance((SecCertificateRef)itemRef); - } - } - else { - itemImplRef = (SecKeychainItemRef)((itemRef) ? CFRetain(itemRef) : NULL); - } + BEGIN_SECKCITEMAPI - try + // make sure this item has a keychain + Keychain kc = ItemImpl::required(__itemImplRef)->keychain(); + if (kc == NULL) { - // make sure this item has a keychain - Keychain kc = ItemImpl::required(itemImplRef)->keychain(); - if (kc == NULL) - { - MacOSError::throwMe(errSecNoSuchKeychain); - } - - Required(keychainRef) = kc->handle(); - __secapiresult=0; + MacOSError::throwMe(errSecNoSuchKeychain); } - catch (const MacOSError &err) { __secapiresult=err.osStatus(); } - catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } - catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } - catch (...) { __secapiresult=errSecInternalComponent; } - if (itemImplRef) { - CFRelease(itemImplRef); - } - return __secapiresult; -#endif + Required(keychainRef) = kc->handle(); + + END_SECKCITEMAPI } @@ -394,36 +244,36 @@ OSStatus SecKeychainItemCreateCopy(SecKeychainItemRef itemRef, SecKeychainRef destKeychainRef, SecAccessRef initialAccess, SecKeychainItemRef *itemCopy) { -#if SECTRUST_OSX - // bridge code for certificate items - if (itemRef && CFGetTypeID(itemRef) == SecCertificateGetTypeID()) { - return SecCertificateAddToKeychain((SecCertificateRef)itemRef, destKeychainRef); + BEGIN_SECKCITEMAPI + + Item copy = ItemImpl::required(__itemImplRef)->copyTo(Keychain::optional(destKeychainRef), Access::optional(initialAccess)); + if (itemCopy) { + *itemCopy = copy->handle(); } -#endif - BEGIN_SECAPI - Item copy = ItemImpl::required(itemRef)->copyTo(Keychain::optional(destKeychainRef), Access::optional(initialAccess)); - if (itemCopy) - *itemCopy = copy->handle(); - END_SECAPI + END_SECKCITEMAPI } OSStatus SecKeychainItemGetUniqueRecordID(SecKeychainItemRef itemRef, const CSSM_DB_UNIQUE_RECORD **uniqueRecordID) { - BEGIN_SECAPI - Required(uniqueRecordID) = ItemImpl::required(itemRef)->dbUniqueRecord(); - END_SECAPI + BEGIN_SECKCITEMAPI + + Required(uniqueRecordID) = ItemImpl::required(__itemImplRef)->dbUniqueRecord(); + + END_SECKCITEMAPI } OSStatus SecKeychainItemGetDLDBHandle(SecKeychainItemRef itemRef, CSSM_DL_DB_HANDLE* dldbHandle) { - BEGIN_SECAPI - *dldbHandle = ItemImpl::required(itemRef)->keychain()->database()->handle(); - END_SECAPI + BEGIN_SECKCITEMAPI + + *dldbHandle = ItemImpl::required(__itemImplRef)->keychain()->database()->handle(); + + END_SECKCITEMAPI } #if 0 @@ -432,9 +282,11 @@ OSStatus SecAccessCreateFromObject(CFTypeRef sourceRef, SecAccessRef *accessRef) { BEGIN_SECAPI + Required(accessRef); // preflight SecPointer access = new Access(*aclBearer(sourceRef)); *accessRef = access->handle(); + END_SECAPI } @@ -445,7 +297,9 @@ static OSStatus SecAccessModifyObject(SecAccessRef accessRef, CFTypeRef sourceRef) { BEGIN_SECAPI + Access::required(accessRef)->setAccess(*aclBearer(sourceRef), true); + END_SECAPI } #endif @@ -453,36 +307,37 @@ OSStatus SecAccessModifyObject(SecAccessRef accessRef, CFTypeRef sourceRef) OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef* accessRef) { - BEGIN_SECAPI + BEGIN_SECKCITEMAPI Required(accessRef); // preflight - SecPointer access = new Access(*aclBearer(reinterpret_cast(itemRef))); + SecPointer access = new Access(*aclBearer(reinterpret_cast(__itemImplRef))); *accessRef = access->handle(); - END_SECAPI + END_SECKCITEMAPI } OSStatus SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef accessRef) { - BEGIN_SECAPI + BEGIN_SECKCITEMAPI - Access::required(accessRef)->setAccess(*aclBearer(reinterpret_cast(itemRef)), true); + Access::required(accessRef)->setAccess(*aclBearer(reinterpret_cast(__itemImplRef)), true); - ItemImpl::required(itemRef)->postItemEvent (kSecUpdateEvent); + ItemImpl::required(__itemImplRef)->postItemEvent(kSecUpdateEvent); - END_SECAPI + END_SECKCITEMAPI } -OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) { - BEGIN_SECAPI +OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) +{ + BEGIN_SECKCITEMAPI OSStatus result; // try to unlock the keychain with this password first SecKeychainRef kc = NULL; - result = SecKeychainItemCopyKeychain(itemRef, &kc); + result = SecKeychainItemCopyKeychain(__itemImplRef, &kc); if(!result) { SecKeychainUnlock(kc, passwordLength, password, true); if(kc) { @@ -494,10 +349,10 @@ OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAcc CssmAutoData data(Allocator::standard(), password, passwordLength); AclFactory::PassphraseUnlockCredentials cred(data, Allocator::standard()); - Access::required(accessRef)->editAccess(*aclBearer(reinterpret_cast(itemRef)), true, cred.getAccessCredentials()); + Access::required(accessRef)->editAccess(*aclBearer(reinterpret_cast(__itemImplRef)), true, cred.getAccessCredentials()); ItemImpl::required(itemRef)->postItemEvent (kSecUpdateEvent); - END_SECAPI + END_SECKCITEMAPI } @@ -507,9 +362,11 @@ OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAcc */ OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const void* data) { - BEGIN_SECAPI - ItemImpl::required(itemRef)->setData(length, data); - END_SECAPI + BEGIN_SECKCITEMAPI + + ItemImpl::required(__itemImplRef)->setData(length, data); + + END_SECKCITEMAPI } /* Gets an item's data for legacy "KC" CoreServices APIs. @@ -517,24 +374,28 @@ OSStatus SecKeychainItemSetData(SecKeychainItemRef itemRef, UInt32 length, const */ OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, void* data, UInt32* actualLength) { - BEGIN_SECAPI - /* The caller either needs to specify data and maxLength or an actualLength, so we return either the data itself or the actual length of the data or both. */ - if (!((data && maxLength) || actualLength)) - MacOSError::throwMe(errSecParam); + BEGIN_SECKCITEMAPI - CssmDataContainer aData; - ItemImpl::required(itemRef)->getData(aData); - if (actualLength) - *actualLength = (UInt32)aData.length(); - - if (data) - { - // Make sure the buffer is big enough - if (aData.length() > maxLength) - MacOSError::throwMe(errSecBufferTooSmall); - memcpy(data, aData.data(), aData.length()); + /* The caller either needs to specify data and maxLength or an actualLength, + * so we return either the data itself or the actual length of the data or both. + */ + if (!((data && maxLength) || actualLength)) { + MacOSError::throwMe(errSecParam); + } + CssmDataContainer aData; + ItemImpl::required(__itemImplRef)->getData(aData); + if (actualLength) { + *actualLength = (UInt32)aData.length(); + } + if (data) { + // Make sure the buffer is big enough + if (aData.length() > maxLength) { + MacOSError::throwMe(errSecBufferTooSmall); } - END_SECAPI + memcpy(data, aData.data(), aData.length()); + } + + END_SECKCITEMAPI } /* Update a keychain item for legacy "KC" CoreServices APIs. @@ -542,38 +403,46 @@ OSStatus SecKeychainItemGetData(SecKeychainItemRef itemRef, UInt32 maxLength, vo */ OSStatus SecKeychainItemUpdate(SecKeychainItemRef itemRef) { - BEGIN_SECAPI - ItemImpl::required(itemRef)->update(); - END_SECAPI + BEGIN_SECKCITEMAPI + + ItemImpl::required(__itemImplRef)->update(); + + END_SECKCITEMAPI } /* Add a 'floating' keychain item without UI for legacy "KC" CoreServices APIs. */ OSStatus SecKeychainItemAddNoUI(SecKeychainRef keychainRef, SecKeychainItemRef itemRef) { - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - Keychain::optional(keychainRef)->add(item); - END_SECAPI + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + Keychain::optional(keychainRef)->add(item); + + END_SECKCITEMAPI } /* Add a 'floating' keychain item to the default keychain with possible UI for legacy "KC" Carbon APIs. */ OSStatus SecKeychainItemAdd(SecKeychainItemRef itemRef) { - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - Keychain defaultKeychain = globals().storageManager.defaultKeychainUI(item); - defaultKeychain->add(item); - END_SECAPI + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + Keychain defaultKeychain = globals().storageManager.defaultKeychainUI(item); + defaultKeychain->add(item); + + END_SECKCITEMAPI } /* Creates a floating keychain item for legacy "KC" CoreServices APIs */ OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UInt32 length, const void* data, SecKeychainItemRef* itemRef) { - BEGIN_SECAPI - RequiredParam(itemRef) = Item(itemClass, itemCreator, length, data, false)->handle(); + BEGIN_SECAPI + + RequiredParam(itemRef) = Item(itemClass, itemCreator, length, data, false)->handle(); + END_SECAPI } @@ -581,18 +450,22 @@ OSStatus SecKeychainItemCreateNew(SecItemClass itemClass, OSType itemCreator, UI */ OSStatus SecKeychainItemGetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute, UInt32* actualLength) { - BEGIN_SECAPI - ItemImpl::required(itemRef)->getAttribute(RequiredParam(attribute), actualLength); - END_SECAPI + BEGIN_SECKCITEMAPI + + ItemImpl::required(__itemImplRef)->getAttribute(RequiredParam(attribute), actualLength); + + END_SECKCITEMAPI } /* Sets an individual attribute for legacy "KC" CoreServices APIs */ OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttribute* attribute) { - BEGIN_SECAPI - ItemImpl::required(itemRef)->setAttribute(RequiredParam(attribute)); - END_SECAPI + BEGIN_SECKCITEMAPI + + ItemImpl::required(__itemImplRef)->setAttribute(RequiredParam(attribute)); + + END_SECKCITEMAPI } /* Finds a keychain item for legacy "KC" CoreServices APIs. @@ -602,45 +475,83 @@ OSStatus SecKeychainItemSetAttribute(SecKeychainItemRef itemRef, SecKeychainAttr */ OSStatus SecKeychainItemFindFirst(SecKeychainRef keychainRef, const SecKeychainAttributeList *attrList, SecKeychainSearchRef *searchRef, SecKeychainItemRef *itemRef) { - BEGIN_SECAPI - KCCursor cursor; - if (keychainRef) - cursor = KeychainImpl::required(keychainRef)->createCursor(attrList); - else - cursor = globals().storageManager.createCursor(attrList); - - Item item; - if (!cursor->next(item)) - return errSecItemNotFound; - - *itemRef=item->handle(); - if (searchRef) - *searchRef=cursor->handle(); + BEGIN_SECAPI + + KCCursor cursor; + if (keychainRef) { + cursor = KeychainImpl::required(keychainRef)->createCursor(attrList); + } else { + cursor = globals().storageManager.createCursor(attrList); + } + + Item item; + if (!cursor->next(item)) + return errSecItemNotFound; + + *itemRef=item->handle(); + if (searchRef) { + *searchRef=cursor->handle(); + } + END_SECAPI } #if SECTRUST_OSX static OSStatus SecKeychainItemCreatePersistentReferenceFromCertificate(SecCertificateRef certRef, - CFDataRef *persistentItemRef) + CFDataRef *persistentItemRef, Boolean isIdentity) { - if (!certRef || !persistentItemRef) + OSStatus __secapiresult; + if (!certRef || !persistentItemRef) { return errSecParam; + } + + // If we already have a keychain item, we won't need to look it up by serial and issuer + SecKeychainItemRef kcItem = NULL; + if (SecCertificateIsItemImplInstance(certRef)) { + kcItem = (SecKeychainItemRef) CFRetain(certRef); + } + else { + kcItem = (SecKeychainItemRef) SecCertificateCopyKeychainItem(certRef); + } + if (kcItem) { + __secapiresult = errSecParam; + try { + Item item = ItemImpl::required((kcItem)); + item->copyPersistentReference(*persistentItemRef, isIdentity); + __secapiresult = errSecSuccess; + } + catch(...) {} + CFRelease(kcItem); + if (__secapiresult == errSecSuccess) { + return __secapiresult; + } + } + + // Certificate does not have a keychain item reference; look it up by serial and issuer + SecCertificateRef certItem = NULL; + if (SecCertificateIsItemImplInstance(certRef)) { + certItem = SecCertificateCreateFromItemImplInstance(certRef); + } + else { + certItem = (SecCertificateRef) CFRetain(certRef); + } - OSStatus __secapiresult; CFErrorRef errorRef = NULL; - CFDataRef serialData = SecCertificateCopySerialNumber(certRef, &errorRef); + CFDataRef serialData = SecCertificateCopySerialNumber(certItem, &errorRef); if (errorRef) { CFIndex err = CFErrorGetCode(errorRef); CFRelease(errorRef); if (serialData) { CFRelease(serialData); } + if (certItem) { CFRelease(certItem); } return (OSStatus)err; } - CFDataRef issuerData = SecCertificateCopyNormalizedIssuerContent(certRef, &errorRef); + CFDataRef issuerData = SecCertificateCopyNormalizedIssuerContent(certItem, &errorRef); if (errorRef) { CFIndex err = CFErrorGetCode(errorRef); CFRelease(errorRef); if (serialData) { CFRelease(serialData); } if (issuerData) { CFRelease(issuerData); } + if (certItem) { CFRelease(certItem); } return (OSStatus)err; } @@ -665,6 +576,8 @@ static OSStatus SecKeychainItemCreatePersistentReferenceFromCertificate(SecCerti CFRelease(serialData); if (issuerData) CFRelease(issuerData); + if (certItem) + CFRelease(certItem); return __secapiresult; } @@ -677,8 +590,9 @@ OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CF KCThrowParamErrIf_(!itemRef || !persistentItemRef); Item item; - bool isIdentityRef = (CFGetTypeID(itemRef) == SecIdentityGetTypeID()) ? true : false; - bool isCertificateRef = (CFGetTypeID(itemRef) == SecCertificateGetTypeID()) ? true : false; + CFTypeID itemType = (itemRef) ? CFGetTypeID(itemRef) ? 0; + bool isIdentityRef = (itemType == SecIdentityGetTypeID()) ? true : false; + bool isCertificateRef = (itemType == SecCertificateGetTypeID()) ? true : false; if (isIdentityRef) { SecPointer certificatePtr(Identity::required((SecIdentityRef)itemRef)->certificate()); SecCertificateRef certificateRef = certificatePtr->handle(false); @@ -700,17 +614,32 @@ OSStatus SecKeychainItemCreatePersistentReference(SecKeychainItemRef itemRef, CF if (!itemRef || !persistentItemRef) { return errSecParam; } - bool isIdentityRef = (CFGetTypeID(itemRef) == SecIdentityGetTypeID()) ? true : false; - bool isCertificateRef = (CFGetTypeID(itemRef) == SecCertificateGetTypeID()) ? true : false; + // first, query the iOS keychain + { + const void *keys[] = { kSecValueRef, kSecReturnPersistentRef, kSecAttrNoLegacy }; + const void *values[] = { itemRef, kCFBooleanTrue, kCFBooleanTrue }; + CFRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)persistentItemRef); + if (status == errSecSuccess) { + return status; + } + } + // otherwise, handle certificate SecCertificateRef certRef = NULL; - if (isIdentityRef) { + CFTypeID itemType = CFGetTypeID(itemRef); + bool isIdentity = false; + if (itemType == SecIdentityGetTypeID()) { SecIdentityCopyCertificate((SecIdentityRef)itemRef, &certRef); + isIdentity = true; } - else if (isCertificateRef) { + else if (itemType == SecCertificateGetTypeID()) { certRef = (SecCertificateRef) CFRetain(itemRef); } if (certRef) { - OSStatus status = SecKeychainItemCreatePersistentReferenceFromCertificate(certRef, persistentItemRef); + OSStatus status = SecKeychainItemCreatePersistentReferenceFromCertificate(certRef, persistentItemRef, isIdentity); CFRelease(certRef); return status; } @@ -729,6 +658,20 @@ OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, BEGIN_SECAPI KCThrowParamErrIf_(!persistentItemRef || !itemRef); + // first, query the iOS keychain + { + const void *keys[] = { kSecValuePersistentRef, kSecReturnRef, kSecAttrNoLegacy}; + const void *values[] = { persistentItemRef, kCFBooleanTrue, kCFBooleanTrue }; + CFRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + OSStatus status = SecItemCopyMatching(query, (CFTypeRef *)itemRef); + if (status == errSecSuccess) { + return status; + } + } + // otherwise, proceed as usual for keychain item CFTypeRef result = NULL; bool isIdentityRef = false; Item item = ItemImpl::makeFromPersistentReference(persistentItemRef, &isIdentityRef); @@ -749,7 +692,7 @@ OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, #if SECTRUST_OSX /* see if we should convert outgoing item to a unified SecCertificateRef */ SecItemClass tmpItemClass = Schema::itemClassFor(item->recordType()); - if (tmpItemClass == kSecCertificateItemClass) { + if (tmpItemClass == kSecCertificateItemClass && !isIdentityRef) { SecPointer certificate(static_cast(&*item)); CssmData certData = certificate->data(); CFDataRef data = NULL; @@ -783,14 +726,16 @@ OSStatus SecKeychainItemCopyFromPersistentReference(CFDataRef persistentItemRef, OSStatus SecKeychainItemCopyRecordIdentifier(SecKeychainItemRef itemRef, CFDataRef *recordIdentifier) { - BEGIN_SECAPI - CSSM_DATA data; - RequiredParam (recordIdentifier); - Item item = ItemImpl::required(itemRef); - item->copyRecordIdentifier (data); - *recordIdentifier = ::CFDataCreate(kCFAllocatorDefault, (UInt8*) data.Data, data.Length); - free (data.Data); - END_SECAPI + BEGIN_SECKCITEMAPI + + CSSM_DATA data; + RequiredParam (recordIdentifier); + Item item = ItemImpl::required(__itemImplRef); + item->copyRecordIdentifier (data); + *recordIdentifier = ::CFDataCreate(kCFAllocatorDefault, (UInt8*) data.Data, data.Length); + free (data.Data); + + END_SECKCITEMAPI } OSStatus @@ -799,51 +744,53 @@ SecKeychainItemCopyFromRecordIdentifier(SecKeychainRef keychainRef, CFDataRef recordIdentifier) { BEGIN_SECAPI - // make a local Keychain reference - RequiredParam (keychainRef); - Keychain keychain = KeychainImpl::optional (keychainRef); - RequiredParam (itemRef); - RequiredParam (recordIdentifier); - - Db db(keychain->database()); - - // make a raw database call to get the data - CSSM_DL_DB_HANDLE dbHandle = db.handle (); - CSSM_DB_UNIQUE_RECORD uniqueRecord; - - // according to source, we should be able to reconsitute the uniqueRecord - // from the data we earlier retained - - // prepare the record id - memset (&uniqueRecord, 0, sizeof (uniqueRecord)); - uniqueRecord.RecordIdentifier.Data = (uint8*) CFDataGetBytePtr (recordIdentifier); - uniqueRecord.RecordIdentifier.Length = CFDataGetLength (recordIdentifier); - - // convert this unique id to a CSSM_DB_UNIQUE_RECORD that works for the CSP/DL - CSSM_DB_UNIQUE_RECORD_PTR outputUniqueRecordPtr; - CSSM_RETURN result; - result = CSSM_DL_PassThrough (dbHandle, CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER, &uniqueRecord, (void**) &outputUniqueRecordPtr); - KCThrowIf_(result != 0, errSecItemNotFound); - - // from this, get the record type - CSSM_DB_RECORD_ATTRIBUTE_DATA attributeData; - memset (&attributeData, 0, sizeof (attributeData)); - - result = CSSM_DL_DataGetFromUniqueRecordId (dbHandle, outputUniqueRecordPtr, &attributeData, NULL); - KCThrowIf_(result != 0, errSecItemNotFound); - CSSM_DB_RECORDTYPE recordType = attributeData.DataRecordType; - - // make the unique record item -- precursor to creation of a SecKeychainItemRef - DbUniqueRecord unique(db); - CSSM_DB_UNIQUE_RECORD_PTR *uniquePtr = unique; - *uniquePtr = outputUniqueRecordPtr; - - unique->activate (); - Item item = keychain->item (recordType, unique); - if (itemRef) - { - *itemRef = item->handle(); - } + + // make a local Keychain reference + RequiredParam (keychainRef); + Keychain keychain = KeychainImpl::optional (keychainRef); + RequiredParam (itemRef); + RequiredParam (recordIdentifier); + + Db db(keychain->database()); + + // make a raw database call to get the data + CSSM_DL_DB_HANDLE dbHandle = db.handle (); + CSSM_DB_UNIQUE_RECORD uniqueRecord; + + // according to source, we should be able to reconsitute the uniqueRecord + // from the data we earlier retained + + // prepare the record id + memset (&uniqueRecord, 0, sizeof (uniqueRecord)); + uniqueRecord.RecordIdentifier.Data = (uint8*) CFDataGetBytePtr (recordIdentifier); + uniqueRecord.RecordIdentifier.Length = CFDataGetLength (recordIdentifier); + + // convert this unique id to a CSSM_DB_UNIQUE_RECORD that works for the CSP/DL + CSSM_DB_UNIQUE_RECORD_PTR outputUniqueRecordPtr; + CSSM_RETURN result; + result = CSSM_DL_PassThrough (dbHandle, CSSM_APPLECSPDL_DB_CONVERT_RECORD_IDENTIFIER, &uniqueRecord, (void**) &outputUniqueRecordPtr); + KCThrowIf_(result != 0, errSecItemNotFound); + + // from this, get the record type + CSSM_DB_RECORD_ATTRIBUTE_DATA attributeData; + memset (&attributeData, 0, sizeof (attributeData)); + + result = CSSM_DL_DataGetFromUniqueRecordId (dbHandle, outputUniqueRecordPtr, &attributeData, NULL); + KCThrowIf_(result != 0, errSecItemNotFound); + CSSM_DB_RECORDTYPE recordType = attributeData.DataRecordType; + + // make the unique record item -- precursor to creation of a SecKeychainItemRef + DbUniqueRecord unique(db); + CSSM_DB_UNIQUE_RECORD_PTR *uniquePtr = unique; + *uniquePtr = outputUniqueRecordPtr; + + unique->activate (); + Item item = keychain->item (recordType, unique); + if (itemRef) + { + *itemRef = item->handle(); + } + END_SECAPI } @@ -851,44 +798,44 @@ OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, UInt32 length, const void *data, SecKeychainRef keychainRef, SecAccessRef initialAccess, SecKeychainItemRef *itemRef, CFDataRef *localID) { - BEGIN_SECAPI - KCThrowParamErrIf_(length!=0 && data==NULL); + BEGIN_SECAPI - RequiredParam (localID); - RequiredParam (keychainRef); + KCThrowParamErrIf_(length!=0 && data==NULL); + RequiredParam (localID); + RequiredParam (keychainRef); - Item item(itemClass, (uint32) 0, length, data, true); - if (initialAccess) - item->setAccess(Access::required(initialAccess)); + Item item(itemClass, (uint32) 0, length, data, true); + if (initialAccess) + item->setAccess(Access::required(initialAccess)); - Keychain keychain = Keychain::optional(keychainRef); - if (!keychain->exists()) - { - MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. - } + Keychain keychain = Keychain::optional(keychainRef); + if (!keychain->exists()) + { + MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. + } - item->doNotEncrypt (); - try - { - keychain->add(item); - } - catch (const CommonError &err) + item->doNotEncrypt (); + try + { + keychain->add(item); + } + catch (const CommonError &err) + { + if (err.osStatus () == errSecNoSuchClass) { - if (err.osStatus () == errSecNoSuchClass) + // the only time this should happen is if the item is a certificate (for keychain syncing) + if (itemClass == CSSM_DL_DB_RECORD_X509_CERTIFICATE) { - // the only time this should happen is if the item is a certificate (for keychain syncing) - if (itemClass == CSSM_DL_DB_RECORD_X509_CERTIFICATE) - { - // create the certificate relation - Db db(keychain->database()); + // create the certificate relation + Db db(keychain->database()); - db->createRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE, + db->createRelation(CSSM_DL_DB_RECORD_X509_CERTIFICATE, "CSSM_DL_DB_RECORD_X509_CERTIFICATE", Schema::X509CertificateSchemaAttributeCount, Schema::X509CertificateSchemaAttributeList, Schema::X509CertificateSchemaIndexCount, Schema::X509CertificateSchemaIndexList); - keychain->keychainSchema()->didCreateRelation( + keychain->keychainSchema()->didCreateRelation( CSSM_DL_DB_RECORD_X509_CERTIFICATE, "CSSM_DL_DB_RECORD_X509_CERTIFICATE", Schema::X509CertificateSchemaAttributeCount, @@ -896,24 +843,25 @@ OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, Schema::X509CertificateSchemaIndexCount, Schema::X509CertificateSchemaIndexList); - // add the item again - keychain->add(item); - } - } - else - { - throw; + // add the item again + keychain->add(item); } } + else + { + throw; + } + } - if (itemRef) - *itemRef = item->handle(); + if (itemRef) + *itemRef = item->handle(); - CSSM_DATA recordID; - item->copyRecordIdentifier (recordID); + CSSM_DATA recordID; + item->copyRecordIdentifier (recordID); + + *localID = CFDataCreate(kCFAllocatorDefault, (UInt8*) recordID.Data, recordID.Length); + free (recordID.Data); - *localID = CFDataCreate(kCFAllocatorDefault, (UInt8*) recordID.Data, recordID.Length); - free (recordID.Data); END_SECAPI } @@ -921,18 +869,22 @@ OSStatus SecKeychainItemCopyAttributesAndEncryptedData(SecKeychainItemRef itemRe SecItemClass *itemClass, SecKeychainAttributeList **attrList, UInt32 *length, void **outData) { - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - item->doNotEncrypt (); - item->getAttributesAndData(info, itemClass, attrList, length, outData); - END_SECAPI + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + item->doNotEncrypt (); + item->getAttributesAndData(info, itemClass, attrList, length, outData); + + END_SECKCITEMAPI } OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 length, const void *data) { - BEGIN_SECAPI - Item item = ItemImpl::required(itemRef); - item->doNotEncrypt (); - item->modifyAttributesAndData(NULL, length, data); - END_SECAPI + BEGIN_SECKCITEMAPI + + Item item = ItemImpl::required(__itemImplRef); + item->doNotEncrypt (); + item->modifyAttributesAndData(NULL, length, data); + + END_SECKCITEMAPI } diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.h b/OSX/libsecurity_keychain/lib/SecKeychainItem.h index a83533de..4b579812 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.h @@ -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 initialAccess, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemCopy); + SecAccessRef __nullable initialAccess, SecKeychainItemRef * __nonnull CF_RETURNS_RETAINED itemCopy); /*! @function SecKeychainItemCreatePersistentReference diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp index 1f7e0061..0f34defe 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemExtendedAttributes.cpp @@ -42,6 +42,8 @@ static CFTypeID SecKeychainItemExtendedAttributesGetTypeID(void) } #endif +extern "C" Boolean SecKeyIsCDSAKey(SecKeyRef ref); + /* * Determine if incoming itemRef can be considered for * this mechanism; throw if not. @@ -52,7 +54,7 @@ static void isItemRefCapable( CFTypeID id = CFGetTypeID(itemRef); if((id == gTypes().ItemImpl.typeID) || (id == gTypes().Certificate.typeID) || - (id == gTypes().KeyItem.typeID)) { + (id == SecKeyGetTypeID() && SecKeyIsCDSAKey((SecKeyRef)itemRef))) { return; } else { @@ -140,9 +142,9 @@ OSStatus SecKeychainItemSetExtendedAttribute( CFStringRef attrName, CFDataRef attrValue) /* NULL means delete the attribute */ { -#if SECTRUST_OSX -#warning This needs to detect SecCertificateRef items, and when it does, SecKeychainItemDelete must be updated -#endif + // + //%%% This needs to detect SecCertificateRef items, and when it does, SecKeychainItemDelete must be updated + BEGIN_SECAPI if((itemRef == NULL) || (attrName == NULL)) { @@ -190,9 +192,9 @@ OSStatus SecKeychainItemCopyExtendedAttribute( CFStringRef attrName, CFDataRef *attrValue) /* RETURNED */ { -#if SECTRUST_OSX -#warning This needs to detect SecCertificateRef items -#endif + // + //%%% This needs to detect SecCertificateRef items + BEGIN_SECAPI if((itemRef == NULL) || (attrName == NULL) || (attrValue == NULL)) { @@ -231,9 +233,9 @@ OSStatus SecKeychainItemCopyAllExtendedAttributes( CFArrayRef *attrValues) /* optional, RETURNED, each element is a * CFDataRef */ { -#if SECTRUST_OSX -#warning This needs to detect SecCertificateRef items, and when it does, SecKeychainItemDelete must be updated -#endif + // + //%%% This needs to detect SecCertificateRef items, and when it does, SecKeychainItemDelete must be updated + BEGIN_SECAPI if((itemRef == NULL) || (attrNames == NULL)) { diff --git a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h index e9650f96..d504b4a1 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h @@ -114,10 +114,26 @@ OSStatus SecKeychainSystemKeychainCheckWouldDeadlock() __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); +OSStatus SecKeychainEraseUnlockKey(SecKeychainRef systemKeychainRef, CFStringRef username) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); +/* Token login support */ +OSStatus SecKeychainStoreUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash, CFStringRef tokenID, CFDataRef wrapPubKeyHash, SecKeychainRef userKeychain, CFStringRef password) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); +OSStatus SecKeychainEraseUnlockKeyWithPubKeyHash(CFDataRef pubKeyHash) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); + +/* calls to interact with keychain versions */ OSStatus SecKeychainGetKeychainVersion(SecKeychainRef keychain, UInt32* version) __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); +OSStatus SecKeychainAttemptMigrationWithMasterKey(SecKeychainRef keychain, UInt32 version, const char* masterKeyFilename) + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); + +/* calls for testing only */ +OSStatus SecKeychainGetUserPromptAttempts(uint32_t* attempts) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_NA); + /*! @function SecKeychainMDSInstall Set up MDS. diff --git a/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp b/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp index 68eb54a0..2ba38d91 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainSearch.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004,2011-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -80,7 +80,7 @@ SecKeychainSearchCreateFromAttributesExtended(CFTypeRef keychainOrArray, SecItem OSStatus SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *itemRef) { - BEGIN_SECAPI + BEGIN_SECAPI RequiredParam(itemRef); Item item; @@ -104,8 +104,10 @@ SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *it } if (!data) { /* zero-length or otherwise bad cert data; skip to next item */ - CFRelease(*itemRef); - *itemRef = NULL; + if (*itemRef) { + CFRelease(*itemRef); + *itemRef = NULL; + } if (!itemCursor->next(item)) return errSecItemNotFound; *itemRef=item->handle(); @@ -117,12 +119,24 @@ SecKeychainSearchCopyNext(SecKeychainSearchRef searchRef, SecKeychainItemRef *it CFRelease(data); if (tmpRef) CFRelease(tmpRef); + if (NULL == *itemRef) { + /* unable to create unified certificate item; skip to next item */ + if (!itemCursor->next(item)) + return errSecItemNotFound; + *itemRef=item->handle(); + continue; + } itemChecked = true; - } + } else { itemChecked = true; } } while (!itemChecked); + + if (NULL == *itemRef) { + /* never permit a NULL item reference to be returned without an error result */ + return errSecItemNotFound; + } #endif END_SECAPI diff --git a/OSX/libsecurity_keychain/lib/SecPassword.cpp b/OSX/libsecurity_keychain/lib/SecPassword.cpp index c5989d05..477c9bac 100644 --- a/OSX/libsecurity_keychain/lib/SecPassword.cpp +++ b/OSX/libsecurity_keychain/lib/SecPassword.cpp @@ -179,7 +179,7 @@ SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt3 AuthorizationItemSet envSet = { sizeof(envRights) / sizeof(*envRights), envRights }; - secdebug("SecPassword", "dialog(%s)%s%s%s.", right.name, tries?" retry":"", keychain?" show-add-keychain":"", addToKeychain?" save-to-keychain":""); + secinfo("SecPassword", "dialog(%s)%s%s%s.", right.name, tries?" retry":"", keychain?" show-add-keychain":"", addToKeychain?" save-to-keychain":""); status = AuthorizationCopyRights(authRef, &rightSet, &envSet, kAuthorizationFlagDefaults|kAuthorizationFlagInteractionAllowed|kAuthorizationFlagExtendRights, NULL); @@ -224,14 +224,14 @@ SecPasswordAction(SecPasswordRef itemRef, CFTypeRef message, UInt32 flags, UInt3 if (data) *data = passwordData; - secdebug("SecPassword", "Got password (%u,%p).", (unsigned int)passwordLength, passwordData); + secinfo("SecPassword", "Got password (%u,%p).", (unsigned int)passwordLength, passwordData); } else if (!strcmp(AGENT_ADD_TO_KEYCHAIN, item.name)) { bool remember = (item.value && item.valueLength == strlen("YES") && !memcmp("YES", static_cast(item.value), item.valueLength)); passwordRef->setRememberInKeychain(remember); if (remember) - secdebug("SecPassword", "User wants to add the password to the Keychain."); + secinfo("SecPassword", "User wants to add the password to the Keychain."); } } } diff --git a/OSX/libsecurity_keychain/lib/SecPolicy.cpp b/OSX/libsecurity_keychain/lib/SecPolicy.cpp index e4515732..9c89e06d 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicy.cpp +++ b/OSX/libsecurity_keychain/lib/SecPolicy.cpp @@ -1,3 +1,4 @@ + /* * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved. * @@ -40,6 +41,7 @@ #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); +#if !SECTRUST_OSX SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2"); SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3"); SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8"); @@ -61,46 +63,36 @@ SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24"); SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25"); SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26"); SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27"); -#if TARGET_OS_IPHONE SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28"); SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29"); /* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */ -SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30"); -SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31"); -SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32"); -#endif +SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113635.100.1.30"); +SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113635.100.1.31"); +SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113635.100.1.32"); SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33"); SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34"); -SEC_CONST_DECL (kSecPolicyApplePPQSigning, "1.2.840.113625.100.1.35"); -SEC_CONST_DECL (kSecPolicyAppleTestPPQSigning, "1.2.840.113625.100.1.36"); -SEC_CONST_DECL (kSecPolicyAppleATVAppSigning, "1.2.840.113625.100.1.37"); -SEC_CONST_DECL (kSecPolicyAppleTestATVAppSigning, "1.2.840.113625.100.1.38"); -SEC_CONST_DECL (kSecPolicyApplePayIssuerEncryption, "1.2.840.113625.100.1.39"); -SEC_CONST_DECL (kSecPolicyAppleOSXProvisioningProfileSigning, "1.2.840.113625.100.1.40"); -SEC_CONST_DECL (kSecPolicyAppleAST2DiagnosticsServerAuth, "1.2.840.113625.100.1.42"); +SEC_CONST_DECL (kSecPolicyApplePPQSigning, "1.2.840.113635.100.1.35"); +SEC_CONST_DECL (kSecPolicyAppleTestPPQSigning, "1.2.840.113635.100.1.36"); +SEC_CONST_DECL (kSecPolicyApplePayIssuerEncryption, "1.2.840.113635.100.1.39"); +SEC_CONST_DECL (kSecPolicyAppleOSXProvisioningProfileSigning, "1.2.840.113635.100.1.40"); +SEC_CONST_DECL (kSecPolicyAppleAST2DiagnosticsServerAuth, "1.2.840.113635.100.1.42"); +SEC_CONST_DECL (kSecPolicyAppleEscrowProxyServerAuth, "1.2.840.113635.100.1.43"); +SEC_CONST_DECL (kSecPolicyAppleFMiPServerAuth, "1.2.840.113635.100.1.44"); SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient"); SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags"); SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier"); - -SEC_CONST_DECL (kSecPolicyKU_DigitalSignature, "CE_KU_DigitalSignature"); -SEC_CONST_DECL (kSecPolicyKU_NonRepudiation, "CE_KU_NonRepudiation"); -SEC_CONST_DECL (kSecPolicyKU_KeyEncipherment, "CE_KU_KeyEncipherment"); -SEC_CONST_DECL (kSecPolicyKU_DataEncipherment, "CE_KU_DataEncipherment"); -SEC_CONST_DECL (kSecPolicyKU_KeyAgreement, "CE_KU_KeyAgreement"); -SEC_CONST_DECL (kSecPolicyKU_KeyCertSign, "CE_KU_KeyCertSign"); -SEC_CONST_DECL (kSecPolicyKU_CRLSign, "CE_KU_CRLSign"); -SEC_CONST_DECL (kSecPolicyKU_EncipherOnly, "CE_KU_EncipherOnly"); -SEC_CONST_DECL (kSecPolicyKU_DecipherOnly, "CE_KU_DecipherOnly"); +#else +/* Some of these aren't defined in SecPolicy.c, but used here. */ +SEC_CONST_DECL (kSecPolicyAppleiChat, "1.2.840.113635.100.1.12"); +#endif // Private functions extern "C" { -CFArrayRef SecPolicyCopyEscrowRootCertificates(void); #if SECTRUST_OSX -CFStringRef SecPolicyGetOidString(SecPolicyRef policy); CFDictionaryRef SecPolicyGetOptions(SecPolicyRef policy); void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value); #endif @@ -163,6 +155,34 @@ const oidmap_entry_t oidmap[] = { { kSecPolicyAppleOSXProvisioningProfileSigning, &CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING }, }; +#if SECTRUST_OSX +const oidmap_entry_t oidmap_priv[] = { + { CFSTR("basicX509"), &CSSMOID_APPLE_X509_BASIC }, + { CFSTR("sslServer"), &CSSMOID_APPLE_TP_SSL }, + { CFSTR("sslClient"), &CSSMOID_APPLE_TP_SSL }, + { CFSTR("SMIME"), &CSSMOID_APPLE_TP_SMIME }, + { CFSTR("eapServer"), &CSSMOID_APPLE_TP_EAP }, + { CFSTR("eapClient"), &CSSMOID_APPLE_TP_EAP }, + { CFSTR("AppleSWUpdateSigning"), &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING }, + { CFSTR("ipsecServer"), &CSSMOID_APPLE_TP_IP_SEC }, + { CFSTR("ipsecClient"), &CSSMOID_APPLE_TP_IP_SEC }, + { CFSTR("CodeSigning"), &CSSMOID_APPLE_TP_CODE_SIGNING }, + { CFSTR("PackageSigning"), &CSSMOID_APPLE_TP_PACKAGE_SIGNING }, + { CFSTR("AppleIDAuthority"), &CSSMOID_APPLE_TP_APPLEID_SHARING }, + { CFSTR("MacAppStoreReceipt"), &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT }, + { CFSTR("AppleTimeStamping"), &CSSMOID_APPLE_TP_TIMESTAMPING }, + { CFSTR("revocation"), &CSSMOID_APPLE_TP_REVOCATION }, + { CFSTR("ApplePassbook"), &CSSMOID_APPLE_TP_PASSBOOK_SIGNING }, + { CFSTR("AppleMobileStore"), &CSSMOID_APPLE_TP_MOBILE_STORE }, + { CFSTR("AppleEscrowService"), &CSSMOID_APPLE_TP_ESCROW_SERVICE }, + { CFSTR("AppleProfileSigner"), &CSSMOID_APPLE_TP_PROFILE_SIGNING }, + { CFSTR("AppleQAProfileSigner"), &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING }, + { CFSTR("AppleTestMobileStore"), &CSSMOID_APPLE_TP_TEST_MOBILE_STORE }, + { CFSTR("ApplePCSEscrowService"), &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE }, + { CFSTR("AppleOSXProvisioningProfileSigning"), &CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING }, +}; +#endif + // // CF boilerplate // @@ -391,7 +411,6 @@ SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) OSStatus status = errSecSuccess; CFDataRef data = NULL; CFStringRef name = NULL; - CFNumberRef cnum = NULL; CFStringRef oid = (CFStringRef) SecPolicyGetOidString(policyRef); if (!oid) { syslog(LOG_ERR, "SecPolicySetValue: unknown policy OID"); @@ -463,27 +482,27 @@ SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) CSSM_APPLE_TP_CRL_OPTIONS *opts = (CSSM_APPLE_TP_CRL_OPTIONS *)value->Data; if (opts->Version == CSSM_APPLE_TP_CRL_OPTS_VERSION) { CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags = opts->CrlFlags; - CFOptionFlags revocationFlags = 0; if ((crlFlags & CSSM_TP_ACTION_FETCH_CRL_FROM_NET) == 0) { /* disable network access */ - revocationFlags |= kSecRevocationNetworkAccessDisabled; + SecPolicySetOptionsValue(policyRef, CFSTR("NoNetworkAccess") /*kSecPolicyCheckNoNetworkAccess*/, kCFBooleanTrue); } if ((crlFlags & CSSM_TP_ACTION_CRL_SUFFICIENT) == 0) { - /* if OCSP method is not sufficient, must use CRL */ - revocationFlags |= (kSecRevocationCRLMethod | kSecRevocationPreferCRL); + /* if CRL method is not sufficient, must use OCSP */ + SecPolicySetOptionsValue(policyRef, CFSTR("Revocation") /*kSecPolicyCheckRevocation*/, + CFSTR("OCSP")/*kSecPolicyCheckRevocationOCSP*/); } else { /* either method is sufficient */ - revocationFlags |= kSecRevocationUseAnyAvailableMethod; + SecPolicySetOptionsValue(policyRef, CFSTR("Revocation") /*kSecPolicyCheckRevocation*/, + CFSTR("AnyRevocationMethod") /*kSecPolicyCheckRevocationAny*/); } + if ((crlFlags & CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT) != 0) { /* require a response */ - revocationFlags |= kSecRevocationRequirePositiveResponse; + SecPolicySetOptionsValue(policyRef, + CFSTR("RevocationResponseRequired") /*kSecPolicyCheckRevocationResponseRequired*/, + kCFBooleanTrue); } - cnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &revocationFlags); - if (cnum) { - SecPolicySetOptionsValue(policyRef, kSecPolicyRevocationFlags, cnum); - } - } + } } else { syslog(LOG_ERR, "SecPolicySetValue: unrecognized policy OID"); @@ -491,7 +510,6 @@ SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) } if (data) { CFRelease(data); } if (name) { CFRelease(name); } - if (cnum) { CFRelease(cnum); } return status; #endif } @@ -810,71 +828,84 @@ SecPolicyCreateRevocation(CFOptionFlags revocationFlags) } #endif -/* OS X only: deprecated SPI entry point */ -/* new in 10.9 ***FIXME*** TO BE REMOVED */ -CFArrayRef SecPolicyCopyEscrowRootCertificates(void) -{ - return SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot); -} - +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateApplePushServiceLegacy(CFStringRef hostname) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif +#if !SECTRUST_OSX +/* new in 10.11.4 */ SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif -SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) +#if !SECTRUST_OSX +/* new in 10.12 */ +SecPolicyRef SecPolicyCreateAppleEscrowProxyService(CFStringRef hostname, CFDictionaryRef __unused context) { return SecPolicyCreateSSL(true, hostname); } +#endif #if !SECTRUST_OSX -/* new in 10.11 */ -SecPolicyRef SecPolicyCreateAppleATVAppSigning(void) +/* new in 10.12 */ +SecPolicyRef SecPolicyCreateAppleFMiPService(CFStringRef hostname, CFDictionaryRef __unused context) { - return _SecPolicyCreateWithOID(kSecPolicyAppleX509Basic); + return SecPolicyCreateSSL(true, hostname); } #endif #if !SECTRUST_OSX -/* new in 10.11 */ -SecPolicyRef SecPolicyCreateTestAppleATVAppSigning(void) +/* new in 10.11.4 */ +SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) { - return _SecPolicyCreateWithOID(kSecPolicyAppleX509Basic); + return SecPolicyCreateSSL(true, hostname); } #endif @@ -969,16 +1000,17 @@ SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray) }; #else /* implement with unified SecPolicyRef instances */ - /* %%% FIXME revisit this since SecPolicyCreateWithOID is OSX-only; */ - /* should use SecPolicyCreateWithProperties instead */ SecPolicyRef policy = NULL; CFMutableArrayRef resultPolicyArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - policy = SecPolicyCreateWithOID(kSecPolicyAppleTimeStamping); + if (!resultPolicyArray) { + return NULL; + } + policy = SecPolicyCreateWithProperties(kSecPolicyAppleTimeStamping, NULL); if (policy) { CFArrayAppendValue(resultPolicyArray, policy); CFReleaseNull(policy); } - policy = SecPolicyCreateWithOID(kSecPolicyAppleRevocation); + policy = SecPolicyCreateWithProperties(kSecPolicyAppleRevocation, NULL); if (policy) { CFArrayAppendValue(resultPolicyArray, policy); CFReleaseNull(policy); diff --git a/OSX/libsecurity_keychain/lib/SecPolicy.h b/OSX/libsecurity_keychain/lib/SecPolicy.h index 5e80bc92..eceb7c89 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicy.h +++ b/OSX/libsecurity_keychain/lib/SecPolicy.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-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, @@ -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@ */ @@ -25,7 +25,7 @@ @header SecPolicy The functions provided in SecPolicy.h provide an interface to various X.509 certificate trust policies. -*/ + */ #ifndef _SECURITY_SECPOLICY_H_ #define _SECURITY_SECPOLICY_H_ @@ -34,9 +34,7 @@ #include #include -#if defined(__cplusplus) -extern "C" { -#endif +__BEGIN_DECLS CF_ASSUME_NONNULL_BEGIN CF_IMPLICIT_BRIDGING_ENABLED @@ -48,8 +46,8 @@ CF_IMPLICIT_BRIDGING_ENABLED @constant kSecPolicyAppleSSL @constant kSecPolicyAppleSMIME @constant kSecPolicyAppleEAP - @constant kSecPolicyAppleIPsec @constant kSecPolicyAppleiChat + @constant kSecPolicyAppleIPsec @constant kSecPolicyApplePKINITClient @constant kSecPolicyApplePKINITServer @constant kSecPolicyAppleCodeSigning @@ -58,8 +56,8 @@ CF_IMPLICIT_BRIDGING_ENABLED @constant kSecPolicyAppleTimeStamping @constant kSecPolicyAppleRevocation @constant kSecPolicyApplePassbookSigning - @constant kSecPolicyApplePayIssuerEncryption -*/ + @constant kSecPolicyApplePayIssuerEncryption + */ extern const CFStringRef kSecPolicyAppleX509Basic __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleSSL @@ -70,8 +68,10 @@ extern const CFStringRef kSecPolicyAppleEAP __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleIPsec __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); +#if TARGET_OS_MAC && !TARGET_OS_IPHONE extern const CFStringRef kSecPolicyAppleiChat __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); +#endif extern const CFStringRef kSecPolicyApplePKINITClient __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyApplePKINITServer @@ -91,11 +91,10 @@ extern const CFStringRef kSecPolicyApplePassbookSigning extern const CFStringRef kSecPolicyApplePayIssuerEncryption __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); - /*! @enum Policy Value Constants @abstract Predefined property key constants used to get or set values in - a dictionary for a policy instance. + a dictionary for a policy instance. @discussion All policies will have the following read-only value: kSecPolicyOid (the policy object identifier) @@ -104,14 +103,16 @@ extern const CFStringRef kSecPolicyApplePayIssuerEncryption kSecPolicyName (name which must be matched) kSecPolicyClient (evaluate for client, rather than server) kSecPolicyRevocationFlags (only valid for a revocation policy) + kSecPolicyRevocationFlags (only valid for a revocation policy) + kSecPolicyTeamIdentifier (only valid for a Passbook signing policy) @constant kSecPolicyOid Specifies the policy OID (value is a CFStringRef) @constant kSecPolicyName Specifies a CFStringRef (or CFArrayRef of same) containing a name which must be matched in the certificate to satisfy this policy. For SSL/TLS, EAP, and IPSec policies, this specifies the server name which must match the common name of the certificate. - For S/MIME, this specifies the RFC822 email address. - For Passbook signing, this specifies the pass signer. + For S/MIME, this specifies the RFC822 email address. For Passbook + signing, this specifies the pass signer. @constant kSecPolicyClient Specifies a CFBooleanRef value that indicates this evaluation should be for a client certificate. If not set (or false), the policy evaluates the certificate as a server certificate. @@ -124,60 +125,61 @@ extern const CFStringRef kSecPolicyApplePayIssuerEncryption the Organizational Unit field of the certificate subject. */ extern const CFStringRef kSecPolicyOid - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyName - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyClient - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); extern const CFStringRef kSecPolicyRevocationFlags - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecPolicyTeamIdentifier - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); /*! - @function SecPolicyGetTypeID - @abstract Returns the type identifier of SecPolicy instances. - @result The CFTypeID of SecPolicy instances. -*/ + @function SecPolicyGetTypeID + @abstract Returns the type identifier of SecPolicy instances. + @result The CFTypeID of SecPolicy instances. + */ CFTypeID SecPolicyGetTypeID(void) - __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); + __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_2_0); /*! - @function SecPolicyCopyProperties - @abstract Returns a dictionary of this policy's properties. - @param policyRef A policy reference. - @result A properties dictionary. See "Policy Value Constants" for a list - of currently defined property keys. It is the caller's responsibility to - CFRelease this reference when it is no longer needed. - @result A result code. See "Security Error Codes" (SecBase.h). - @discussion This function returns the properties for a policy, as set by the - policy's construction function or by a prior call to SecPolicySetProperties. -*/ + @function SecPolicyCopyProperties + @abstract Returns a dictionary of this policy's properties. + @param policyRef A policy reference. + @result A properties dictionary. See "Policy Value Constants" for a list + of currently defined property keys. It is the caller's responsibility to + CFRelease this reference when it is no longer needed. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function returns the properties for a policy, as set by the + policy's construction function or by a prior call to SecPolicySetProperties. + */ +__nullable CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_7_0); /*! - @function SecPolicyCreateBasicX509 - @abstract Returns a policy object for the default X.509 policy. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ + @function SecPolicyCreateBasicX509 + @abstract Returns a policy object for the default X.509 policy. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ SecPolicyRef SecPolicyCreateBasicX509(void) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); /*! - @function SecPolicyCreateSSL - @abstract Returns a policy object for evaluating SSL certificate chains. - @param server Passing true for this parameter creates a policy for SSL - server certificates. - @param hostname (Optional) If present, the policy will require the specified - hostname to match the hostname in the leaf certificate. - @result A policy object. The caller is responsible for calling CFRelease - on this when it is no longer needed. -*/ + @function SecPolicyCreateSSL + @abstract Returns a policy object for evaluating SSL certificate chains. + @param server Passing true for this parameter creates a policy for SSL + server certificates. + @param hostname (Optional) If present, the policy will require the specified + hostname to match the hostname in the leaf certificate. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef __nullable hostname) - __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); + __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); /*! @enum Revocation Policy Constants @@ -200,14 +202,14 @@ SecPolicyRef SecPolicyCreateSSL(Boolean server, CFStringRef __nullable hostname) OCSP or CRL may be used, depending on the method(s) specified in the certificate and the value of kSecRevocationPreferCRL. */ -enum { - kSecRevocationOCSPMethod = (1 << 0), - kSecRevocationCRLMethod = (1 << 1), - kSecRevocationPreferCRL = (1 << 2), - kSecRevocationRequirePositiveResponse = (1 << 3), - kSecRevocationNetworkAccessDisabled = (1 << 4), - kSecRevocationUseAnyAvailableMethod = (kSecRevocationOCSPMethod | - kSecRevocationCRLMethod) +CF_ENUM(CFOptionFlags) { + kSecRevocationOCSPMethod = (1 << 0), + kSecRevocationCRLMethod = (1 << 1), + kSecRevocationPreferCRL = (1 << 2), + kSecRevocationRequirePositiveResponse = (1 << 3), + kSecRevocationNetworkAccessDisabled = (1 << 4), + kSecRevocationUseAnyAvailableMethod = (kSecRevocationOCSPMethod | + kSecRevocationCRLMethod) }; /*! @@ -222,9 +224,10 @@ enum { create a revocation policy yourself unless you wish to override default system behavior (e.g. to force a particular method, or to disable revocation checking entirely.) -*/ + */ +__nullable SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); /*! @function SecPolicyCreateWithProperties @@ -236,11 +239,11 @@ SecPolicyRef SecPolicyCreateRevocation(CFOptionFlags revocationFlags) Constants" for a list of currently defined property keys. @result The returned policy reference, or NULL if the policy could not be created. -*/ + */ __nullable SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, - CFDictionaryRef __nullable properties) - __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); + CFDictionaryRef __nullable properties) + __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END @@ -310,23 +313,23 @@ CF_IMPLICIT_BRIDGING_ENABLED have a key usage that permits it to be used for decryption only. */ extern const CFStringRef kSecPolicyKU_DigitalSignature - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_NonRepudiation - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_KeyEncipherment - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_DataEncipherment - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_KeyAgreement - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_KeyCertSign - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_CRLSign - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_EncipherOnly - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecPolicyKU_DecipherOnly - __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); + __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); /*! @function SecPolicyCreateWithOID @@ -339,10 +342,10 @@ extern const CFStringRef kSecPolicyKU_DecipherOnly @discussion This function is deprecated in Mac OS X 10.9 and later; use SecPolicyCreateWithProperties (or a more specific policy creation function) instead. -*/ + */ __nullable SecPolicyRef SecPolicyCreateWithOID(CFTypeRef policyOID) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); /*! @function SecPolicyGetOID @@ -352,9 +355,9 @@ SecPolicyRef SecPolicyCreateWithOID(CFTypeRef policyOID) @result A result code. See "Security Error Codes" (SecBase.h). @discussion This function is deprecated in Mac OS X 10.7 and later; use SecPolicyCopyProperties instead. -*/ + */ OSStatus SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID *oid) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); /*! @function SecPolicyGetValue @@ -364,9 +367,9 @@ OSStatus SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID *oid) @result A result code. See "Security Error Codes" (SecBase.h). @discussion This function is deprecated in Mac OS X 10.7 and later; use SecPolicyCopyProperties instead. -*/ + */ OSStatus SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA *value) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); /*! @function SecPolicySetValue @@ -379,9 +382,9 @@ OSStatus SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA *value) instances should be considered read-only; in cases where your code would consider changing properties of a policy, it should instead create a new policy instance with the desired properties. -*/ + */ OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); /*! @function SecPolicySetProperties @@ -396,10 +399,10 @@ OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) instances should be considered read-only; in cases where your code would consider changing properties of a policy, it should instead create a new policy instance with the desired properties. -*/ + */ OSStatus SecPolicySetProperties(SecPolicyRef policyRef, - CFDictionaryRef properties) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); + CFDictionaryRef properties) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA); /*! @function SecPolicyGetTPHandle @@ -408,17 +411,15 @@ OSStatus SecPolicySetProperties(SecPolicyRef policyRef, @param tpHandle On return, a pointer to a value of type CSSM_TP_HANDLE. @result A result code. See "Security Error Codes" (SecBase.h). @discussion This function is deprecated in Mac OS X 10.7 and later. -*/ + */ OSStatus SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE *tpHandle) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); CF_IMPLICIT_BRIDGING_DISABLED CF_ASSUME_NONNULL_END - + #endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ -#if defined(__cplusplus) -} -#endif +__END_DECLS #endif /* !_SECURITY_SECPOLICY_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecPolicyPriv.h b/OSX/libsecurity_keychain/lib/SecPolicyPriv.h index bb4a6023..7eb06b4c 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicyPriv.h +++ b/OSX/libsecurity_keychain/lib/SecPolicyPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,20 +22,24 @@ */ /*! - @header SecPolicyPriv - Private part of SecPolicy.h -*/ + @header SecPolicyPriv + The functions provided in SecPolicyPriv provide an interface to various + X.509 certificate trust policies. + */ #ifndef _SECURITY_SECPOLICYPRIV_H_ #define _SECURITY_SECPOLICYPRIV_H_ #include +#include #include +#include +#include +__BEGIN_DECLS -#if defined(__cplusplus) -extern "C" { -#endif +CF_ASSUME_NONNULL_BEGIN +CF_IMPLICIT_BRIDGING_ENABLED /*! @enum Policy Constants (Private) @@ -55,12 +59,43 @@ extern "C" { @constant kSecPolicyApplePPQSigning @constant kSecPolicyAppleTestPPQSigning @constant kSecPolicyAppleSWUpdateSigning - @constant kSecPolicyAppleATVAppSigning - @constant kSecPolicyAppleTestATVAppSigning + @constant kSecPolicyApplePackageSigning @constant kSecPolicyAppleOSXProvisioningProfileSigning @constant kSecPolicyAppleATVVPNProfileSigning - -*/ + @constant kSecPolicyAppleAST2DiagnosticsServerAuth + @constant kSecPolicyAppleEscrowProxyServerAuth + @constant kSecPolicyAppleFMiPServerAuth + @constant kSecPolicyAppleMMCService + @constant kSecPolicyAppleGSService + @constant kSecPolicyApplePPQService + @constant kSecPolicyAppleHomeKitServerAuth + @constant kSecPolicyAppleiPhoneActivation + @constant kSecPolicyAppleiPhoneDeviceCertificate + @constant kSecPolicyAppleFactoryDeviceCertificate + @constant kSecPolicyAppleiAP + @constant kSecPolicyAppleiTunesStoreURLBag + @constant kSecPolicyAppleiPhoneApplicationSigning + @constant kSecPolicyAppleiPhoneProfileApplicationSigning + @constant kSecPolicyAppleiPhoneProvisioningProfileSigning + @constant kSecPolicyAppleLockdownPairing + @constant kSecPolicyAppleURLBag + @constant kSecPolicyAppleOTATasking + @constant kSecPolicyAppleMobileAsset + @constant kSecPolicyAppleIDAuthority + @constant kSecPolicyAppleGenericApplePinned + @constant kSecPolicyAppleGenericAppleSSLPinned + @constant kSecPolicyAppleSoftwareSigning + @constant kSecPolicyAppleExternalDeveloper + @constant kSecPolicyAppleOCSPSigner + @constant kSecPolicyAppleIDSService + @constant kSecPolicyAppleIDSServiceContext + @constant kSecPolicyApplePushService + @constant kSecPolicyAppleLegacyPushService + @constant kSecPolicyAppleTVOSApplicationSigning + @constant kSecPolicyAppleUniqueDeviceIdentifierCertificate + @constant kSecPolicyAppleEscrowProxyCompatibilityServerAuth + @constant kSecPolicyAppleMMCSCompatibilityServerAuth + */ extern const CFStringRef kSecPolicyAppleMobileStore __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleTestMobileStore @@ -73,29 +108,27 @@ 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); -#if TARGET_OS_IPHONE extern const CFStringRef kSecPolicyAppleOTAPKISigner - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleTestOTAPKISigner - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_7_0); extern const CFStringRef kSecPolicyAppleIDValidationRecordSigningPolicy - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_7_0); + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA, __MAC_NA, __IPHONE_7_0, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleIDValidationRecordSigning + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); extern const CFStringRef kSecPolicyAppleSMPEncryption - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_8_0); extern const CFStringRef kSecPolicyAppleTestSMPEncryption - __OSX_AVAILABLE_STARTING(__MAC_NA, __IPHONE_8_0); -#endif + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_8_0); extern const CFStringRef kSecPolicyApplePCSEscrowService - __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); + __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_7_0); extern const CFStringRef kSecPolicyApplePPQSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); extern const CFStringRef kSecPolicyAppleTestPPQSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); extern const CFStringRef kSecPolicyAppleSWUpdateSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); -extern const CFStringRef kSecPolicyAppleATVAppSigning - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); -extern const CFStringRef kSecPolicyAppleTestATVAppSigning +extern const CFStringRef kSecPolicyApplePackageSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); extern const CFStringRef kSecPolicyAppleOSXProvisioningProfileSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); @@ -103,157 +136,1077 @@ extern const CFStringRef kSecPolicyAppleATVVPNProfileSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); extern const CFStringRef kSecPolicyAppleAST2DiagnosticsServerAuth __OSX_AVAILABLE_STARTING(__MAC_10_11_4, __IPHONE_9_3); +extern const CFStringRef kSecPolicyAppleEscrowProxyServerAuth + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleFMiPServerAuth + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleMMCService + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleGSService + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyApplePPQService + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleHomeKitServerAuth + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiPhoneActivation + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiPhoneDeviceCertificate + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleFactoryDeviceCertificate + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiAP + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiTunesStoreURLBag + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiPhoneApplicationSigning + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiPhoneProfileApplicationSigning + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleiPhoneProvisioningProfileSigning + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleLockdownPairing + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleURLBag + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleOTATasking + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleMobileAsset + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleIDAuthority + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleGenericApplePinned + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleGenericAppleSSLPinned + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleSoftwareSigning + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleExternalDeveloper + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleOCSPSigner + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleIDSService + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleIDSServiceContext + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyApplePushService + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleLegacyPushService + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleTVOSApplicationSigning + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleUniqueDeviceIdentifierCertificate + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleEscrowProxyCompatibilityServerAuth + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyAppleMMCSCompatibilityServerAuth + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); + +/*! + @enum Policy Value Constants + @abstract Predefined property key constants used to get or set values in + a dictionary for a policy instance. + @discussion + All policies will have the following read-only value: + kSecPolicyOid (the policy object identifier) + + Additional policy values which your code can optionally set: + kSecPolicyName (name which must be matched) + kSecPolicyClient (evaluate for client, rather than server) + kSecPolicyRevocationFlags (only valid for a revocation policy) + kSecPolicyRevocationFlags (only valid for a revocation policy) + kSecPolicyTeamIdentifier (only valid for a Passbook signing policy) + kSecPolicyContext (valid for policies below that take a context parameter) + kSecPolicyPolicyName (only valid for GenericApplePinned or + GenericAppleSSLPinned policies) + kSecPolicyIntermediateMarkerOid (only valid for GenericApplePinned or + GenericAppleSSLPinned policies) + kSecPolicyLeafMarkerOid (only valid for GenericApplePinned or + GenericAppleSSLPinned policies) + kSecPolicyRootDigest (only valid for the UniqueDeviceCertificate policy) + + @constant kSecPolicyContext Specifies a CFDictionaryRef with keys and values + specified by the particular SecPolicyCreate function. + @constant kSecPolicyPolicyName Specifies a CFStringRef of the name of the + desired policy result. + @constant kSecPolicyIntermediateMarkerOid Specifies a CFStringRef of the + marker OID (in decimal format) required in the intermediate certificate. + @constant kSecPolicyLeafMarkerOid Specifies a CFStringRef of the + marker OID (in decimal format) required in the leaf certificate. + @constant kSecPolicyRootDigest Specifies a CFDataRef of digest required to + match the SHA-256 of the root certificate. + */ +extern const CFStringRef kSecPolicyContext + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyPolicyName + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyIntermediateMarkerOid + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyLeafMarkerOid + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); +extern const CFStringRef kSecPolicyRootDigest + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); /*! - @function SecPolicyCopy - @abstract Returns a copy of a policy reference based on certificate type and OID. - @param certificateType A certificate type. - @param policyOID The OID of the policy you want to find. This is a required parameter. See oidsalg.h to see a list of policy OIDs. - @param policy The returned policy reference. 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. -*/ -OSStatus SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + @function SecPolicyCreateApplePinned + @abstract Returns a policy object for verifying Apple certificates. + @param policyName A string that identifies the policy name. + @param intermediateMarkerOID A string containing the decimal representation of the + extension OID in the intermediate certificate. + @param leafMarkerOID A string containing the decimal representation of the extension OID + 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. + * There are exactly 3 certs in the chain. + * The intermediate has a marker extension with OID matching the intermediateMarkerOID + parameter. + * The leaf has a marker extension with OID matching the leafMarkerOID parameter. + * Revocation is checked via OCSP or CRL. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePinned(CFStringRef policyName, + CFStringRef intermediateMarkerOID, CFStringRef leafMarkerOID) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); /*! - @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* policies) - __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_3, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); + @function SecPolicyCreateAppleSSLPinned + @abstract Returns a policy object for verifying Apple SSL certificates. + @param policyName A string that identifies the service/policy name. + @param hostname hostname to verify the certificate name against. + @param intermediateMarkerOID A string containing the decimal representation of the + extension OID in the intermediate certificate. If NULL is passed, the default OID of + 1.2.840.113635.100.6.2.12 is checked. + @param leafMarkerOID A string containing the decimal representation of the extension OID + 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. + * 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP or CRL. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + For developers who need to disable pinning this function is equivalent to SecPolicyCreateSSL + on internal releases if the value true is set for the key "AppleServerAuthenticationNoPinning%@" + (where %@ is the policyName parameter) in the com.apple.Security preferences for the user + of the calling application. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleSSLPinned(CFStringRef policyName, CFStringRef hostname, + CFStringRef __nullable intermediateMarkerOID, CFStringRef leafMarkerOID) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); -/* 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. */ -SecPolicyRef SecPolicyCreateItemImplInstance(SecPolicyRef policy); +/*! + @function SecPolicyCreateiPhoneActivation + @abstract Returns a policy object for verifying iPhone Activation + certificate chains. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * The chain is anchored to "Apple Root CA" certificate. + * There are exactly 3 certs in chain. + * The intermediate has Common Name "Apple iPhone Certification Authority". + * The leaf has Common Name "iPhone Activation". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiPhoneActivation(void); -/* Given a CSSM_OID pointer, return a string which can be passed - to SecPolicyCreateWithProperties. The return value can be NULL - if no supported policy was found for the OID argument. */ -CFStringRef SecPolicyGetStringForOID(CSSM_OID* oid); +/*! + @function SecPolicyCreateiPhoneDeviceCertificate + @abstract Returns a policy object for verifying iPhone Device certificate + chains. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * There are exactly 4 certs in chain. + * The chain is anchored to "Apple Root CA" certificate. + * The first intermediate has Common Name "Apple iPhone Device CA". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiPhoneDeviceCertificate(void); + +/*! + @function SecPolicyCreateFactoryDeviceCertificate + @abstract Returns a policy object for verifying Factory Device certificate + chains. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * The chain is anchored to the Factory Device CA. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateFactoryDeviceCertificate(void); + +/*! + @function SecPolicyCreateiAP + @abstract Returns a policy object for verifying iAP certificate chains. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * The leaf has notBefore date after 5/31/2006 midnight GMT. + * The leaf has Common Name beginning with "IPA_". + The intended use of this policy is that the caller pass in the + intermediates for iAP1 and iAP2 to SecTrustSetAnchorCertificates(). + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiAP(void); + +/*! + @function SecPolicyCreateiTunesStoreURLBag + @abstract Returns a policy object for verifying iTunes Store URL bag + certificates. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * The chain is anchored to the iTMS CA. + * There are exactly 2 certs in the chain. + * The leaf has Organization "Apple Inc.". + * The leaf has Common Name "iTunes Store URL Bag". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiTunesStoreURLBag(void); + +/*! + @function SecPolicyCreateEAP + @abstract Returns a policy object for verifying for 802.1x/EAP certificates. + @param server Passing true for this parameter create a policy for EAP + server certificates. + @param trustedServerNames Optional; if present, the hostname in the leaf + certificate must be in the trustedServerNames list. Note that contrary + to all other policies the trustedServerNames list entries can have wildcards + whilst the certificate cannot. This matches the existing deployments. + @discussion This policy uses the Basic X.509 policy with validity check but + disallowing network fetching. If trustedServerNames param is non-null, the + ExtendedKeyUsage extension, if present, of the leaf certificate is verified + to contain either the ServerAuth OID, if the server param is true or + ClientAuth OID, otherwise. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateEAP(Boolean server, CFArrayRef __nullable trustedServerNames); + +/*! + @function SecPolicyCreateIPSec + @abstract Returns a policy object for evaluating IPSec certificate chains. + @param server Passing true for this parameter create a policy for IPSec + server certificates. + @param hostname Optional; if present, the policy will require the specified + hostname or ip address to match the hostname in the leaf certificate. + @discussion This policy uses the Basic X.509 policy with validity check. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateIPSec(Boolean server, CFStringRef __nullable hostname); + +/*! + @function SecPolicyCreateAppleSWUpdateSigning + @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 "Apple Root CA" certificate. + * There are exactly 3 certs in the chain. + * The leaf ExtendedKeyUsage extension contains 1.2.840.113635.100.4.1. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleSWUpdateSigning(void); + +/*! + @function SecPolicyCreateApplePackageSigning + @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 "Apple Root CA" certificate. + * There are exactly 3 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 SecPolicyCreateApplePackageSigning(void); + +/*! + @function SecPolicyCreateiPhoneApplicationSigning + @abstract Returns a policy object for evaluating signed application + 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 "Apple Root CA" certificate. + * 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". + * If the device is not a production device and is running an internal + release, the leaf may have the Common Name "TEST Apple iPhone OS + Application Signing TEST". + * The leaf has ExtendedKeyUsage, if any, with the AnyExtendedKeyUsage OID + or the CodeSigning OID. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiPhoneApplicationSigning(void); + +/*! + @function SecPolicyCreateiPhoneProfileApplicationSigning + @abstract Returns a policy object for evaluating signed application + signatures. This policy is for certificates inside a UPP or regular + profile. + @discussion This policy only verifies that the leaf is temporally valid + and not revoked. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiPhoneProfileApplicationSigning(void); + +/*! + @function SecPolicyCreateiPhoneProvisioningProfileSigning + @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 "Apple Root CA" certificate. + * 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". + * If the device is not a production device and is running an internal + release, the leaf may have the Common Name "TEST Apple iPhone OS + Provisioning Profile Signing TEST". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateiPhoneProvisioningProfileSigning(void); + +/*! + @function SecPolicyCreateAppleTVOSApplicationSigning + @abstract Returns a policy object for evaluating signed application + signatures. This is for apps signed directly by the Apple TV app store, + 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. + 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. + * The leaf has ExtendedKeyUsage, if any, with the AnyExtendedKeyUsage OID or + the CodeSigning OID. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.1.24 or OID + 1.2.840.113635.100.6.1.24.1. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleTVOSApplicationSigning(void); + +/*! + @function SecPolicyCreateOCSPSigner + @abstract Returns a policy object for evaluating ocsp response signers. + @discussion This policy uses the Basic X.509 policy with validity check and + requires the leaf to have an ExtendedKeyUsage of OCSPSigning. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateOCSPSigner(void); + + +enum { + kSecSignSMIMEUsage = (1 << 0), + kSecKeyEncryptSMIMEUsage = (1 << 1), + kSecDataEncryptSMIMEUsage = (1 << 2), + kSecKeyExchangeDecryptSMIMEUsage = (1 << 3), + kSecKeyExchangeEncryptSMIMEUsage = (1 << 4), + kSecKeyExchangeBothSMIMEUsage = (1 << 5), + kSecAnyEncryptSMIME = kSecKeyEncryptSMIMEUsage | kSecDataEncryptSMIMEUsage | + kSecKeyExchangeDecryptSMIMEUsage | kSecKeyExchangeEncryptSMIMEUsage +}; + +/*! + @function SecPolicyCreateSMIME + @abstract Returns a policy object for evaluating S/MIME certificate chains. + @param smimeUsage Pass the bitwise or of one or more kSecXXXSMIMEUsage + flags, to indicate the intended usage of this certificate. + @param email Optional; if present, the policy will require the specified + email to match the email in the leaf certificate. + @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 + * 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. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateSMIME(CFIndex smimeUsage, CFStringRef __nullable email); + +/*! + @function SecPolicyCreateCodeSigning + @abstract Returns a policy object for evaluating code signing certificate chains. + @discussion This policy uses the Basic X.509 policy with validity check and + requires the leaf to have + * a KeyUsage with both the DigitalSignature and NonRepudiation bits set, and + * an ExtendedKeyUsage with the AnyExtendedKeyUsage OID or the CodeSigning OID. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateCodeSigning(void); + +/*! + @function SecPolicyCreateLockdownPairing + @abstract basic x509 policy for checking lockdown pairing certificate chains. + @disucssion This policy checks some of the Basic X.509 policy options with no + validity check. It explicitly allows for empty subjects. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateLockdownPairing(void); + +/*! + @function SecPolicyCreateURLBag + @abstract Returns a policy object for evaluating certificate chains for signing URL bags. + @discussion This policy uses the Basic X.509 policy with no validity check and requires + that the leaf has ExtendedKeyUsage extension with the CodeSigning OID. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateURLBag(void); + +/*! + @function SecPolicyCreateOTATasking + @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 "Apple Root CA" certificate. + * There are exactly 3 certs in the chain. + * The leaf has Common Name "OTA Task Signing". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateOTATasking(void); + +/*! + @function SecPolicyCreateMobileAsset + @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 "Apple Root CA" certificate. + * There are exactly 3 certs in the chain. + * The leaf has Common Name "Asset Manifest Signing". + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateMobileAsset(void); + +/*! + @function SecPolicyCreateAppleIDAuthorityPolicy + @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 "Apple Root CA" certificate. + * 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. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleIDAuthorityPolicy(void); + +/*! + @function SecPolicyCreateMacAppStoreReceipt + @abstract Returns a policy object for evaluating certificate chains for signing + Mac App Store Receipts. + @discussion This policy uses the Basic X.509 policy with validity check + and pinning options: + * The chain is anchored to "Apple Root CA" certificate. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateMacAppStoreReceipt(void); + +/*! + @function SecPolicyCreatePassbookCardSigner + @abstract Returns a policy object for evaluating certificate chains for signing Passbook cards. + @param cardIssuer Required; must match name in marker extension. + @param teamIdentifier Optional; if present, the policy will require the specified + 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 "Apple Root CA" certificate. + * 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. + * The leaf has a Organizational Unit matching the TeamID. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreatePassbookCardSigner(CFStringRef cardIssuer, + CFStringRef __nullable teamIdentifier); + +/*! + @function SecPolicyCreateMobileStoreSigner + @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 "Apple Root CA" certificate. + * 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. + * The leaf has CertificatePolicy extension with OID 1.2.840.113635.100.5.12. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateMobileStoreSigner(void); + +/*! + @function SecPolicyCreateTestMobileStoreSigner + @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 "Apple Root CA" certificate. + * 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. + * The leaf has CertificatePolicy extension with OID 1.2.840.113635.100.5.12.1. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateTestMobileStoreSigner(void); + +/*! + @function SecPolicyCreateEscrowServiceSigner + @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 + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateEscrowServiceSigner(void); + +/*! + @function SecPolicyCreatePCSEscrowServiceSigner + @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 + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreatePCSEscrowServiceSigner(void); + +/*! + @function SecPolicyCreateOSXProvisioningProfileSigning + @abstract Returns a policy object for evaluating certificate chains for signing OS X + Provisioning Profiles. + @discussion This policy uses the Basic X.509 policy with validity check + and pinning options: + * The chain is anchored to "Apple Root CA" certificate. + * 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. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void); + +/*! + @function SecPolicyCreateConfigurationProfileSigner + @abstract Returns a policy object for evaluating certificate chains for signing + Configuration Profiles. + @discussion This policy uses the Basic X.509 policy with validity check + and pinning options: + * The chain is anchored to "Apple Root CA" certificate. + * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.16. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateConfigurationProfileSigner(void); + +/*! + @function SecPolicyCreateQAConfigurationProfileSigner + @abstract Returns a policy object for evaluating certificate chains for signing + QA Configuration Profiles. + @discussion This policy uses the Basic X.509 policy with validity check + and pinning options: + * The chain is anchored to "Apple Root CA" certificate. + * The leaf has ExtendedKeyUsage with OID 1.2.840.113635.100.4.17. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__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); + +/*! + @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); + +/*! + @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 "Apple Root CA" certificate. + * 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. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleIDValidationRecordSigningPolicy(void); + +/*! + @function SecPolicyCreateAppleSMPEncryption + @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 "Apple Root CA - ECC" certificate. + * 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. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.30. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleSMPEncryption(void); + +/*! + @function SecPolicyCreateTestAppleSMPEncryption + @abstract Returns a policy object for evaluating Test SMP certificate chains. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * The chain is anchored to a Test Apple Root with ECC public key certificate. + * There are exactly 3 certs in the chain. + * The intermediate has Common Name "Test Apple System Integration CA - ECC". + * The leaf has KeyUsage with the KeyEncipherment bit set. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateTestAppleSMPEncryption(void); + +/*! + @function SecPolicyCreateApplePPQSigning + @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 "Apple Root CA" certificate. + * There are exactly 3 certs in the chain. + * The intermediate has Common Name "Apple System Integration 2 Certification + Authority". + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.10. + * The leaf has KeyUsage with the DigitalSignature bit set. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.38.2. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePPQSigning(void); + +/*! + @function SecPolicyCreateTestApplePPQSigning + @abstract Returns a policy object for verifying test PPQ Signing certificates. + @discussion This policy uses the Basic X.509 policy with no validity check + and pinning options: + * The chain is anchored to "Apple Root CA" certificate. + * There are exactly 3 certs in the chain. + * The intermediate has Common Name "Apple System Integration 2 Certification + Authority". + * The intermediate has a marker extension with OID 1.2.840.113635.100.6.2.10. + * The leaf has KeyUsage with the DigitalSignature bit set. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.38.1. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +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. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef __nullable hostname); /*! - @function SecPolicyCreateAppleIDSService + @function SecPolicyCreateAppleIDSServiceContext @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATIDS" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDictionaryRef context); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDictionaryRef __nullable context); /*! @function SecPolicyCreateApplePushService - @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions) + @abstract Ensure we're appropriately pinned to the Apple Push service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATAPN" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryRef context); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryRef __nullable context); /*! @function SecPolicyCreateApplePushServiceLegacy - @abstract Ensure we're appropriately pinned to the Push service (SSL + Apple restrictions) + @abstract Ensure we're appropriately pinned to the Push service (via Entrust) + @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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ +__nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateApplePushServiceLegacy(CFStringRef hostname); /*! @function SecPolicyCreateAppleMMCSService - @abstract Ensure we're appropriately pinned to the IDS service (SSL + Apple restrictions) + @abstract Ensure we're appropriately pinned to the MMCS service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATMMCS" with value + Boolean true will allow Test Apple rotos 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 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 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. */ -SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryRef context); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryRef __nullable context); + +/*! + @function SecPolicyCreateAppleCompatibilityMMCSService + @abstract Ensure we're appropriately pinned to the MMCS service using compatibility certs + @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 the GeoTrust Global CA + * The intermediate has a subject public key info hash matching the public key of + the Apple IST CA G1 intermediate. + * 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 ExtendedKeyUsage with the ServerAuth OID. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleCompatibilityMMCSService(CFStringRef hostname) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); /*! @function SecPolicyCreateAppleGSService @abstract Ensure we're appropriately pinned to the GS service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATGS" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef context) +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef __nullable context) __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); /*! @function SecPolicyCreateApplePPQService @abstract Ensure we're appropriately pinned to the PPQ service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATPPQ" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef context); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef __nullable context) + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); /*! @function SecPolicyCreateAppleAST2Service @abstract Ensure we're appropriately pinned to the AST2 Diagnostic service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATAST2" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef context) +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef __nullable context) __OSX_AVAILABLE_STARTING(__MAC_10_11_4, __IPHONE_9_3); /*! - @function SecPolicyCreateAppleSSLService - @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions) + @function SecPolicyCreateAppleEscrowProxyService + @abstract Ensure we're appropriately pinned to the iCloud Escrow Proxy service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATEscrow" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via CRL. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleEscrowProxyService(CFStringRef hostname, CFDictionaryRef __nullable context) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); /*! - @function SecPolicyCreateAppleTimeStampingAndRevocationPolicies - @abstract Create timeStamping policy array from a given set of policies by applying identical revocation behavior - @param policyOrArray can be a SecPolicyRef or a CFArray of SecPolicyRef + @function SecPolicyCreateAppleFMiPService + @abstract Ensure we're appropriately pinned to the Find My iPhone service (SSL + Apple restrictions) + @param hostname Required; hostname to verify the certificate name against. + @param context Optional; if present, "AppleServerAuthenticationAllowUATFMiP" with value + 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 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 ExtendedKeyUsage with the ServerAuth OID. + * Revocation is checked via CRL. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -CFArrayRef SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleFMiPService(CFStringRef hostname, CFDictionaryRef __nullable context) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); /*! - @function SecPolicyCreateAppleATVAppSigning - @abstract Check for intermediate certificate 'Apple Worldwide Developer Relations Certification Authority' by name, - and apple anchor. - Leaf cert must have Digital Signature usage. - Leaf cert must have Apple ATV App Signing marker OID (1.2.840.113635.100.6.1.24). - Leaf cert must have 'Apple TVOS Application Signing' common name. + @function SecPolicyCreateAppleSSLService + @abstract Ensure we're appropriately pinned to an Apple server (SSL + Apple restrictions) + @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 "Apple Root CA" certificate. + * 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 ExtendedKeyUsage, if any, with the ServerAuth OID. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateAppleATVAppSigning(void) - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef __nullable hostname); /*! - @function SecPolicyCreateTestAppleATVAppSigning - @abstract Check for intermediate certificate 'Apple Worldwide Developer Relations Certification Authority' by name, - and apple anchor. - Leaf cert must have Digital Signature usage. - Leaf cert must have Apple ATV App Signing Test marker OID (1.2.840.113635.100.6.1.24.1). - Leaf cert must have 'TEST Apple TVOS Application Signing TEST' common name. + @function SecPolicyCreateAppleTimeStamping + @abstract Returns a policy object for evaluating time stamping certificate chains. + @discussion This policy uses the Basic X.509 policy with validity check + and requires the leaf has ExtendedKeyUsage with the TimeStamping OID. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ -SecPolicyRef SecPolicyCreateTestAppleATVAppSigning(void) - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleTimeStamping(void); /*! @function SecPolicyCreateApplePayIssuerEncryption - @abstract Check for intermediate certificate 'Apple Worldwide Developer Relations CA - G2' by name, - and apple anchor. - Leaf cert must have Key Encipherment and Key Agreement usage. - Leaf cert must have Apple Pay Issuer Encryption marker OID (1.2.840.113635.100.6.39). + @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 "Apple Root CA - ECC" certificate. + * 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. + * The leaf has a marker extension with OID 1.2.840.113635.100.6.39. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ +__nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateApplePayIssuerEncryption(void) __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); -/*! - @function SecPolicyCreateOSXProvisioningProfileSigning - @abstract Check for leaf marker OID 1.2.840.113635.100.4.11, - intermediate marker OID 1.2.840.113635.100.6.2.1, - chains to Apple Root CA -*/ -SecPolicyRef SecPolicyCreateOSXProvisioningProfileSigning(void) - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); - - /*! @function SecPolicyCreateAppleATVVPNProfileSigning - @abstract Check for leaf marker OID 1.2.840.113635.100.6.43, - intermediate marker OID 1.2.840.113635.100.6.2.10, - chains to Apple Root CA, path length 3 + @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. + * 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. + * Revocation is checked via OCSP. + @result A policy object. The caller is responsible for calling CFRelease + on this when it is no longer needed. */ +__nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateAppleATVVPNProfileSigning(void) __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); @@ -275,11 +1228,170 @@ SecPolicyRef SecPolicyCreateAppleATVVPNProfileSigning(void) @result A policy object. The caller is responsible for calling CFRelease on this when it is no longer needed. */ +__nullable CF_RETURNS_RETAINED SecPolicyRef SecPolicyCreateAppleHomeKitServerAuth(CFStringRef hostname) __OSX_AVAILABLE_STARTING(__MAC_10_11_4, __IPHONE_9_3); -#if defined(__cplusplus) -} -#endif +/*! + @function SecPolicyCreateAppleExternalDeveloper + @abstract Returns a policy object for verifying Apple-issued external developer + 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. + * 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). + * The leaf has a marker extension with OID matching one of the following: + * 1.2.840.113635.100.6.1.2 ("iPhone Developer" leaf) + * 1.2.840.113635.100.6.1.4 ("iPhone Distribution" leaf) + * 1.2.840.113635.100.6.1.5 ("Safari Developer" leaf) + * 1.2.840.113635.100.6.1.7 ("3rd Party Mac Developer Application" leaf) + * 1.2.840.113635.100.6.1.8 ("3rd Party Mac Developer Installer" leaf) + * 1.2.840.113635.100.6.1.12 ("Mac Developer" leaf) + * 1.2.840.113635.100.6.1.13 ("Developer ID Application" leaf) + * 1.2.840.113635.100.6.1.14 ("Developer ID Installer" leaf) + * The leaf has an ExtendedKeyUsage OID matching one of the following: + * 1.3.6.1.5.5.7.3.3 (CodeSigning EKU) + * 1.2.840.113635.100.4.8 ("Safari Developer" EKU) + * 1.2.840.113635.100.4.9 ("3rd Party Mac Developer Installer" EKU) + * 1.2.840.113635.100.4.13 ("Developer ID Installer" EKU) + * Revocation is checked via OCSP or CRL. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleExternalDeveloper(void) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecPolicyCreateAppleSoftwareSigning + @abstract Returns a policy object for verifying the Apple Software Signing 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 a defaults write for the policy is set. + * 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. + * The leaf has an ExtendedKeyUsage OID matching 1.3.6.1.5.5.7.3.3 (Code Signing). + * Revocation is checked via OCSP or CRL. + * RSA key sizes are 2048-bit or larger. EC key sizes are P-256 or larger. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleSoftwareSigning(void) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecPolicyGetName + @abstract Returns a policy's name. + @param policy A policy reference. + @result A policy name. + */ +__nullable CFStringRef SecPolicyGetName(SecPolicyRef policy) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecPolicyGetOidString + @abstract Returns a policy's oid in string decimal format. + @param policy A policy reference. + @result A policy oid. + */ +CFStringRef SecPolicyGetOidString(SecPolicyRef policy) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +/*! + @function SecPolicyCreateAppleUniqueDeviceCertificate + @abstract Returns a policy object for verifying Unique Device Identifier Certificates. + @param testRootHash Optional; The SHA-256 fingerprint of a test root for pinning. + @discussion The resulting policy uses the Basic X.509 policy with no validity check and + pinning options: + * The chain is anchored to the SEP Root CA. Internal releases allow the chain to be + anchored to the testRootHash input if the value true is set for the key + "ApplePinningAllowTestCertsUCRT" in the com.apple.security preferences for the user + of the calling application. + * There are exactly 3 certs in the chain. + * The intermediate has an extension with OID matching 1.2.840.113635.100.6.44 and value + of "ucrt". + * The leaf has a marker extension with OID matching 1.2.840.113635.100.10.1. + * RSA key sizes are are disallowed. EC key sizes are P-256 or larger. + @result A policy object. The caller is responsible for calling CFRelease on this when + it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateAppleUniqueDeviceCertificate(CFDataRef __nullable testRootHash) + __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0); + +CF_IMPLICIT_BRIDGING_DISABLED +CF_ASSUME_NONNULL_END + +/* + * Legacy functions (OS X only) + */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE + +CF_ASSUME_NONNULL_BEGIN +CF_IMPLICIT_BRIDGING_ENABLED + +/*! + @function SecPolicyCopy + @abstract Returns a copy of a policy reference based on certificate type and OID. + @param certificateType A certificate type. + @param policyOID The OID of the policy you want to find. This is a required parameter. See oidsalg.h to see a list of policy OIDs. + @param policy The returned policy reference. 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. + */ +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. */ +__nullable CF_RETURNS_RETAINED +SecPolicyRef SecPolicyCreateItemImplInstance(SecPolicyRef policy); + +/* Given a CSSM_OID pointer, return a string which can be passed + to SecPolicyCreateWithProperties. The return value can be NULL + if no supported policy was found for the OID argument. */ +__nullable +CFStringRef SecPolicyGetStringForOID(CSSM_OID* oid); + +/*! + @function SecPolicyCreateAppleTimeStampingAndRevocationPolicies + @abstract Create timeStamping policy array from a given set of policies by applying identical revocation behavior + @param policyOrArray can be a SecPolicyRef or a CFArray of SecPolicyRef + @discussion This function is soon to be deprecated. Callers should create an array of the non-deprecated timestamping + and revocation policies. + */ +__nullable CF_RETURNS_RETAINED +CFArrayRef SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray); + +CF_IMPLICIT_BRIDGING_DISABLED +CF_ASSUME_NONNULL_END + +#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ + +__END_DECLS #endif /* !_SECURITY_SECPOLICYPRIV_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecRandom.h b/OSX/libsecurity_keychain/lib/SecRandom.h index 8890a259..d15cbbec 100644 --- a/OSX/libsecurity_keychain/lib/SecRandom.h +++ b/OSX/libsecurity_keychain/lib/SecRandom.h @@ -55,10 +55,12 @@ extern const SecRandomRef kSecRandomDefault /*! @function SecRandomCopyBytes @abstract Return count random bytes in *bytes, allocated by the caller. + It is critical to check the return value for error @result Return 0 on success or -1 if something went wrong, check errno to find out the real error. */ int SecRandomCopyBytes(SecRandomRef __nullable rnd, size_t count, uint8_t *bytes) + __attribute__ ((warn_unused_result)) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_2_0); CF_IMPLICIT_BRIDGING_DISABLED diff --git a/OSX/libsecurity_keychain/lib/SecTrust.cpp b/OSX/libsecurity_keychain/lib/SecTrust.cpp index ae0d4c93..8feae2cc 100644 --- a/OSX/libsecurity_keychain/lib/SecTrust.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrust.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,12 +24,12 @@ #include "SecTrust.h" #include "SecTrustPriv.h" #include "Trust.h" -#include #include "SecBase.h" #include "SecBridge.h" #include "SecInternal.h" #include "SecInternalP.h" #include "SecTrustSettings.h" +#include "SecTrustSettingsPriv.h" #include "SecCertificatePriv.h" #include "SecCertificateP.h" #include "SecCertificatePrivP.h" @@ -44,6 +44,11 @@ CFArrayRef SecTrustCopyDetails(SecTrustRef trust); static CFDictionaryRef SecTrustGetExceptionForCertificateAtIndex(SecTrustRef trust, CFIndex ix); static void SecTrustCheckException(const void *key, const void *value, void *context); +#else +CFArrayRef SecTrustCopyInputCertificates(SecTrustRef trust); +CFArrayRef SecTrustCopyInputAnchors(SecTrustRef trust); +CFArrayRef SecTrustCopyConstructedChain(SecTrustRef trust); +static CSSM_TP_APPLE_EVIDENCE_INFO * SecTrustGetEvidenceInfo(SecTrustRef trust); #endif typedef struct SecTrustCheckExceptionContext { @@ -61,6 +66,68 @@ const CFStringRef kSecTrustRevocationReason = CFSTR("TrustRevocationReas const CFStringRef kSecTrustRevocationValidUntilDate = CFSTR("TrustExpirationDate"); const CFStringRef kSecTrustResultDetails = CFSTR("TrustResultDetails"); +// Policy check string to CSSM_RETURN mapping + +struct resultmap_entry_s { + const CFStringRef checkstr; + const CSSM_RETURN resultcode; +}; +typedef struct resultmap_entry_s resultmap_entry_t; + +#if SECTRUST_OSX +const resultmap_entry_t cssmresultmap[] = { + { CFSTR("SSLHostname"), CSSMERR_APPLETP_HOSTNAME_MISMATCH }, + { CFSTR("email"), CSSMERR_APPLETP_SMIME_EMAIL_ADDRS_NOT_FOUND }, + { CFSTR("IssuerCommonName"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("SubjectCommonName"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("SubjectCommonNamePrefix"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("SubjectCommonNameTEST"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("SubjectOrganization"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("SubjectOrganizationalUnit"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("EAPTrustedServerNames"), CSSMERR_APPLETP_HOSTNAME_MISMATCH }, + { CFSTR("CertificatePolicy"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION }, + { CFSTR("KeyUsage"), CSSMERR_APPLETP_INVALID_KEY_USAGE }, + { CFSTR("ExtendedKeyUsage"), CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE }, + { CFSTR("BasicConstraints"), CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS }, + { CFSTR("QualifiedCertStatements"), CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT }, + { CFSTR("IntermediateSPKISHA256"), CSSMERR_APPLETP_IDENTIFIER_MISSING }, + { CFSTR("IntermediateEKU"), CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE }, + { CFSTR("AnchorSHA1"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("AnchorSHA256"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("AnchorTrusted"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("AnchorApple"), CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH }, + { CFSTR("NonEmptySubject"), CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT }, + { CFSTR("IdLinkage"), CSSMERR_APPLETP_INVALID_AUTHORITY_ID }, + { CFSTR("WeakIntermediates"), CSSMERR_TP_INVALID_CERTIFICATE }, + { CFSTR("WeakLeaf"), CSSMERR_TP_INVALID_CERTIFICATE }, + { CFSTR("WeakRoot"), CSSMERR_TP_INVALID_CERTIFICATE }, + { CFSTR("KeySize"), CSSMERR_CSP_UNSUPPORTED_KEY_SIZE }, + { CFSTR("SignatureHashAlgorithms"), CSSMERR_CSP_ALGID_MISMATCH }, + { CFSTR("CriticalExtensions"), CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN }, + { CFSTR("ChainLength"), CSSMERR_APPLETP_PATH_LEN_CONSTRAINT }, + { CFSTR("BasicCertificateProcessing"), CSSMERR_TP_INVALID_CERTIFICATE }, + { CFSTR("ExtendedValidation"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("Revocation"), CSSMERR_TP_CERT_REVOKED }, + { CFSTR("RevocationResponseRequired"), CSSMERR_TP_VERIFY_ACTION_FAILED }, + { CFSTR("CertificateTransparency"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("BlackListedLeaf"), CSSMERR_TP_CERT_REVOKED }, + { CFSTR("GrayListedLeaf"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("GrayListedKey"), CSSMERR_TP_NOT_TRUSTED }, + { CFSTR("BlackListedKey"), CSSMERR_TP_CERT_REVOKED }, + { CFSTR("CheckLeafMarkerOid"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION }, + { CFSTR("CheckLeafMarkerOidNoValueCheck"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION }, + { CFSTR("CheckIntermediateMarkerOid"), CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION }, + { CFSTR("UsageConstraints"), CSSMERR_APPLETP_TRUST_SETTING_DENY }, + { CFSTR("NotValidBefore"), CSSMERR_TP_CERT_NOT_VALID_YET }, + { CFSTR("ValidIntermediates"), CSSMERR_TP_CERT_EXPIRED }, + { CFSTR("ValidLeaf"), CSSMERR_TP_CERT_EXPIRED }, + { CFSTR("ValidRoot"), CSSMERR_TP_CERT_EXPIRED }, +// { CFSTR("AnchorAppleTestRoots"), }, +// { CFSTR("AnchorAppleTestRootsOnProduction"), }, +// { CFSTR("NoNetworkAccess"), }, +}; +#endif + // // CF boilerplate // @@ -101,6 +168,111 @@ SecTrustSetPolicies(SecTrustRef trustRef, CFTypeRef policies) } #endif +#if SECTRUST_OSX +typedef struct { + SecTrustOptionFlags flags; + CFIndex certIX; + SecTrustRef trustRef; + CFMutableDictionaryRef filteredException; + CFDictionaryRef oldException; +} SecExceptionFilterContext; + +#if 0 +//%%%FIXME SecCFWrappers produces some conflicting definitions on OSX +#include +#else +// inline function from SecCFWrappers.h +static inline char *CFStringToCString(CFStringRef inStr) +{ + if (!inStr) + return (char *)strdup(""); + CFRetain(inStr); // compensate for release on exit + + // need to extract into buffer + CFIndex length = CFStringGetLength(inStr); // in 16-bit character units + size_t len = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); + char *buffer = (char *)malloc(len); // pessimistic + if (!CFStringGetCString(inStr, buffer, len, kCFStringEncodingUTF8)) + buffer[0] = 0; + + CFRelease(inStr); + return buffer; +} +#endif + +static void +filter_exception(const void *key, const void *value, void *context) +{ + SecExceptionFilterContext *ctx = (SecExceptionFilterContext *)context; + if (!ctx) { return; } + + SecTrustOptionFlags options = ctx->flags; + CFMutableDictionaryRef filteredException = ctx->filteredException; + CFStringRef keystr = (CFStringRef)key; + + if (ctx->oldException && CFDictionaryContainsKey(ctx->oldException, key)) { + // Keep existing exception in filtered dictionary, regardless of options + CFDictionaryAddValue(filteredException, key, CFDictionaryGetValue(ctx->oldException, key)); + return; + } + + bool allowed = false; + + if (CFEqual(keystr, CFSTR("SHA1Digest"))) { + allowed = true; // this key is informational and always permitted + } + else if (CFEqual(keystr, CFSTR("NotValidBefore"))) { + allowed = ((options & kSecTrustOptionAllowExpired) != 0); + } + else if (CFEqual(keystr, CFSTR("ValidLeaf"))) { + allowed = ((options & kSecTrustOptionAllowExpired) != 0); + } + else if (CFEqual(keystr, CFSTR("ValidIntermediates"))) { + allowed = ((options & kSecTrustOptionAllowExpired) != 0); + } + else if (CFEqual(keystr, CFSTR("ValidRoot"))) { + if (((options & kSecTrustOptionAllowExpired) != 0) || + ((options & kSecTrustOptionAllowExpiredRoot) != 0)) { + allowed = true; + } + } + else if (CFEqual(keystr, CFSTR("AnchorTrusted"))) { + bool implicitAnchors = ((options & kSecTrustOptionImplicitAnchors) != 0); + // Implicit anchors option only filters exceptions for self-signed certs + if (implicitAnchors && ctx->trustRef && + (ctx->certIX < SecTrustGetCertificateCount(ctx->trustRef))) { + Boolean isSelfSigned = false; + SecCertificateRef cert = SecTrustGetCertificateAtIndex(ctx->trustRef, ctx->certIX); + if (cert && (errSecSuccess == SecCertificateIsSelfSigned(cert, &isSelfSigned)) && + isSelfSigned) { + allowed = true; + } + } + } + else if (CFEqual(keystr, CFSTR("KeyUsage")) || + CFEqual(keystr, CFSTR("ExtendedKeyUsage")) || + CFEqual(keystr, CFSTR("BasicConstraints")) || + CFEqual(keystr, CFSTR("NonEmptySubject")) || + CFEqual(keystr, CFSTR("IdLinkage"))) { + // Cannot override these exceptions + allowed = false; + } + else { + // Unhandled exceptions should not be overridden, + // but we want to know which ones we're missing + char *cstr = CFStringToCString(keystr); + syslog(LOG_ERR, "Unfiltered exception: %s", (cstr) ? cstr : ""); + if (cstr) { free(cstr); } + allowed = false; + } + + if (allowed) { + CFDictionaryAddValue(filteredException, key, value); + } +} + +#endif + /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ OSStatus SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) @@ -122,31 +294,80 @@ SecTrustSetOptions(SecTrustRef trustRef, SecTrustOptionFlags options) #else /* bridge to support API functionality for legacy callers */ OSStatus status = errSecSuccess; -#if 1 -#warning STU: -//%%% need to ensure that the exception covers only the requested options -#else - CFArrayRef details = SecTrustGetDetails(trustRef); // NOTE: performs the evaluation if not done already - CFIndex pathLength = details ? CFArrayGetCount(details) : 0; - CFIndex ix; - for (ix = 0; ix < pathLength; ++ix) { - CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix); - CFIndex detailCount = CFDictionaryGetCount(detail); - if (detailCount > 0) { - // see if we can ignore this error - syslog(LOG_ERR, "SecTrustSetOptions: examining detail dictionary items at ix %ld", (long)ix); - CFShow(detail); + CFDataRef encodedExceptions = SecTrustCopyExceptions(trustRef); + CFArrayRef exceptions = NULL, + oldExceptions = SecTrustGetTrustExceptionsArray(trustRef); + + if (encodedExceptions) { + exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault, + encodedExceptions, kCFPropertyListImmutable, NULL, NULL); + CFRelease(encodedExceptions); + encodedExceptions = NULL; + } + + if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) { + CFRelease(exceptions); + exceptions = NULL; + } + + if (oldExceptions && exceptions && + CFArrayGetCount(oldExceptions) > CFArrayGetCount(exceptions)) { + oldExceptions = NULL; + } + + /* verify both exceptions are for the same leaf */ + if (oldExceptions && exceptions && CFArrayGetCount(oldExceptions) > 0) { + CFDictionaryRef oldLeafExceptions = (CFDictionaryRef)CFArrayGetValueAtIndex(oldExceptions, 0); + CFDictionaryRef leafExceptions = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, 0); + CFDataRef oldDigest = (CFDataRef)CFDictionaryGetValue(oldLeafExceptions, CFSTR("SHA1Digest")); + CFDataRef digest = (CFDataRef)CFDictionaryGetValue(leafExceptions, CFSTR("SHA1Digest")); + if (!oldDigest || !digest || !CFEqual(oldDigest, digest)) { + oldExceptions = NULL; } } - syslog(LOG_ERR, "SecTrustSetOptions: creating trust exception"); -#endif - CFDataRef exceptions = SecTrustCopyExceptions(trustRef); + + /* add only those exceptions which are allowed by the supplied options */ if (exceptions) { - SecTrustSetExceptions(trustRef, exceptions); + CFMutableArrayRef filteredExceptions = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFIndex i, exceptionCount = (filteredExceptions) ? CFArrayGetCount(exceptions) : 0; + + for (i = 0; i < exceptionCount; ++i) { + CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(exceptions, i); + CFDictionaryRef oldException = NULL; + if (oldExceptions && i < CFArrayGetCount(oldExceptions)) { + oldException = (CFDictionaryRef)CFArrayGetValueAtIndex(oldExceptions, i); + } + CFMutableDictionaryRef filteredException = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (exception && filteredException) { + SecExceptionFilterContext filterContext = { options, i, trustRef, filteredException, oldException }; + CFDictionaryApplyFunction(exception, filter_exception, &filterContext); + CFArrayAppendValue(filteredExceptions, filteredException); + CFRelease(filteredException); + } + } + + if (filteredExceptions) { + CFIndex filteredCount = CFArrayGetCount(filteredExceptions); + /* remove empty trailing entries to match iOS behavior */ + for (i = filteredCount; i-- > 1;) { + CFDictionaryRef exception = (CFDictionaryRef)CFArrayGetValueAtIndex(filteredExceptions, i); + if (CFDictionaryGetCount(exception) == 0) { + CFArrayRemoveValueAtIndex(filteredExceptions, i); + } else { + break; + } + } + encodedExceptions = CFPropertyListCreateData(kCFAllocatorDefault, + filteredExceptions, kCFPropertyListBinaryFormat_v1_0, 0, NULL); + CFRelease(filteredExceptions); + + SecTrustSetExceptions(trustRef, encodedExceptions); + CFRelease(encodedExceptions); + } CFRelease(exceptions); } - #if SECTRUST_DEPRECATION_WARNINGS bool displayModifyMsg = false; bool displayNetworkMsg = false; @@ -341,7 +562,7 @@ OSStatus SecTrustEvaluate(SecTrustRef trust, SecTrustResultType *resultP) } - secdebug("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult); + secnotice("SecTrustEvaluate", "SecTrustEvaluate trust result = %d", (int)trustResult); if (resultP) { *resultP = trustResult; } @@ -389,112 +610,21 @@ OSStatus SecTrustGetResult( #else /* bridge to support old functionality */ #if SECTRUST_DEPRECATION_WARNINGS - syslog(LOG_ERR, "WARNING: SecTrustGetResult has been deprecated since 10.7, and may not return a statusChain in 10.11. Please use SecTrustGetTrustResult instead."); + syslog(LOG_ERR, "WARNING: SecTrustGetResult has been deprecated since 10.7. Please use SecTrustGetTrustResult instead."); #endif - SecTrustResultType trustResult; - OSStatus status = SecTrustGetTrustResult(trustRef, &trustResult); + SecTrustResultType trustResult; + OSStatus status = SecTrustGetTrustResult(trustRef, &trustResult); + if (status != errSecSuccess) { + return status; + } if (result) { *result = trustResult; } - if (certChain && !statusChain) { - /* This is the easy case; caller only wants cert chain and not status chain. */ - CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFIndex idx, count = SecTrustGetCertificateCount(trustRef); - for (idx=0; idx < count; idx++) { - SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trustRef, idx); - if (certificate) { - CFArrayAppendValue(certArray, certificate); - } - } - *certChain = certArray; - } - else if (certChain && statusChain) { - /* - * Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO* is tied to a - * Trust object and does not exist in the new unified world. Unfortunately, some clients are - * still calling this legacy API and grubbing through the info for StatusBits and StatusCodes. - * If they want this info, then we have to do a legacy evaluation to get it. The info struct - * goes away once the old-style object does, so we must keep the old-style object alive after - * returning from the function. - * - * TODO: keep a dictionary and figure out how to expire entries when no longer needed., - * or build the evidence info ourselves: rdar://21005914 - */ - static CFMutableArrayRef sTrustArray = NULL; - - // make array of Certificate instances from unified SecCertificateRefs - CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFIndex idx, count = SecTrustGetCertificateCount(trustRef); - for (idx=0; idx < count; idx++) { - SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trustRef, idx); - if (certificate) { - SecCertificateRef itemImplRef = SecCertificateCreateItemImplInstance(certificate); - if (itemImplRef) { - CFArrayAppendValue(certArray, itemImplRef); - CFRelease(itemImplRef); - } - } - } - // make array of Policy instances from unified SecPolicyRefs - CFMutableArrayRef policyArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayRef policies = NULL; - status = SecTrustCopyPolicies(trustRef, &policies); - count = (!status && policies) ? CFArrayGetCount(policies) : 0; - for (idx=0; idx < count; idx++) { - SecPolicyRef policy = (SecPolicyRef) CFArrayGetValueAtIndex(policies, idx); - if (policy) { - SecPolicyRef itemImplRef = SecPolicyCreateItemImplInstance(policy); - if (itemImplRef) { - CFArrayAppendValue(policyArray, itemImplRef); - CFRelease(itemImplRef); - } - } - } - // now make a Trust instance and evaluate it - try { - Trust *trustObj = new Trust(certArray, policyArray); - SecTrustRef trust = trustObj->handle(); - if (!trust) { - MacOSError::throwMe(errSecTrustNotAvailable); - } - if (!sTrustArray) { - sTrustArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - if (!sTrustArray) { - MacOSError::throwMe(errSecAllocate); - } - } - // fetch the built cert chain and status chain - CFArrayRef itemImplCertArray = NULL; - trustObj->evaluate(); - trustObj->buildEvidence(itemImplCertArray, TPEvidenceInfo::overlayVar(*statusChain)); - - // convert each Certificate in the built chain to a unified SecCertificateRef - CFMutableArrayRef outCertChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFIndex idx, count = (itemImplCertArray) ? CFArrayGetCount(itemImplCertArray) : 0; - for (idx=0; idx < count; idx++) { - SecCertificateRef inCert = (SecCertificateRef) CFArrayGetValueAtIndex(itemImplCertArray, idx); - SecCertificateRef outCert = SecCertificateCreateFromItemImplInstance(inCert); - if (outCert) { - CFArrayAppendValue(outCertChain, outCert); - CFRelease(outCert); - } - } - *certChain = outCertChain; - if (itemImplCertArray) { - CFRelease(itemImplCertArray); - } - CFArrayAppendValue(sTrustArray, trust); - status = errSecSuccess; - } - 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 (policyArray) - CFRelease(policyArray); - if (certArray) - CFRelease(certArray); + if (certChain) { + *certChain = SecTrustCopyConstructedChain(trustRef); + } + if (statusChain) { + *statusChain = SecTrustGetEvidenceInfo(trustRef); } return status; #endif @@ -564,29 +694,146 @@ OSStatus SecTrustGetCssmResult(SecTrustRef trust, CSSM_TP_VERIFY_CONTEXT_RESULT_ } #if SECTRUST_OSX -static void applyPropertyToCssmResultCode(const void *_key, const void *_value, void *context) { - CFStringRef key = (CFStringRef)_key; - CFStringRef value = (CFStringRef)_value; - OSStatus *result = (OSStatus *)context; - if (CFGetTypeID(_value) != CFStringGetTypeID()) { - return; +// +// Returns a malloced array of CSSM_RETURN values, with the length in numStatusCodes, +// for the certificate specified by chain index in the given SecTrustRef. +// +// To match legacy behavior, the array actually allocates one element more than the +// value of numStatusCodes; if the certificate is revoked, the additional element +// at the end contains the CrlReason value. +// +// Caller must free the returned pointer. +// +static CSSM_RETURN *copyCssmStatusCodes(SecTrustRef trust, + unsigned int index, unsigned int *numStatusCodes) +{ + if (!trust || !numStatusCodes) { + return NULL; } - if (!CFEqual(CFSTR("value"), key)) { - return; + *numStatusCodes = 0; + CFArrayRef details = SecTrustGetDetails(trust); + CFIndex chainLength = (details) ? CFArrayGetCount(details) : 0; + if (!(index < chainLength)) { + return NULL; } - if (CFEqual(CFSTR("Invalid certificate chain linkage."), value)) { - *result = CSSMERR_APPLETP_INVALID_ID_LINKAGE; - } else if (CFEqual(CFSTR("One or more unsupported critical extensions found."), value)) { - *result = CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN; - } else if (CFEqual(CFSTR("Root certificate is not trusted."), value)) { - *result = CSSMERR_TP_NOT_TRUSTED; - } else if (CFEqual(CFSTR("Hostname mismatch."), value)) { - *result = CSSMERR_APPLETP_HOSTNAME_MISMATCH; - } else if (CFEqual(CFSTR("One or more certificates have expired or are not valid yet."), value)) { - *result = CSSMERR_TP_CERT_EXPIRED; - } else if (CFEqual(CFSTR("Policy requirements not met."), value)) { - *result = CSSMERR_TP_VERIFY_ACTION_FAILED; + CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, index); + CFIndex ix, detailCount = CFDictionaryGetCount(detail); + *numStatusCodes = (unsigned int)detailCount; + + // Allocate one more entry than we need; this is used to store a CrlReason + // at the end of the array. + CSSM_RETURN *statusCodes = (CSSM_RETURN*)malloc((detailCount+1) * sizeof(CSSM_RETURN)); + statusCodes[*numStatusCodes] = 0; + + const unsigned int resultmaplen = sizeof(cssmresultmap) / sizeof(resultmap_entry_t); + const void *keys[detailCount]; + CFDictionaryGetKeysAndValues(detail, &keys[0], NULL); + for (ix = 0; ix < detailCount; ix++) { + CFStringRef key = (CFStringRef)keys[ix]; + CSSM_RETURN statusCode = CSSM_OK; + for (unsigned int mapix = 0; mapix < resultmaplen; mapix++) { + CFStringRef str = (CFStringRef) cssmresultmap[mapix].checkstr; + if (CFStringCompare(str, key, 0) == kCFCompareEqualTo) { + statusCode = (CSSM_RETURN) cssmresultmap[mapix].resultcode; + break; + } + } + if (statusCode == CSSMERR_TP_CERT_REVOKED) { + SInt32 reason; + CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(detail, key); + if (number && CFNumberGetValue(number, kCFNumberSInt32Type, &reason)) { + statusCodes[*numStatusCodes] = (CSSM_RETURN)reason; + } + } + statusCodes[ix] = statusCode; } + + return statusCodes; +} + +static uint8_t convertCssmResultToPriority(CSSM_RETURN resultCode) { + switch (resultCode) { + /* explicitly not trusted */ + case CSSMERR_TP_CERT_REVOKED: + case CSSMERR_APPLETP_TRUST_SETTING_DENY: + return 1; + /* failure to comply with X.509 */ + case CSSMERR_APPLETP_NO_BASIC_CONSTRAINTS: + case CSSMERR_APPLETP_UNKNOWN_QUAL_CERT_STATEMENT: + case CSSMERR_APPLETP_INVALID_EMPTY_SUBJECT: + case CSSMERR_APPLETP_INVALID_AUTHORITY_ID: + case CSSMERR_TP_INVALID_CERTIFICATE: + case CSSMERR_APPLETP_UNKNOWN_CRITICAL_EXTEN: + return 2; + case CSSMERR_TP_CERT_EXPIRED: + return 3; + /* doesn't chain to trusted root */ + case CSSMERR_TP_NOT_TRUSTED: + case CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH: + return 4; + /* all others are policy-specific failures */ + default: + return 5; + } +} + +#include +#include +static bool isSoftwareUpdateDevelopment(SecTrustRef trust) { + bool isPolicy = false, isEKU = false; + CFArrayRef policies = NULL; + + /* Policy used to evaluate was SWUpdateSigning */ + SecTrustCopyPolicies(trust, &policies); + if (policies) { + SecPolicyRef swUpdatePolicy = SecPolicyCreateAppleSWUpdateSigning(); + if (swUpdatePolicy && CFArrayContainsValue(policies, CFRangeMake(0, CFArrayGetCount(policies)), + swUpdatePolicy)) { + isPolicy = true; + } + if (swUpdatePolicy) { CFRelease(swUpdatePolicy); } + CFRelease(policies); + } + if (!isPolicy) { + return false; + } + + /* Only error was EKU on the leaf */ + CFArrayRef details = SecTrustGetDetails(trust); + CFIndex ix, count = CFArrayGetCount(details); + for (ix = 0; ix < count; ix++) { + CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix); + if (ix == 0) { // Leaf + if (CFDictionaryGetCount(detail) != 1 || // One error + CFDictionaryGetValue(detail, CFSTR("ExtendedKeyUsage")) != kCFBooleanFalse) // kSecPolicyCheckExtendedKeyUsage + return false; + } else { + if (CFDictionaryGetCount(detail) > 0) { // No errors on other certs + return false; + } + } + } + + /* EKU on the leaf is the Apple Development Code Signing OID */ + SecCertificateRef leaf = SecTrustGetCertificateAtIndex(trust, 0); + CSSM_DATA *fieldValue = NULL; + if (errSecSuccess != SecCertificateCopyFirstFieldValue(leaf, &CSSMOID_ExtendedKeyUsage, &fieldValue)) { + return false; + } + if (fieldValue && fieldValue->Data && fieldValue->Length == sizeof(CSSM_X509_EXTENSION)) { + const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)fieldValue->Data; + if (ext->format == CSSM_X509_DATAFORMAT_PARSED) { + const CE_ExtendedKeyUsage *ekus = (const CE_ExtendedKeyUsage *)ext->value.parsedValue; + if (ekus && (ekus->numPurposes == 1) && ekus->purposes[0].Data && + (ekus->purposes[0].Length == CSSMOID_APPLE_EKU_CODE_SIGNING_DEV.Length) && + (memcmp(ekus->purposes[0].Data, CSSMOID_APPLE_EKU_CODE_SIGNING_DEV.Data, + ekus->purposes[0].Length) == 0)) { + isEKU = true; + } + } + } + SecCertificateReleaseFirstFieldValue(leaf, &CSSMOID_ExtendedKeyUsage, fieldValue); + return isEKU; } #endif @@ -612,24 +859,48 @@ OSStatus SecTrustGetCssmResultCode(SecTrustRef trustRef, OSStatus *result) if (!trustRef || !result) { return errSecParam; } - CFArrayRef properties = SecTrustCopyProperties(trustRef); - if (!properties) { - *result = 0; - return errSecSuccess; - } - OSStatus cssmResultCode = 0; - CFIndex ix, count = CFArrayGetCount(properties); - for (ix = 0; ix < count; ++ix) { - CFDictionaryRef property = (CFDictionaryRef) - CFArrayGetValueAtIndex(properties, ix); - CFDictionaryApplyFunction(property, applyPropertyToCssmResultCode, &cssmResultCode); - } + + SecTrustResultType trustResult = kSecTrustResultInvalid; + (void) SecTrustGetTrustResult(trustRef, &trustResult); + if (trustResult == kSecTrustResultProceed || trustResult == kSecTrustResultUnspecified) { + if (result) { *result = 0; } + return errSecSuccess; + } + + /* Development Software Update certs return a special error code when evaluated + * against the AppleSWUpdateSigning policy. See . */ + if (isSoftwareUpdateDevelopment(trustRef)) { + if (result) { + *result = CSSMERR_APPLETP_CODE_SIGN_DEVELOPMENT; + } + return errSecSuccess; + } + + OSStatus cssmResultCode = errSecSuccess; + uint8_t resultCodePriority = 0xFF; + CFIndex ix, count = SecTrustGetCertificateCount(trustRef); + for (ix = 0; ix < count; ix++) { + unsigned int numStatusCodes; + CSSM_RETURN *statusCodes = NULL; + statusCodes = copyCssmStatusCodes(trustRef, (uint32_t)ix, &numStatusCodes); + if (statusCodes && numStatusCodes > 0) { + unsigned int statusIX; + for (statusIX = 0; statusIX < numStatusCodes; statusIX++) { + CSSM_RETURN currStatus = statusCodes[statusIX]; + uint8_t currPriotiy = convertCssmResultToPriority(currStatus); + if (resultCodePriority > currPriotiy) { + cssmResultCode = currStatus; + resultCodePriority = currPriotiy; + } + } + } + if (statusCodes) { free(statusCodes); } + if (resultCodePriority == 1) { break; } + } + if (result) { *result = cssmResultCode; } - if (properties) { - CFRelease(properties); - } return errSecSuccess; #endif } @@ -884,6 +1155,312 @@ SecCertificateRef SecTrustGetCertificateAtIndex(SecTrustRef trust, CFIndex ix) } #endif +// cannot link against the new iOS SecTrust from this implementation, +// so there are no possible accessors for the fields of this struct +typedef struct __TSecTrust { + CFRuntimeBase _base; + CFArrayRef _certificates; + CFArrayRef _anchors; + CFTypeRef _policies; + CFArrayRef _responses; + CFArrayRef _SCTs; + CFArrayRef _trustedLogs; + CFDateRef _verifyDate; + CFTypeRef _chain; + SecKeyRef _publicKey; + CFArrayRef _details; + CFDictionaryRef _info; + CFArrayRef _exceptions; + SecTrustResultType _trustResult; + bool _anchorsOnly; + bool _keychainsAllowed; + void* _legacy_info_array; + void* _legacy_status_array; + SecTrustResultType _trustResultBeforeExceptions; +} TSecTrust; + +#if SECTRUST_OSX +CFArrayRef SecTrustCopyInputCertificates(SecTrustRef trust) +{ + if (!trust) { return NULL; }; + TSecTrust *secTrust = (TSecTrust *)trust; + if (secTrust->_certificates) { + CFRetain(secTrust->_certificates); + } + return secTrust->_certificates; +} +#endif + +#if SECTRUST_OSX +CFArrayRef SecTrustCopyInputAnchors(SecTrustRef trust) +{ + if (!trust) { return NULL; }; + TSecTrust *secTrust = (TSecTrust *)trust; + if (secTrust->_anchors) { + CFRetain(secTrust->_anchors); + } + return secTrust->_anchors; +} +#endif + +#if SECTRUST_OSX +// Return the constructed certificate chain for this trust reference, +// making output certificates pointer-equivalent to any provided input +// certificates (where possible) for legacy behavioral compatibility. +// Caller must release this array. +// +CFArrayRef SecTrustCopyConstructedChain(SecTrustRef trust) +{ + CFMutableArrayRef certChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFIndex idx, count = SecTrustGetCertificateCount(trust); + for (idx=0; idx < count; idx++) { + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, idx); + if (certificate) { + CFArrayAppendValue(certChain, certificate); + } + } + // + // Some callers make the assumption that the certificates in + // this chain are pointer-equivalent to ones they passed to the + // SecTrustCreateWithCertificates function. We'll maintain that + // behavior here for compatibility. + // + CFArrayRef inputCertArray = SecTrustCopyInputCertificates(trust); + CFArrayRef inputAnchorArray = SecTrustCopyInputAnchors(trust); + CFIndex inputCertIdx, inputCertCount = (inputCertArray) ? CFArrayGetCount(inputCertArray) : 0; + CFIndex inputAnchorIdx, inputAnchorCount = (inputAnchorArray) ? CFArrayGetCount(inputAnchorArray) : 0; + for (idx=0; idx < count; idx++) { + SecCertificateRef tmpCert = (SecCertificateRef) CFArrayGetValueAtIndex(certChain, idx); + if (tmpCert) { + SecCertificateRef matchCert = NULL; + for (inputCertIdx=0; inputCertIdx < inputCertCount && !matchCert; inputCertIdx++) { + SecCertificateRef inputCert = (SecCertificateRef) CFArrayGetValueAtIndex(inputCertArray, inputCertIdx); + if (inputCert && CFEqual(inputCert, tmpCert)) { + matchCert = inputCert; + } + } + for (inputAnchorIdx=0; inputAnchorIdx < inputAnchorCount && !matchCert; inputAnchorIdx++) { + SecCertificateRef inputAnchor = (SecCertificateRef) CFArrayGetValueAtIndex(inputAnchorArray, inputAnchorIdx); + if (inputAnchor && CFEqual(inputAnchor, tmpCert)) { + matchCert = inputAnchor; + } + } + if (matchCert) { + CFArraySetValueAtIndex(certChain, idx, matchCert); + } + } + } + if (inputCertArray) { + CFRelease(inputCertArray); + } + if (inputAnchorArray) { + CFRelease(inputAnchorArray); + } + return certChain; +} +#endif + +#if SECTRUST_OSX +// +// Here is where backward compatibility gets ugly. CSSM_TP_APPLE_EVIDENCE_INFO does not exist +// in the unified SecTrust world. Unfortunately, some clients are still calling legacy APIs +// (e.g. SecTrustGetResult) and grubbing through the info for StatusBits and StatusCodes. +// SecTrustGetEvidenceInfo builds the legacy evidence info structure as needed, and returns +// a pointer to it. The evidence data is allocated here and set in the _legacy_* fields +// of the TSecTrust; the trust object subsequently owns it. The returned pointer is expected +// to be valid for the lifetime of the SecTrustRef, or until the trust parameters are changed, +// which would force re-evaluation. +// +static CSSM_TP_APPLE_EVIDENCE_INFO * +SecTrustGetEvidenceInfo(SecTrustRef trust) +{ + TSecTrust *secTrust = (TSecTrust *)trust; + if (!secTrust) { + return NULL; + } + if (secTrust->_trustResult != kSecTrustSettingsResultInvalid && + secTrust->_legacy_info_array) { + // we've already got valid evidence info, return it now. + return (CSSM_TP_APPLE_EVIDENCE_INFO *)secTrust->_legacy_info_array; + } + + // Getting the count implicitly evaluates the chain if necessary. + CFIndex idx, count = SecTrustGetCertificateCount(trust); + CFArrayRef inputCertArray = SecTrustCopyInputCertificates(trust); + CFArrayRef inputAnchorArray = SecTrustCopyInputAnchors(trust); + CFIndex inputCertIdx, inputCertCount = (inputCertArray) ? CFArrayGetCount(inputCertArray) : 0; + CFIndex inputAnchorIdx, inputAnchorCount = (inputAnchorArray) ? CFArrayGetCount(inputAnchorArray) : 0; + + CSSM_TP_APPLE_EVIDENCE_INFO *infoArray = (CSSM_TP_APPLE_EVIDENCE_INFO *)calloc(count, sizeof(CSSM_TP_APPLE_EVIDENCE_INFO)); + CSSM_RETURN *statusArray = NULL; + unsigned int numStatusCodes = 0; + + // Set status codes for each certificate in the constructed chain + for (idx=0; idx < count; idx++) { + SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, idx); + if (!cert) { + continue; + } + CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &infoArray[idx]; + + /* first the booleans (StatusBits flags) */ + CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); + if (secTrust->_verifyDate) { + now = CFDateGetAbsoluteTime(secTrust->_verifyDate); + } + CFAbsoluteTime na = SecCertificateNotValidAfter(cert); + if (na < now) { + evInfo->StatusBits |= CSSM_CERT_STATUS_EXPIRED; + } + CFAbsoluteTime nb = SecCertificateNotValidBefore(cert); + if (nb > now) { + evInfo->StatusBits |= CSSM_CERT_STATUS_NOT_VALID_YET; + } + for (inputAnchorIdx=0; inputAnchorIdx < inputAnchorCount; inputAnchorIdx++) { + SecCertificateRef inputAnchor = (SecCertificateRef) CFArrayGetValueAtIndex(inputAnchorArray, inputAnchorIdx); + if (inputAnchor && CFEqual(inputAnchor, cert)) { + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_IN_ANCHORS; + break; + } + } + for (inputCertIdx=0; inputCertIdx < inputCertCount; inputCertIdx++) { + SecCertificateRef inputCert = (SecCertificateRef) CFArrayGetValueAtIndex(inputCertArray, inputCertIdx); + if (inputCert && CFEqual(inputCert, cert)) { + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_IN_INPUT_CERTS; + break; + } + } + + /* See if there are trust settings for this certificate. */ + CFStringRef hashStr = SecTrustSettingsCertHashStrFromCert(cert); + bool foundMatch = false; + bool foundAny = false; + CSSM_RETURN *errors = NULL; + uint32 errorCount = 0; + OSStatus status = 0; + SecTrustSettingsDomain foundDomain = 0; + SecTrustSettingsResult foundResult = kSecTrustSettingsResultInvalid; + bool isSelfSigned = false; + if ((count - 1) == idx) { + // Only the last cert in the chain needs to be considered + Boolean selfSigned; + status = SecCertificateIsSelfSigned(cert, &selfSigned); + isSelfSigned = (status) ? false : ((selfSigned) ? true : false); + if (isSelfSigned) { + evInfo->StatusBits |= CSSM_CERT_STATUS_IS_ROOT; + } + } + // STU: rdar://25554967 + // %%% need to get policyOID, policyString, and keyUsage here! + + status = SecTrustSettingsEvaluateCert( + hashStr, /* certHashStr */ + NULL, /* policyOID (optional) */ + NULL, /* policyString (optional) */ + 0, /* policyStringLen */ + 0, /* keyUsage */ + isSelfSigned, /* isRootCert */ + &foundDomain, /* foundDomain */ + &errors, /* allowedErrors -- MUST FREE */ + &errorCount, /* numAllowedErrors */ + &foundResult, /* resultType */ + &foundMatch, /* foundMatchingEntry */ + &foundAny); /* foundAnyEntry */ + + if (status == errSecSuccess) { + if (foundMatch) { + switch (foundResult) { + case kSecTrustSettingsResultTrustRoot: + case kSecTrustSettingsResultTrustAsRoot: + /* these two can be disambiguated by IS_ROOT */ + evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST; + break; + case kSecTrustSettingsResultDeny: + evInfo->StatusBits |= CSSM_CERT_STATUS_TRUST_SETTINGS_DENY; + break; + case kSecTrustSettingsResultUnspecified: + case kSecTrustSettingsResultInvalid: + default: + break; + } + } + } + if (errors) { + free(errors); + } + if (hashStr) { + CFRelease(hashStr); + } + + unsigned int numCodes=0; + CSSM_RETURN *statusCodes = copyCssmStatusCodes(trust, (unsigned int)idx, &numCodes); + if (statusCodes) { + // Realloc space for these status codes at end of our status codes block. + // Two important things to note: + // 1. the actual length is numCodes+1 because copyCssmStatusCodes + // allocates one more element at the end for the CrlReason value. + // 2. realloc may cause the pointer to move, which means we will + // need to fix up the StatusCodes fields after we're done with this loop. + unsigned int totalStatusCodes = numStatusCodes + numCodes + 1; + statusArray = (CSSM_RETURN *)realloc(statusArray, totalStatusCodes * sizeof(CSSM_RETURN)); + evInfo->StatusCodes = &statusArray[numStatusCodes]; + evInfo->NumStatusCodes = numCodes; + // Copy the new codes (plus one) into place + for (unsigned int cpix = 0; cpix <= numCodes; cpix++) { + evInfo->StatusCodes[cpix] = statusCodes[cpix]; + } + numStatusCodes = totalStatusCodes; + free(statusCodes); + } + + if(evInfo->StatusBits & (CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST | + CSSM_CERT_STATUS_TRUST_SETTINGS_DENY | + CSSM_CERT_STATUS_TRUST_SETTINGS_IGNORED_ERROR)) { + /* Something noteworthy happened involving TrustSettings */ + uint32 whichDomain = 0; + switch(foundDomain) { + case kSecTrustSettingsDomainUser: + whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_USER; + break; + case kSecTrustSettingsDomainAdmin: + whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_ADMIN; + break; + case kSecTrustSettingsDomainSystem: + whichDomain = CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM; + break; + } + evInfo->StatusBits |= whichDomain; + } + + /* index into raw cert group or AnchorCerts depending on IS_IN_ANCHORS */ + //evInfo->Index = certInfo->index(); + /* nonzero if cert came from a DLDB */ + //evInfo->DlDbHandle = certInfo->dlDbHandle(); + //evInfo->UniqueRecord = certInfo->uniqueRecord(); + } + + // Now that all the status codes have been allocated in a contiguous block, + // refresh the StatusCodes pointer in each array element. + numStatusCodes = 0; + for (idx=0; idx < count; idx++) { + CSSM_TP_APPLE_EVIDENCE_INFO *evInfo = &infoArray[idx]; + evInfo->StatusCodes = &statusArray[numStatusCodes]; + numStatusCodes += evInfo->NumStatusCodes + 1; + } + + secTrust->_legacy_info_array = infoArray; + secTrust->_legacy_status_array = statusArray; + + if (inputCertArray) { + CFRelease(inputCertArray); + } + if (inputAnchorArray) { + CFRelease(inputAnchorArray); + } + + return (CSSM_TP_APPLE_EVIDENCE_INFO *)secTrust->_legacy_info_array; +} +#endif #if !SECTRUST_OSX static CFStringRef kSecCertificateDetailSHA1Digest = CFSTR("SHA1Digest"); @@ -1074,9 +1651,13 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) /* new in 10.9 */ bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions) { - CFArrayRef exceptions; - exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault, - encodedExceptions, kCFPropertyListImmutable, NULL, NULL); + CFArrayRef exceptions = NULL; + + if (NULL != encodedExceptions) { + exceptions = (CFArrayRef)CFPropertyListCreateWithData(kCFAllocatorDefault, + encodedExceptions, kCFPropertyListImmutable, NULL, NULL); + } + if (exceptions && CFGetTypeID(exceptions) != CFArrayGetTypeID()) { CFRelease(exceptions); exceptions = NULL; @@ -1084,6 +1665,8 @@ bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef encodedExceptions) OSStatus __secapiresult = errSecSuccess; try { + /* Exceptions are being set or cleared, we'll need to re-evaluate trust either way. */ + Trust::required(trust)->setResult(kSecTrustResultInvalid); Trust::required(trust)->exceptions(exceptions); } catch (const MacOSError &err) { __secapiresult=err.osStatus(); } @@ -1153,6 +1736,59 @@ SecTrustCopyProperties(SecTrustRef trust) } return result; } +#else +CFArrayRef SecTrustCopyProperties(SecTrustRef trust) { + /* OS X creates a completely different structure with one dictionary for each certificate */ + CFIndex ix, count = SecTrustGetCertificateCount(trust); + + CFMutableArrayRef properties = CFArrayCreateMutable(kCFAllocatorDefault, count, + &kCFTypeArrayCallBacks); + + for (ix = 0; ix < count; ix++) { + CFMutableDictionaryRef certDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + /* Populate the certificate title */ + SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, ix); + if (cert) { + CFStringRef subjectSummary = SecCertificateCopySubjectSummary(cert); + if (subjectSummary) { + CFDictionaryAddValue(certDict, kSecPropertyTypeTitle, subjectSummary); + CFRelease(subjectSummary); + } + } + + /* Populate a revocation reason if the cert was revoked */ + unsigned int numStatusCodes; + CSSM_RETURN *statusCodes = NULL; + statusCodes = copyCssmStatusCodes(trust, (uint32_t)ix, &numStatusCodes); + if (statusCodes) { + int32_t reason = statusCodes[numStatusCodes]; // stored at end of status codes array + if (reason > 0) { + CFNumberRef cfreason = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &reason); + if (cfreason) { + CFDictionarySetValue(certDict, kSecTrustRevocationReason, cfreason); + CFRelease(cfreason); + } + } + free(statusCodes); + } + + /* Populate the error in the leaf dictionary */ + if (ix == 0) { + OSStatus error = errSecSuccess; + (void)SecTrustGetCssmResultCode(trust, &error); + CFStringRef errorStr = SecCopyErrorMessageString(error, NULL); + if (errorStr) { + CFDictionarySetValue(certDict, kSecPropertyTypeError, errorStr); + CFRelease(errorStr); + } + } + + CFArrayAppendValue(properties, certDict); + } + + return properties; +} #endif /* deprecated in 10.5 */ diff --git a/OSX/libsecurity_keychain/lib/SecTrust.h b/OSX/libsecurity_keychain/lib/SecTrust.h index 86ae0fc3..d8ec764c 100644 --- a/OSX/libsecurity_keychain/lib/SecTrust.h +++ b/OSX/libsecurity_keychain/lib/SecTrust.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-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, @@ -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@ */ @@ -34,9 +34,7 @@ #include #include -#if defined(__cplusplus) -extern "C" { -#endif +__BEGIN_DECLS CF_ASSUME_NONNULL_BEGIN CF_IMPLICIT_BRIDGING_ENABLED @@ -82,17 +80,15 @@ CF_IMPLICIT_BRIDGING_ENABLED of trust evaluation. This value may be returned by the SecTrustEvaluate function but not stored as part of the user trust settings. */ - -typedef uint32_t SecTrustResultType; -enum { - kSecTrustResultInvalid = 0, - kSecTrustResultProceed = 1, - kSecTrustResultConfirm CF_ENUM_DEPRECATED(10_0, 10_9, NA, NA) = 2, - kSecTrustResultDeny = 3, - kSecTrustResultUnspecified = 4, - kSecTrustResultRecoverableTrustFailure = 5, - kSecTrustResultFatalTrustFailure = 6, - kSecTrustResultOtherError = 7 +typedef CF_ENUM(uint32_t, SecTrustResultType) { + kSecTrustResultInvalid CF_ENUM_AVAILABLE(10_3, 2_0) = 0, + kSecTrustResultProceed CF_ENUM_AVAILABLE(10_3, 2_0) = 1, + kSecTrustResultConfirm CF_ENUM_DEPRECATED(10_3, 10_9, 2_0, 7_0) = 2, + kSecTrustResultDeny CF_ENUM_AVAILABLE(10_3, 2_0) = 3, + kSecTrustResultUnspecified CF_ENUM_AVAILABLE(10_3, 2_0) = 4, + kSecTrustResultRecoverableTrustFailure CF_ENUM_AVAILABLE(10_3, 2_0) = 5, + kSecTrustResultFatalTrustFailure CF_ENUM_AVAILABLE(10_3, 2_0) = 6, + kSecTrustResultOtherError CF_ENUM_AVAILABLE(10_3, 2_0) = 7 }; /*! @@ -150,6 +146,12 @@ extern const CFStringRef kSecPropertyTypeError value of kCFBooleanTrue. The value will be a CFDateRef representing the earliest date at which the revocation info for one of the certificates in this chain might change. + @constant kSecTrustCertificateTransparency + This key will be present and have a value of kCFBooleanTrue + if this chain is CT qualified. + @constant kSecTrustCertificateTransparencyWhiteList + This key will be present and have a value of kCFBooleanTrue + if this chain is EV, not CT qualified, but included of the CT WhiteList. */ extern const CFStringRef kSecTrustEvaluationDate __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); @@ -163,6 +165,10 @@ extern const CFStringRef kSecTrustRevocationChecked __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecTrustRevocationValidUntilDate __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); +extern const CFStringRef kSecTrustCertificateTransparency + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); +extern const CFStringRef kSecTrustCertificateTransparencyWhiteList + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); #ifdef __BLOCKS__ /*! @@ -318,7 +324,7 @@ OSStatus SecTrustSetVerifyDate(SecTrustRef trust, CFDateRef verifyDate) /*! @function SecTrustGetVerifyTime @abstract Returns the verify time. - 4 + @param trust A reference to the trust object being verified. @result A CFAbsoluteTime value representing the time at which certificates should be checked for validity. @discussion This function retrieves the verification time for the given @@ -441,8 +447,9 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) @abstract Set a trust cookie to be used for evaluating this certificate chain. @param trust A reference to a trust object. @param exceptions An exceptions cookie as returned by a call to - SecTrustCopyExceptions() in the past. - @result Upon calling SecTrustEvaluate(), any failures that where present at the + SecTrustCopyExceptions() in the past. You may pass NULL to clear any + exceptions which have been previously set on this trust reference. + @result Upon calling SecTrustEvaluate(), any failures that were present at the time the exceptions object was created are ignored, and instead of returning kSecTrustResultRecoverableTrustFailure, kSecTrustResultProceed will be returned (if the certificate for which exceptions was created matches the current leaf @@ -459,7 +466,7 @@ CFDataRef SecTrustCopyExceptions(SecTrustRef trust) of the wireless network for which this cert is needed, the account for which this cert should be considered valid, and so on. */ -bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef exceptions) +bool SecTrustSetExceptions(SecTrustRef trust, CFDataRef __nullable exceptions) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_4_0); /*! @@ -625,7 +632,7 @@ OSStatus SecTrustSetKeychains(SecTrustRef trust, CFTypeRef __nullable keychainOr for the evaluation, use SecTrustGetTrustResult. */ OSStatus SecTrustGetResult(SecTrustRef trustRef, SecTrustResultType * __nullable result, - CFArrayRef * __nonnull CF_RETURNS_RETAINED certChain, CSSM_TP_APPLE_EVIDENCE_INFO * __nullable * __nonnull statusChain) + CFArrayRef * __nullable CF_RETURNS_RETAINED certChain, CSSM_TP_APPLE_EVIDENCE_INFO * __nullable * __nullable statusChain) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_2, __MAC_10_7, __IPHONE_NA, __IPHONE_NA); /*! @@ -693,8 +700,6 @@ CF_ASSUME_NONNULL_END #endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ -#if defined(__cplusplus) -} -#endif +__END_DECLS #endif /* !_SECURITY_SECTRUST_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp b/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp new file mode 100644 index 00000000..55c09939 --- /dev/null +++ b/OSX/libsecurity_keychain/lib/SecTrustOSXEntryPoints.cpp @@ -0,0 +1,290 @@ +/* + * 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@ + */ + +/* + * SecTrustOSXEntryPoints - Interface for unified SecTrust into OS X Security + * Framework. + */ + +#include "SecTrustOSXEntryPoints.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* + * MARK: CFRunloop + */ + +static OSStatus SecLegacySourceChanged(__unused SecKeychainEvent keychainEvent, __unused SecKeychainCallbackInfo *info, __unused void *context) { + // Purge keychain parent cache + SecItemParentCachePurge(); + // Purge unrestricted roots cache + SecTrustSettingsPurgeUserAdminCertsCache(); + return 0; +} + +static void *SecTrustOSXCFRunloop(__unused void *unused) { + CFRunLoopTimerRef timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, (CFTimeInterval) UINT_MAX, 0, 0, 0, ^(__unused CFRunLoopTimerRef _timer) { + /* do nothing */ + }); + + /* add a timer to force the runloop to stay running */ + CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); + /* add keychain callback before we initiate a runloop to avoid it exiting due to no sources */ + + SecKeychainEventMask trustdMask = (kSecAddEventMask | kSecDeleteEventMask | kSecUpdateEventMask | + kSecDefaultChangedEventMask | kSecKeychainListChangedMask | + kSecTrustSettingsChangedEventMask); + SecKeychainAddCallback(SecLegacySourceChanged, trustdMask, NULL); + + try { + CFRunLoopRun(); + } + catch (...) { + /* An exception was rethrown from the runloop. Since we can't reliably + * obtain info about changes to keychains or trust settings anymore, + * just exit and respawn the process when needed. */ + + secerror("Exception occurred in CFRunLoopRun; exiting"); + exit(0); + } + CFRelease(timer); + return NULL; +} + +void SecTrustLegacySourcesEventRunloopCreate(void) { + /* A runloop is currently necessary to receive notifications about changes in the + * legacy keychains and trust settings. */ + static dispatch_once_t once; + + dispatch_once(&once, ^{ + pthread_attr_t attrs; + pthread_t thread; + + pthread_attr_init(&attrs); + pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); + + /* we do this with traditional pthread to avoid impacting our 512 WQ thread limit since this is a parked thread */ + pthread_create(&thread, &attrs, SecTrustOSXCFRunloop, NULL); + }); +} + +/* + * MARK: ocspd CRL Interface + */ +/* lengths of time strings without trailing NULL */ +#define CSSM_TIME_STRLEN 14 /* no trailing 'Z' */ +#define GENERALIZED_TIME_STRLEN 15 + +OSStatus SecTrustLegacyCRLStatus(SecCertificateRef cert, CFArrayRef chain, CFURLRef currCRLDP); +OSStatus SecTrustLegacyCRLFetch(CFURLRef currCRLDP, CFAbsoluteTime verifyTime); + +static OSStatus cssmReturnToOSStatus(CSSM_RETURN crtn) { + OSStatus status = errSecInternalComponent; + + switch (crtn) { + case CSSM_OK: + status = errSecSuccess; + break; + case CSSMERR_TP_CERT_REVOKED: + status = errSecCertificateRevoked; + break; + case CSSMERR_APPLETP_NETWORK_FAILURE: + status = errSecNetworkFailure; + break; + case CSSMERR_APPLETP_CRL_NOT_FOUND: + status = errSecCRLNotFound; + break; + default: + status = errSecInternalComponent; + } + return status; +} + +#define PEM_STRING_X509 "CERTIFICATE" +static CFDataRef serializedPathToPemSequences(CFArrayRef certs) { + CFMutableDataRef result = NULL; + CFIndex certIX, certCount; + require_quiet(certs, out); + certCount = CFArrayGetCount(certs); + require_quiet(certCount > 0, out); + require_quiet(result = CFDataCreateMutable(NULL, 0), out); + for (certIX = 0; certIX < certCount; certIX++) { + CFDataRef certData = (CFDataRef)CFArrayGetValueAtIndex(certs, certIX); + require_noerr_quiet(impExpPemEncodeExportRep(certData, PEM_STRING_X509, + NULL, result), out); + } +out: + return result; +} + +OSStatus SecTrustLegacyCRLStatus(SecCertificateRef cert, CFArrayRef chain, CFURLRef currCRLDP) { + OSStatus result = errSecParam; + CSSM_RETURN crtn = CSSMERR_TP_INTERNAL_ERROR; + CFDataRef serialData = NULL, pemIssuers = NULL, crlDP = NULL; + CFMutableArrayRef issuersArray = NULL; + + if (!cert || !chain) { + return result; + } + + /* serialNumber is a CSSM_DATA with the value from the TBS Certificate. */ + CSSM_DATA serialNumber = { 0, NULL }; + serialData = SecCertificateCopySerialNumber(cert, NULL); + if (serialData) { + serialNumber.Data = (uint8_t *)CFDataGetBytePtr(serialData); + serialNumber.Length = CFDataGetLength(serialData); + } + + /* issuers is CSSM_DATA containing pem sequence of all issuers in the chain */ + CSSM_DATA issuers = { 0, NULL }; + issuersArray = CFArrayCreateMutableCopy(NULL, 0, chain); + if (issuersArray) { + CFArrayRemoveValueAtIndex(issuersArray, 0); + pemIssuers = serializedPathToPemSequences(issuersArray); + } + if (pemIssuers) { + issuers.Data = (uint8_t *)CFDataGetBytePtr(pemIssuers); + issuers.Length = CFDataGetLength(pemIssuers); + } + + /* crlUrl is CSSM_DATA with the CRLDP url*/ + CSSM_DATA crlUrl = { 0, NULL }; + crlDP = CFURLCreateData(NULL, currCRLDP, kCFStringEncodingASCII, true); + if (crlDP) { + crlUrl.Data = (uint8_t *)CFDataGetBytePtr(crlDP); + crlUrl.Length = CFDataGetLength(crlDP); + } + + if (serialNumber.Data && issuers.Data && crlUrl.Data) { + crtn = ocspdCRLStatus(serialNumber, issuers, NULL, &crlUrl); + } + + result = cssmReturnToOSStatus(crtn); + + if (serialData) { CFRelease(serialData); } + if (issuersArray) { CFRelease(issuersArray); } + if (pemIssuers) { CFRelease(pemIssuers); } + if (crlDP) { CFRelease(crlDP); } + return result; +} + +static CSSM_RETURN ocspdCRLFetchToCache(const CSSM_DATA &crlURL, + CSSM_TIMESTRING verifyTime) { + Allocator &alloc(Allocator::standard(Allocator::normal)); + CSSM_DATA crlData = { 0, NULL }; + CSSM_RETURN crtn; + + crtn = ocspdCRLFetch(alloc, crlURL, NULL, true, true, verifyTime, crlData); + if (crlData.Data) { alloc.free(crlData.Data); } + return crtn; +} + +static OSStatus fetchCRL(CFURLRef currCRLDP, CFAbsoluteTime verifyTime) { + OSStatus result = errSecParam; + CSSM_RETURN crtn = CSSMERR_TP_INTERNAL_ERROR; + CFDataRef crlDP = NULL; + char *cssmTime = NULL, *genTime = NULL; + + if (!currCRLDP) { + return result; + } + + /* crlUrl is CSSM_DATA with the CRLDP url*/ + CSSM_DATA crlUrl = { 0, NULL }; + crlDP = CFURLCreateData(NULL, currCRLDP, kCFStringEncodingASCII, true); + if (crlDP) { + crlUrl.Data = (uint8_t *)CFDataGetBytePtr(crlDP); + crlUrl.Length = CFDataGetLength(crlDP); + } + + /* determine verification time */ + cssmTime = (char *)malloc(CSSM_TIME_STRLEN + 1); + genTime = (char *)malloc(GENERAL_TIME_STRLEN + 1); + if (cssmTime && genTime) { + if (verifyTime != 0.0) { + cfAbsTimeToGgenTime(verifyTime, genTime); + } else { + cfAbsTimeToGgenTime(CFAbsoluteTimeGetCurrent(), genTime); + } + memmove(cssmTime, genTime, GENERAL_TIME_STRLEN - 1); // don't copy the Z + cssmTime[CSSM_TIME_STRLEN] = '\0'; + } + + if (crlUrl.Data && cssmTime) { + crtn = ocspdCRLFetchToCache(crlUrl, (CSSM_TIMESTRING)cssmTime); + } + + result = cssmReturnToOSStatus(crtn); + + if (crlDP) { CFRelease(crlDP); } + if (cssmTime) { free(cssmTime); } + if (genTime) { free(genTime); } + return result; +} + +/* + * MARK: async_ocspd methods + */ +static void async_ocspd_complete(async_ocspd_t *ocspd) { + if (ocspd->completed) { + ocspd->completed(ocspd); + } +} + +/* Return true, iff we didn't schedule any work, return false if we did. */ +bool SecTrustLegacyCRLFetch(async_ocspd_t *ocspd, + CFURLRef currCRLDP, CFAbsoluteTime verifyTime, + SecCertificateRef cert, CFArrayRef chain) { + dispatch_async(ocspd->queue, ^ { + OSStatus status = fetchCRL(currCRLDP, verifyTime); + switch (status) { + case errSecSuccess: + ocspd->response= SecTrustLegacyCRLStatus(cert, chain, currCRLDP); + break; + default: + ocspd->response = status; + break; + } + async_ocspd_complete(ocspd); + if (chain) { CFRelease(chain); } + }); + + return false; /* false -> something was scheduled. */ +} diff --git a/OSX/libsecurity_keychain/lib/SecTrustPriv.h b/OSX/libsecurity_keychain/lib/SecTrustPriv.h index 0a2b017b..437d847c 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustPriv.h +++ b/OSX/libsecurity_keychain/lib/SecTrustPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2012,2014-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2003-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -23,30 +23,317 @@ /*! @header SecTrustPriv - Private part of SecTrust.h -*/ + The functions and data types in SecTrustPriv implement trust computation + and allow the user to apply trust decisions to the trust configuration. + */ -#ifndef _SECURITY_SECTRUST_PRIV_H_ -#define _SECURITY_SECTRUST_PRIV_H_ +#ifndef _SECURITY_SECTRUSTPRIV_H_ +#define _SECURITY_SECTRUSTPRIV_H_ #include #include +#include #include +__BEGIN_DECLS + +CF_ASSUME_NONNULL_BEGIN +CF_IMPLICIT_BRIDGING_ENABLED + +/* Constants used as keys in property lists. See + SecTrustCopySummaryPropertiesAtIndex for more information. */ +extern const CFStringRef kSecPropertyKeyType; +extern const CFStringRef kSecPropertyKeyLabel; +extern const CFStringRef kSecPropertyKeyLocalizedLabel; +extern const CFStringRef kSecPropertyKeyValue; + +extern const CFStringRef kSecPropertyTypeWarning; +extern const CFStringRef kSecPropertyTypeSuccess; +extern const CFStringRef kSecPropertyTypeSection; +extern const CFStringRef kSecPropertyTypeData; +extern const CFStringRef kSecPropertyTypeString; +extern const CFStringRef kSecPropertyTypeURL; +extern const CFStringRef kSecPropertyTypeDate; + +/* Constants used as keys in the dictionary returned by SecTrustCopyInfo. */ +extern const CFStringRef kSecTrustInfoExtendedValidationKey; +extern const CFStringRef kSecTrustInfoCompanyNameKey; +extern const CFStringRef kSecTrustInfoRevocationKey; +extern const CFStringRef kSecTrustInfoRevocationValidUntilKey; +extern const CFStringRef kSecTrustInfoCertificateTransparencyKey; +extern const CFStringRef kSecTrustInfoCertificateTransparencyWhiteListKey; -#if defined(__cplusplus) -extern "C" { -#endif +/*! + @enum Trust Result Constants + @discussion Predefined key constants used to obtain values in a + dictionary of trust evaluation results for a certificate chain, + as retrieved from a call to SecTrustCopyResult. + + @constant kSecTrustResultDetails + This key will be present if a trust evaluation has been performed. + Its value is a CFArrayRef of CFDictionaryRef representing detailed + status info for each certificate in the completed chain. + @constant kSecTrustRevocationReason + This key will be present iff this chain had its revocation checked, + and a "revoked" response was received. The value of this key will + be a CFNumberRef indicating the reason for revocation. The possible + reason code values are described in RFC 5280, section 5.3.1. + */ +extern const CFStringRef kSecTrustResultDetails; +/*__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_9_0);*/ +extern const CFStringRef kSecTrustRevocationReason; +/*__OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0);*/ + +/*! + @function SecTrustCopySummaryPropertiesAtIndex + @abstract Return a property array for the certificate. + @param trust A reference to the trust object to evaluate. + @param ix The index of the requested certificate. Indices run from 0 + (leaf) to the anchor (or last certificate found if no anchor was found). + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. This function returns a + short summary description of the certificate in question. The property + at index 0 of the array might also include general information about the + entire chain's validity in the context of this trust evaluation. + + @discussion Returns a property array for this trust certificate. A property + array is an array of CFDictionaryRefs. Each dictionary (we call it a + property for short) has the following keys: + + kSecPropertyKeyType This key's value determines how this property + should be displayed. Its associated value is one of the + following: + kSecPropertyTypeWarning + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in yellow with a warning triangle. + kSecPropertyTypeError + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in red with an error X. + kSecPropertyTypeSuccess + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in green with a checkmark in front of it. + kSecPropertyTypeTitle + The kSecPropertyKeyLocalizedLabel and kSecPropertyKeyLabel keys are not + set. The kSecPropertyKeyValue is a CFStringRef which should + be displayed in a larger bold font. + kSecPropertyTypeSection + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef with the name + of the next section to display. The value of the + kSecPropertyKeyValue key is a CFArrayRef which is a property + array as defined here. + kSecPropertyTypeData + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFDataRef. Its contents should be + displayed as: "bytes length_of_data : hexdump_of_data". Ideally + the UI will only show one line of hex dump data and have a + disclosure arrow to see the remainder. + kSecPropertyTypeString + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFStringRef. It's contents should be + displayed in the normal font. + kSecPropertyTypeURL + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFURLRef. It's contents should be + displayed as a hyperlink. + kSecPropertyTypeDate + The optional kSecPropertyKeyLocalizedLabel is a CFStringRef containing + the localized label for the value for the kSecPropertyKeyValue. + The type of this value is a CFDateRef. It's contents should be + displayed in human readable form (probably in the current + timezone). + kSecPropertyKeyLocalizedLabel + Human readable localized label for a given property. + kSecPropertyKeyValue + See description of kSecPropertyKeyType to determine what the value + for this key is. + kSecPropertyKeyLabel + Non localized key (label) for this value. This is only + present for properties with fixed label names. + @param certificate A reference to the certificate to evaluate. + @result A property array. It is the caller's responsability to CFRelease + the returned array when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +CFArrayRef SecTrustCopySummaryPropertiesAtIndex(SecTrustRef trust, CFIndex ix); + +/*! + @function SecTrustCopyDetailedPropertiesAtIndex + @abstract Return a property array for the certificate. + @param trust A reference to the trust object to evaluate. + @param ix The index of the requested certificate. Indices run from 0 + (leaf) to the anchor (or last certificate found if no anchor was found). + @result A property array. It is the caller's responsibility to CFRelease + the returned array when it is no longer needed. + See SecTrustCopySummaryPropertiesAtIndex on how to intepret this array. + Unlike that function call this function returns a detailed description + of the certificate in question. + */ +__nullable CF_RETURNS_RETAINED +CFArrayRef SecTrustCopyDetailedPropertiesAtIndex(SecTrustRef trust, CFIndex ix); + +/*! + @function SecTrustCopyInfo + @abstract Return a dictionary with additional information about the + evaluated certificate chain for use by clients. + @param trust A reference to an evaluated trust object. + @discussion Returns a dictionary for this trust evaluation. This + dictionary may have the following keys: + + kSecTrustInfoExtendedValidationKey this key will be present and have + a value of kCFBooleanTrue if this chain was validated for EV. + kSecTrustInfoCompanyNameKey Company name field of subject of leaf + certificate, this field is meant to be displayed to the user + if the kSecTrustInfoExtendedValidationKey is present. + kSecTrustInfoRevocationKey this key will be present iff this chain + had its revocation checked. The value will be a kCFBooleanTrue + if revocation checking was successful and none of the + certificates in the chain were revoked. + The value will be kCFBooleanFalse if no current revocation status + could be obtained for one or more certificates in the chain due + to connection problems or timeouts etc. This is a hint to a + client to retry revocation checking at a later time. + kSecTrustInfoRevocationValidUntilKey this key will be present iff + kSecTrustInfoRevocationKey has a value of kCFBooleanTrue. + The value will be a CFDateRef representing the earliest date at + which the revocation info for one of the certificates in this chain + might change. + + @result A dictionary with various fields that can be displayed to the user, + or NULL if no additional info is available or the trust has not yet been + validated. The caller is responsible for calling CFRelease on the value + returned when it is no longer needed. + */ +__nullable CF_RETURNS_RETAINED +CFDictionaryRef SecTrustCopyInfo(SecTrustRef trust); + +/* For debugging purposes. */ +__nullable CF_RETURNS_RETAINED +CFArrayRef SecTrustGetDetails(SecTrustRef trust); + +/* For debugging purposes. */ +__nullable CF_RETURNS_RETAINED +CFStringRef SecTrustCopyFailureDescription(SecTrustRef trust); + +OSStatus SecTrustGetOTAPKIAssetVersionNumber(int* versionNumber); + +OSStatus SecTrustOTAPKIGetUpdatedAsset(int* didUpdateAsset); + +/*! + @function SecTrustSignedCertificateTimestampList + @abstract Attach SignedCertificateTimestampList data to a trust object. + @param trust A reference to a trust object. + @param sctArray is a CFArray of CFData objects each containing a SCT (per RFC 6962). + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion Allows the caller to provide SCT data (which may be + obtained during a TLS/SSL handshake, per RFC 6962) as input to a trust + evaluation. + */ +OSStatus SecTrustSetSignedCertificateTimestamps(SecTrustRef trust, CFArrayRef sctArray); + +/*! + @function SecTrustSetTrustedLogs + @abstract Sets the trusted CT logs for a given trust. + @param trust A reference to a trust object. + @param trustedLogs An array of trusted logs. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion trustedLog is a CFArray of CFData containing the DER-encode SubjectPublicKeyInfo + of the trusted CT logs. + */ +OSStatus SecTrustSetTrustedLogs(SecTrustRef trust, CFArrayRef trustedLogs); + +/* Keychain searches are allowed by default. Use this to turn off seaching of + -keychain search list (i.e. login.keychain, system.keychain) + -Local Items/iCloud Keychain + -user- and admin-trusted roots + -network-fetched issuers + User must provide all necessary certificates in the input certificates and/or anchors. */ +OSStatus SecTrustSetKeychainsAllowed(SecTrustRef trust, Boolean allowed) + __OSX_AVAILABLE(__MAC_10_12) __IOS_AVAILABLE(__IPHONE_10_0) __TVOS_AVAILABLE(__TVOS_10_0) __WATCHOS_AVAILABLE(__WATCHOS_3_0); + +/* Get the keychain search policy for the trust object. */ +OSStatus SecTrustGetKeychainsAllowed(SecTrustRef trust, Boolean * __nonnull allowed) + __OSX_AVAILABLE(__MAC_10_12) __IOS_AVAILABLE(__IPHONE_10_0) __TVOS_AVAILABLE(__TVOS_10_0) __WATCHOS_AVAILABLE(__WATCHOS_3_0); + +/*! + @function SecTrustEvaluateLeafOnly + @abstract Evaluates the leaf of the trust reference synchronously. + @param trust A reference to the trust object to evaluate. + @param result A pointer to a result type. + @result A result code. See "Security Error Codes" (SecBase.h). + @discussion This function will only evaluate the trust of the leaf certificate. + No chain will be built and only those aspects of the SecPolicyRef that address + the expected contents of the leaf will be checked. This function does not honor + any set exceptions or usage constraints. + */ +OSStatus SecTrustEvaluateLeafOnly(SecTrustRef trust, SecTrustResultType * __nonnull result) + __OSX_AVAILABLE(__MAC_10_12) __IOS_AVAILABLE(__IPHONE_10_0) __TVOS_AVAILABLE(__TVOS_10_0) __WATCHOS_AVAILABLE(__WATCHOS_3_0); + +/*! + @function SecTrustSerialize + @abstract Creates a serialized version of the trust object + @param trust A reference to the trust object to serialize. + @param error A pointer to an error. + @result The serialized trust object. + @discussion This function is intended to be used to share SecTrustRefs between + processes. Saving the results to disk or sending them over network channels + may cause unexpected behavior. + */ +__nullable CF_RETURNS_RETAINED +CFDataRef SecTrustSerialize(SecTrustRef trust, CFErrorRef *error) + __OSX_AVAILABLE(__MAC_10_12) __IOS_AVAILABLE(__IPHONE_10_0) __TVOS_AVAILABLE(__TVOS_10_0) __WATCHOS_AVAILABLE(__WATCHOS_3_0); + +/*! + @function SecTrustDeserialize + @abstract Creates a trust object from the serialized data + @param serialiedTrust A reference to the serialized trust object + @param error A pointer to an error. + @result A trust object + @discussion This function is intended to be used to share SecTrustRefs between + processes. Saving the results to disk or sending them over network channels + may cause unexpected behavior. + */ +__nullable CF_RETURNS_RETAINED +SecTrustRef SecTrustDeserialize(CFDataRef serializedTrust, CFErrorRef *error) + __OSX_AVAILABLE(__MAC_10_12) __IOS_AVAILABLE(__IPHONE_10_0) __TVOS_AVAILABLE(__TVOS_10_0) __WATCHOS_AVAILABLE(__WATCHOS_3_0); + +/*! + @function SecTrustGetTrustExceptionsArray + @abstract Return the exceptions array current set in the trust object + @param trust A reference to the trust object + @result The array of exceptions. + @discussion This function returns an array of exceptions that was previously set + using SecTrustSetExceptions, unlike SecTrustCopyExceptions which returns the + exceptions which could be set using SecTrustSetExceptions. + */ +__nullable CFArrayRef SecTrustGetTrustExceptionsArray(SecTrustRef trust) + __OSX_AVAILABLE(__MAC_10_12) __IOS_AVAILABLE(__IPHONE_10_0) __TVOS_AVAILABLE(__TVOS_10_0) __WATCHOS_AVAILABLE(__WATCHOS_3_0); + +CF_IMPLICIT_BRIDGING_DISABLED +CF_ASSUME_NONNULL_END + +/* + * Legacy functions (OS X only) + */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE + +CF_ASSUME_NONNULL_BEGIN +CF_IMPLICIT_BRIDGING_ENABLED /* unique keychain item attributes for user trust records. -*/ + */ enum { kSecTrustCertAttr = 'tcrt', kSecTrustPolicyAttr = 'tpol', - /* Leopard and later */ - kSecTrustPubKeyAttr = 'tpbk', - kSecTrustSignatureAttr = 'tsig' + /* Leopard and later */ + kSecTrustPubKeyAttr = 'tpbk', + kSecTrustSignatureAttr = 'tsig' }; /*! @@ -57,9 +344,9 @@ enum { @param trustSetting On return, a pointer to the user specified trust settings. @result A result code. See "Security Error Codes" (SecBase.h). @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. -*/ -OSStatus SecTrustGetUserTrust(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting *trustSetting) - /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; + */ +OSStatus SecTrustGetUserTrust(SecCertificateRef __nullable certificate, SecPolicyRef __nullable policy, SecTrustUserSetting * __nullable trustSetting) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_5, __IPHONE_NA, __IPHONE_NA); /*! @function SecTrustSetUserTrust @@ -70,10 +357,10 @@ OSStatus SecTrustGetUserTrust(SecCertificateRef certificate, SecPolicyRef policy @result A result code. See "Security Error Codes" (SecBase.h). @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. @discussion as of Mac OS version 10.5, this will result in a call to - SecTrustSettingsSetTrustSettings(). -*/ -OSStatus SecTrustSetUserTrust(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting trustSetting) - /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; + SecTrustSettingsSetTrustSettings(). + */ +OSStatus SecTrustSetUserTrust(SecCertificateRef __nullable certificate, SecPolicyRef __nullable policy, SecTrustUserSetting trustSetting) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_5, __IPHONE_NA, __IPHONE_NA); /*! @function SecTrustSetUserTrustLegacy @@ -84,10 +371,11 @@ OSStatus SecTrustSetUserTrust(SecCertificateRef certificate, SecPolicyRef policy @result A result code. See "Security Error Codes" (SecBase.h). @This is the private version of what used to be SecTrustSetUserTrust(); it operates - on UserTrust entries as that function used to. The current SecTrustSetUserTrust() - function operated on Trust Settings. -*/ -OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate, SecPolicyRef policy, SecTrustUserSetting trustSetting); + on UserTrust entries as that function used to. The current SecTrustSetUserTrust() + function operated on Trust Settings. + */ +OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef __nullable certificate, SecPolicyRef __nullable policy, SecTrustUserSetting trustSetting) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_12, __IPHONE_NA, __IPHONE_NA); /*! @function SecTrustGetCSSMAnchorCertificates @@ -96,9 +384,9 @@ OSStatus SecTrustSetUserTrustLegacy(SecCertificateRef certificate, SecPolicyRef @param cssmAnchorCount A pointer to the number of certificates in anchors. @result A result code. See "Security Error Codes" (SecBase.h). @availability Mac OS X version 10.4. Deprecated in Mac OS X version 10.5. -*/ -OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors, uint32 *cssmAnchorCount) - /*DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER*/; + */ +OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA * __nullable * __nullable cssmAnchors, uint32 *cssmAnchorCount) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_5, __IPHONE_NA, __IPHONE_NA); /*! @function SecTrustCopyExtendedResult @@ -114,31 +402,9 @@ OSStatus SecTrustGetCSSMAnchorCertificates(const CSSM_DATA **cssmAnchors, uint32 Note: this function will be deprecated in a future release of OS X. Your code should use SecTrustCopyResult to obtain the trust results dictionary. -*/ -OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef *result) - __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA); - - -/*! - @enum Trust Result Constants - @discussion Predefined key constants used to obtain values in a - dictionary of trust evaluation results for a certificate chain, - as retrieved from a call to SecTrustCopyResult. - - @constant kSecTrustResultDetails - This key will be present if a trust evaluation has been performed. - Its value is a CFArrayRef of CFDictionaryRef representing detailed - status info for each certificate in the completed chain. - @constant kSecTrustRevocationReason - This key will be present iff this chain had its revocation checked, - and a "revoked" response was received. The value of this key will - be a CFNumberRef indicating the reason for revocation. The possible - reason code values are described in RFC 5280, section 5.3.1. */ -extern const CFStringRef kSecTrustResultDetails; - /*__OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_NA);*/ -extern const CFStringRef kSecTrustRevocationReason; - /*__OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0);*/ +OSStatus SecTrustCopyExtendedResult(SecTrustRef trust, CFDictionaryRef * __nonnull CF_RETURNS_RETAINED result) + __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5, __MAC_10_12, __IPHONE_NA, __IPHONE_NA); /* * Preference-related strings for Revocation policies. @@ -148,34 +414,37 @@ extern const CFStringRef kSecTrustRevocationReason; * Preference domain, i.e., the name of a plist in ~/Library/Preferences or in * /Library/Preferences */ -#define kSecRevocationDomain "com.apple.security.revocation" +#define kSecRevocationDomain "com.apple.security.revocation" /* OCSP and CRL style keys, followed by values used for both of them */ -#define kSecRevocationOcspStyle CFSTR("OCSPStyle") -#define kSecRevocationCrlStyle CFSTR("CRLStyle") - #define kSecRevocationOff CFSTR("None") - #define kSecRevocationBestAttempt CFSTR("BestAttempt") - #define kSecRevocationRequireIfPresent CFSTR("RequireIfPresent") - #define kSecRevocationRequireForAll CFSTR("RequireForAll") +#define kSecRevocationOcspStyle CFSTR("OCSPStyle") +#define kSecRevocationCrlStyle CFSTR("CRLStyle") +#define kSecRevocationOff CFSTR("None") +#define kSecRevocationBestAttempt CFSTR("BestAttempt") +#define kSecRevocationRequireIfPresent CFSTR("RequireIfPresent") +#define kSecRevocationRequireForAll CFSTR("RequireForAll") /* Which first if both enabled? */ -#define kSecRevocationWhichFirst CFSTR("RevocationFirst") - #define kSecRevocationOcspFirst CFSTR("OCSP") - #define kSecRevocationCrlFirst CFSTR("CRL") +#define kSecRevocationWhichFirst CFSTR("RevocationFirst") +#define kSecRevocationOcspFirst CFSTR("OCSP") +#define kSecRevocationCrlFirst CFSTR("CRL") /* boolean: A "this policy is sufficient per cert" for each */ -#define kSecRevocationOCSPSufficientPerCert CFSTR("OCSPSufficientPerCert") -#define kSecRevocationCRLSufficientPerCert CFSTR("CRLSufficientPerCert") +#define kSecRevocationOCSPSufficientPerCert CFSTR("OCSPSufficientPerCert") +#define kSecRevocationCRLSufficientPerCert CFSTR("CRLSufficientPerCert") /* local OCSP responder URI, value arbitrary string value */ -#define kSecOCSPLocalResponder CFSTR("OCSPLocalResponder") +#define kSecOCSPLocalResponder CFSTR("OCSPLocalResponder") /* Extended trust result keys (now in public API) */ -#define kSecEVOrganizationName kSecTrustOrganizationName -#define kSecTrustExpirationDate kSecTrustRevocationValidUntilDate +#define kSecEVOrganizationName kSecTrustOrganizationName +#define kSecTrustExpirationDate kSecTrustRevocationValidUntilDate + +CF_IMPLICIT_BRIDGING_DISABLED +CF_ASSUME_NONNULL_END + +#endif /* TARGET_OS_MAC && !TARGET_OS_IPHONE */ -#if defined(__cplusplus) -} -#endif +__END_DECLS -#endif /* !_SECURITY_SECTRUST_PRIV_H_ */ +#endif /* !_SECURITY_SECTRUSTPRIV_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp b/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp index 5e292c98..aa0c5ab1 100644 --- a/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp +++ b/OSX/libsecurity_keychain/lib/SecTrustSettings.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005,2011-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2005,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -54,9 +54,8 @@ #include #include #include -#include /* for _CSCheckFix */ -#define trustSettingsDbg(args...) secdebug("trustSettings", ## args) +#define trustSettingsDbg(args...) secinfo("trustSettings", ## args) /* * Ideally we'd like to implement our own lock to protect the state of the cert stores @@ -390,9 +389,9 @@ static OSStatus tsCopyCertsCommon( &kCFTypeArrayCallBacks)); /* - * Search all keychains - user's, System.keychain, system root store, - * system intermdiates as appropriate - */ + * Search all keychains - user's keychain list, System.keychain, + * and system root store + */ StorageManager::KeychainList keychains; Keychain adminKc; if(user) { @@ -404,8 +403,6 @@ static OSStatus tsCopyCertsCommon( } Keychain sysRootKc = globals().storageManager.make(SYSTEM_ROOT_STORE_PATH, false); keychains.push_back(sysRootKc); - Keychain sysCertKc = globals().storageManager.make(SYSTEM_CERT_STORE_PATH, false); - keychains.push_back(sysCertKc); assert(kSecTrustSettingsDomainUser == 0); for(unsigned domain=0; domain #include #include -//#include -//#include #include #include -//#include #include #include #include @@ -53,6 +50,8 @@ #include "TrustSettingsSchema.h" #include #include +#include +#include "TokenLogin.h" //%%% add this to AuthorizationTagsPriv.h later #ifndef AGENT_HINT_LOGIN_KC_SUPPRESS_RESET_PANEL @@ -76,7 +75,7 @@ static SecPreferencesDomain defaultPreferenceDomain() { SessionAttributeBits sessionAttrs; if (gServerMode) { - secdebug("servermode", "StorageManager initialized in server mode"); + secnotice("servermode", "StorageManager initialized in server mode"); sessionAttrs = sessionIsRoot; } else { MacOSError::check(SessionGetInfo(callerSecuritySession, NULL, &sessionAttrs)); @@ -87,7 +86,7 @@ static SecPreferencesDomain defaultPreferenceDomain() // that has graphics access. Ignore that to help testing.) if ((sessionAttrs & sessionIsRoot) IFDEBUG( && !(sessionAttrs & sessionHasGraphicAccess))) { - secdebug("storagemgr", "using system preferences"); + secnotice("storagemgr", "using system preferences"); return kSecPreferencesDomainSystem; } @@ -154,28 +153,39 @@ StorageManager::keychain(const DLDbIdentifier &dLDbIdentifier) if (!dLDbIdentifier) return Keychain(); - KeychainMap::iterator it = mKeychains.find(dLDbIdentifier); - if (it != mKeychains.end()) + DLDbIdentifier dldbi = mungeDLDbIdentifier(dLDbIdentifier, false); + + KeychainMap::iterator it = mKeychainMap.find(dldbi); + if (it != mKeychainMap.end()) { return it->second; } + // If we have a keychain object for the un/demunged keychain, return that. + // We might be in the middle of an upgrade... + DLDbIdentifier demunge_dldbi = demungeDLDbIdentifier(dLDbIdentifier); + it = mKeychainMap.find(demunge_dldbi); + if (it != mKeychainMap.end()) { + secnotice("integrity", "returning unmunged keychain ref"); + return it->second; + } + if (gServerMode) { - secdebug("servermode", "keychain reference in server mode"); + secnotice("servermode", "keychain reference in server mode"); return Keychain(); } // The keychain is not in our cache. Create it. - Db db(makeDb(dLDbIdentifier)); + Db db(makeDb(dldbi)); Keychain keychain(db); // Add the keychain to the cache. - mKeychains.insert(KeychainMap::value_type(dLDbIdentifier, &*keychain)); - keychain->inCache(true); + registerKeychain(keychain); return keychain; } +// Note: this must be a munged DLDbidentifier. CssmClient::Db StorageManager::makeDb(DLDbIdentifier dLDbIdentifier) { Module module(dLDbIdentifier.ssuid().guid()); @@ -194,38 +204,131 @@ StorageManager::makeDb(DLDbIdentifier dLDbIdentifier) { return db; } +// StorageManager is responsible for silently switching to newer-style keychains. +// If the keychain requested is in ~/Library/Keychains/, and there is a +// newer keychain available (with extension ".keychain-db"), open that one +// instead of the one requested. +// +// Because of backwards compatibility reasons, we can't update the plist +// files on disk to point to the upgraded keychains. We will be asked to +// load "/Users/account/Library/Keychains/login.keychain", hence this +// modification to 'login.keychain-db'. +DLDbIdentifier +StorageManager::mungeDLDbIdentifier(const DLDbIdentifier& dLDbIdentifier, bool isReset) { + if(!dLDbIdentifier.dbName()) { + // If this DLDbIdentifier doesn't have a filename, don't munge it + return dLDbIdentifier; + } + + string path = dLDbIdentifier.dbName(); + + bool shouldCreateProtected = globals().integrityProtection(); + + // If we don't have a DLDbIdentifier, we can't return one + if(dLDbIdentifier.mImpl == NULL) { + return DLDbIdentifier(); + } + + // Ensure we're in ~/Library/Keychains + if(pathInHomeLibraryKeychains(path)) { + string pathdb = makeKeychainDbFilename(path); + + struct stat st; + int stat_result; + stat_result = ::stat(path.c_str(), &st); + bool path_exists = (stat_result == 0); + + stat_result = ::stat(pathdb.c_str(), &st); + bool pathdb_exists = (stat_result == 0); + + // If protections are off, don't change the requested filename. + // If protictions are on and the -db file exists, always use it. + // + // If we're resetting, and we're creating a new-style keychain, use the -db path. + // If we're resetting, and we're creating an old-style keychain, use the original path. + // + // Protection pathdb_exists path_exists resetting Result + // DISABLED X X X original + // ENABLED 1 X X -db + // ENABLED 0 0 X -db + // ENABLED 0 1 0 original + // ENABLED 0 1 1 -db + // + bool switchPaths = shouldCreateProtected && (pathdb_exists || (!pathdb_exists && !path_exists) || isReset); + + if(switchPaths) { + secnotice("integrity", "switching to keychain-db: %s from %s (%d %d %d %d)", pathdb.c_str(), path.c_str(), isReset, shouldCreateProtected, path_exists, pathdb_exists); + path = pathdb; + } else { + secnotice("integrity", "not switching: %s from %s (%d %d %d %d)", pathdb.c_str(), path.c_str(), isReset, shouldCreateProtected, path_exists, pathdb_exists); + } + } else { + secnotice("integrity", "not switching as we're not in ~/Library/Keychains/: %s (%d)", path.c_str(), isReset); + } + + DLDbIdentifier id(dLDbIdentifier.ssuid(), path.c_str(), dLDbIdentifier.dbLocation()); + return id; +} + +DLDbIdentifier +StorageManager::demungeDLDbIdentifier(const DLDbIdentifier& dLDbIdentifier) { + if(dLDbIdentifier.dbName() == NULL) { + return dLDbIdentifier; + } + + string path = dLDbIdentifier.dbName(); + string dbSuffix = "-db"; + bool endsWithKeychainDb = (path.size() > dbSuffix.size() && (0 == path.compare(path.size() - dbSuffix.size(), dbSuffix.size(), dbSuffix))); + + // Ensure we're in ~/Library/Keychains, and that the path ends in "-db" + if(pathInHomeLibraryKeychains(path) && endsWithKeychainDb) { + // remove "-db" from the end. + path.erase(path.end() - 3, path.end()); + } + + DLDbIdentifier id(dLDbIdentifier.ssuid(), path.c_str(), dLDbIdentifier.dbLocation()); + return id; +} + +string +StorageManager::makeKeychainDbFilename(const string& filename) { + string keychainDbSuffix = "-db"; + bool endsWithKeychainDb = (filename.size() > keychainDbSuffix.size() && (0 == filename.compare(filename.size() - keychainDbSuffix.size(), keychainDbSuffix.size(), keychainDbSuffix))); + + if(endsWithKeychainDb) { + return filename; + } else { + return filename + keychainDbSuffix; + } +} + +bool +StorageManager::pathInHomeLibraryKeychains(const string& path) { + return SecurityServer::CommonBlob::pathInHomeLibraryKeychains(path); +} + void StorageManager::reloadKeychain(Keychain keychain) { StLock_(mKeychainMapMutex); DLDbIdentifier dLDbIdentifier = keychain->database()->dlDbIdentifier(); - // Since we're going to reload this database and switch over the keychain's - // mDb, grab its mDb mutex - { - StLock__(keychain->mDbMutex); - - CssmClient::Db db(makeDb(dLDbIdentifier)); - keychain->mDb = db; - } + keychain->changeDatabase(makeDb(mungeDLDbIdentifier(dLDbIdentifier, false))); - // Since this new database is based on the exact same dLDbIdentifier, we - // don't need to update the mKeychains map. + // This keychain might have a different dldbidentifier now, depending on what + // other processes have been doing to the keychain files. Let's re-register it, just + // to be sure. + registerKeychain(keychain); } void StorageManager::removeKeychain(const DLDbIdentifier &dLDbIdentifier, KeychainImpl *keychainImpl) { - // Lock the recursive mutex - - StLock_(mKeychainMapMutex); - - KeychainMap::iterator it = mKeychains.find(dLDbIdentifier); - if (it != mKeychains.end() && (KeychainImpl*) it->second == keychainImpl) - mKeychains.erase(it); + StLock_(mKeychainMapMutex); - keychainImpl->inCache(false); + // Don't trust this dldbidentifier. Just look for the keychain and delete it. + forceRemoveFromCache(keychainImpl); } void @@ -235,20 +338,87 @@ StorageManager::didRemoveKeychain(const DLDbIdentifier &dLDbIdentifier) StLock_(mKeychainMapMutex); - KeychainMap::iterator it = mKeychains.find(dLDbIdentifier); - if (it != mKeychains.end()) + KeychainMap::iterator it = mKeychainMap.find(dLDbIdentifier); + if (it != mKeychainMap.end()) { - mKeychains.erase(it); + it->second->inCache(false); + mKeychainMap.erase(it); } } +// If the client does not keep references to keychains, they are destroyed on +// every API exit, and recreated on every API entrance. +// +// To improve performance, we'll cache keychains for some short period of time. +// We'll do this by CFRetaining the keychain object, and setting a timer to +// CFRelease it when time's up. This way, the client can still recover all its +// memory if it doesn't want the keychains around, but repeated API calls will +// be significantly faster. +// +void +StorageManager::tickleKeychain(KeychainImpl *keychainImpl) { + static dispatch_once_t onceToken = 0; + static dispatch_queue_t release_queue = NULL; + dispatch_once(&onceToken, ^{ + release_queue = dispatch_queue_create("com.apple.security.keychain-cache-queue", DISPATCH_QUEUE_SERIAL); + }); + + __block KeychainImpl* kcImpl = keychainImpl; + + if(!kcImpl) { + return; + } + + // We really only want to cache CSPDL file-based keychains + if(kcImpl->dlDbIdentifier().ssuid().guid() != gGuidAppleCSPDL) { + return; + } + + // Make a one-shot timer to release the keychain + uint32_t seconds = 1; + + const string path = kcImpl->name(); + bool isSystemKeychain = (0 == path.compare("/Library/Keychains/System.keychain")); + if(pathInHomeLibraryKeychains(path) || isSystemKeychain) { + // These keychains are important and likely aren't on removable media. + // Cache them longer. + seconds = 5; + } + + __block CFTypeRef kcHandle = kcImpl->handle(); // calls retain; this keychain object will stay around until our dispatch block fires. + + dispatch_async(release_queue, ^() { + if(kcImpl->mCacheTimer) { + // Update the cache timer to be seconds from now + dispatch_source_set_timer(kcImpl->mCacheTimer, dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, NSEC_PER_SEC/2); + + // We've added an extra retain to this keychain right before invoking this block. Release it. + CFRelease(kcHandle); + + } else { + // No cache timer; make one. + kcImpl->mCacheTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, release_queue); + dispatch_source_set_timer(kcImpl->mCacheTimer, dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, NSEC_PER_SEC/2); + + dispatch_source_set_event_handler(kcImpl->mCacheTimer, ^{ + dispatch_source_cancel(kcImpl->mCacheTimer); + dispatch_release(kcImpl->mCacheTimer); + kcImpl->mCacheTimer = NULL; + CFRelease(kcHandle); + }); + + dispatch_resume(kcImpl->mCacheTimer); + } + }); +} + // Create keychain if it doesn't exist, and optionally add it to the search list. Keychain -StorageManager::makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add) +StorageManager::makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add, bool isReset) { StLock_(mKeychainMapMutex); - Keychain theKeychain = keychain(dLDbIdentifier); + Keychain theKeychain = keychain(mungeDLDbIdentifier(dLDbIdentifier, isReset)); bool post = false; bool updateList = (add && shouldAddToSearchList(dLDbIdentifier)); @@ -256,12 +426,12 @@ StorageManager::makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add) { mSavedList.revert(false); DLDbList searchList = mSavedList.searchList(); - if (find(searchList.begin(), searchList.end(), dLDbIdentifier) != searchList.end()) + if (find(searchList.begin(), searchList.end(), demungeDLDbIdentifier(dLDbIdentifier)) != searchList.end()) return theKeychain; // theKeychain is already in the searchList. mCommonList.revert(false); searchList = mCommonList.searchList(); - if (find(searchList.begin(), searchList.end(), dLDbIdentifier) != searchList.end()) + if (find(searchList.begin(), searchList.end(), demungeDLDbIdentifier(dLDbIdentifier)) != searchList.end()) return theKeychain; // theKeychain is already in the commonList don't add it to the searchList. // If theKeychain doesn't exist don't bother adding it to the search list yet. @@ -271,7 +441,7 @@ StorageManager::makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add) // theKeychain exists and is not in our search list, so add it to the // search list. mSavedList.revert(true); - mSavedList.add(dLDbIdentifier); + mSavedList.add(demungeDLDbIdentifier(dLDbIdentifier)); mSavedList.save(); post = true; } @@ -303,12 +473,12 @@ StorageManager::created(const Keychain &keychain) // keychain the default. if (!mSavedList.defaultDLDbIdentifier()) { - mSavedList.defaultDLDbIdentifier(dLDbIdentifier); + mSavedList.defaultDLDbIdentifier(demungeDLDbIdentifier(dLDbIdentifier)); defaultChanged = true; } // Add the keychain to the search list prefs. - mSavedList.add(dLDbIdentifier); + mSavedList.add(demungeDLDbIdentifier(dLDbIdentifier)); mSavedList.save(); // Make sure we are not holding mLock when we post these events. @@ -390,7 +560,7 @@ StorageManager::defaultKeychain(const Keychain &keychain) { oldDefaultId = mSavedList.defaultDLDbIdentifier(); mSavedList.revert(true); - mSavedList.defaultDLDbIdentifier(newDefaultId); + mSavedList.defaultDLDbIdentifier(demungeDLDbIdentifier(newDefaultId)); mSavedList.save(); } @@ -462,7 +632,7 @@ StorageManager::loginKeychain(Keychain keychain) StLock_(mMutex); mSavedList.revert(true); - mSavedList.loginDLDbIdentifier(keychain->dlDbIdentifier()); + mSavedList.loginDLDbIdentifier(demungeDLDbIdentifier(keychain->dlDbIdentifier())); mSavedList.save(); } @@ -521,59 +691,34 @@ void StorageManager::rename(Keychain keychain, const char* newName) // Find the keychain object for the given ref DLDbIdentifier dLDbIdentifier = keychain->dlDbIdentifier(); - // Actually rename the database on disk. - keychain->database()->rename(newName); + if(!keychain->database()->isLocked()) { + // Bring our unlock state with us + DLDbIdentifier dldbi(dLDbIdentifier.ssuid(), newName, dLDbIdentifier.dbLocation()); + keychain->database()->transferTo(dldbi); + } else { + keychain->database()->rename(newName); + } - if (dLDbIdentifier == defaultId) + if (demungeDLDbIdentifier(dLDbIdentifier) == defaultId) changedDefault=true; newDLDbIdentifier = keychain->dlDbIdentifier(); // Rename the keychain in the search list. - mSavedList.rename(dLDbIdentifier, newDLDbIdentifier); + mSavedList.rename(demungeDLDbIdentifier(dLDbIdentifier), demungeDLDbIdentifier(newDLDbIdentifier)); // If this was the default keychain change it accordingly if (changedDefault) - mSavedList.defaultDLDbIdentifier(newDLDbIdentifier); + mSavedList.defaultDLDbIdentifier(demungeDLDbIdentifier(newDLDbIdentifier)); mSavedList.save(); - // we aren't worried about a weak reference here, because we have to - // hold a lock on an item in order to do the rename - - // Now update the Keychain cache - if (keychain->inCache()) - { - KeychainMap::iterator it = mKeychains.find(dLDbIdentifier); - if (it != mKeychains.end() && (KeychainImpl*) it->second == keychain.get()) - { - // Remove the keychain from the cache under its old - // dLDbIdentifier - mKeychains.erase(it); - } - } - - // If we renamed this keychain on top of an existing one we should - // drop the old one from the cache. - KeychainMap::iterator it = mKeychains.find(newDLDbIdentifier); - if (it != mKeychains.end()) - { - Keychain oldKeychain(it->second); - oldKeychain->inCache(false); - // @@@ Ideally we should invalidate or fault this keychain object. - } - - if (keychain->inCache()) - { - // If the keychain wasn't in the cache to being with let's not put - // it there now. There was probably a good reason it wasn't in it. - // If the keychain was in the cache, update it to use - // newDLDbIdentifier. - mKeychains.insert(KeychainMap::value_type(newDLDbIdentifier, - keychain)); - } - } + // If the keychain wasn't in the cache, don't touch the cache. + // Otherwise, update the cache to use its current identifier. + if(keychain->inCache()) { + registerKeychain(keychain); + } + } - // Make sure we are not holding mLock when we post these events. KCEventNotifier::PostKeychainEvent(kSecKeychainListChangedEvent); if (changedDefault) @@ -581,7 +726,63 @@ void StorageManager::rename(Keychain keychain, const char* newName) newDLDbIdentifier); } -void StorageManager::renameUnique(Keychain keychain, CFStringRef newName) +void StorageManager::registerKeychain(Keychain& kc) { + registerKeychainImpl(kc.get()); +} + +void StorageManager::registerKeychainImpl(KeychainImpl* kcimpl) { + if(!kcimpl) { + return; + } + + { + StLock _(mKeychainMapMutex); + + // First, iterate through the cache to see if this keychain is there. If so, remove it. + forceRemoveFromCache(kcimpl); + + // If we renamed this keychain on top of an existing one, let's drop the old one from the cache. + KeychainMap::iterator it = mKeychainMap.find(kcimpl->dlDbIdentifier()); + if (it != mKeychainMap.end()) + { + Keychain oldKeychain(it->second); + oldKeychain->inCache(false); + // @@@ Ideally we should invalidate or fault this keychain object. + } + + mKeychainMap.insert(KeychainMap::value_type(kcimpl->dlDbIdentifier(), kcimpl)); + kcimpl->inCache(true); + } // drop mKeychainMapMutex +} + +void StorageManager::forceRemoveFromCache(KeychainImpl* inKeychainImpl) { + try { + // Wrap all this in a try-block and ignore all errors - we're trying to clean up these maps + { + StLock _(mKeychainMapMutex); + for(KeychainMap::iterator it = mKeychainMap.begin(); it != mKeychainMap.end(); ) { + if(it->second == inKeychainImpl) { + // Increment the iterator, but use its pre-increment value for the erase + it->second->inCache(false); + mKeychainMap.erase(it++); + } else { + it++; + } + } + } // drop mKeychainMapMutex + } catch(UnixError ue) { + secnotice("storagemgr", "caught UnixError: %d %s", ue.unixError(), ue.what()); + } catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secnotice("storagemgr", "caught CssmError: %d %s", (int) cssme.error, errStr); + } catch (MacOSError mose) { + secnotice("storagemgr", "MacOSError: %d", (int)mose.osStatus()); + } catch(...) { + secnotice("storagemgr", "Unknown error"); + } +} + +void StorageManager::renameUnique(Keychain keychain, CFStringRef newName, bool appendDbSuffix) { StLock_(mMutex); @@ -599,7 +800,11 @@ void StorageManager::renameUnique(Keychain keychain, CFStringRef newName) if ( newNameCFStr ) { CFStringAppendFormat(newNameCFStr, NULL, CFSTR("%s%d"), newNameCString, index); - CFStringAppend(newNameCFStr, CFSTR(kKeychainSuffix)); // add .keychain + if(appendDbSuffix) { + CFStringAppend(newNameCFStr, CFSTR(kKeychainDbSuffix)); + } else { + CFStringAppend(newNameCFStr, CFSTR(kKeychainSuffix)); // add .keychain + } char toUseBuff2[MAXPATHLEN]; if ( CFStringGetCString(newNameCFStr, toUseBuff2, MAXPATHLEN, kCFStringEncodingUTF8) ) // make sure it fits in MAXPATHLEN, etc. { @@ -741,9 +946,10 @@ void StorageManager::remove(const KeychainList &kcsToRemove, bool deleteDb) DLDbIdentifier dLDbIdentifier = theKeychain->dlDbIdentifier(); // Remove it from the saved list - mSavedList.remove(dLDbIdentifier); - if (dLDbIdentifier == defaultId) + mSavedList.remove(demungeDLDbIdentifier(dLDbIdentifier)); + if (demungeDLDbIdentifier(dLDbIdentifier) == defaultId) { unsetDefault=true; + } if (deleteDb) { @@ -755,7 +961,7 @@ void StorageManager::remove(const KeychainList &kcsToRemove, bool deleteDb) } if (unsetDefault) - mSavedList.defaultDLDbIdentifier(DLDbIdentifier()); + mSavedList.defaultDLDbIdentifier(DLDbIdentifier()); mSavedList.save(); } @@ -833,30 +1039,32 @@ StorageManager::setSearchList(const KeychainList &keychainList) { StLock_(mMutex); - DLDbList commonList = mCommonList.searchList(); - - // Strip out the common list part from the end of the search list. - KeychainList::const_iterator it_end = keychainList.end(); - DLDbList::const_reverse_iterator end_common = commonList.rend(); - for (DLDbList::const_reverse_iterator it_common = commonList.rbegin(); it_common != end_common; ++it_common) + DLDbList searchList, oldSearchList(mSavedList.searchList()); + for (KeychainList::const_iterator it = keychainList.begin(); it != keychainList.end(); ++it) { - // Eliminate common entries from the end of the passed in keychainList. - if (it_end == keychainList.begin()) - break; + DLDbIdentifier dldbi = demungeDLDbIdentifier((*it)->dlDbIdentifier()); + + // If this keychain is not in the common or dynamic lists, add it to the new search list + DLDbList commonList = mCommonList.searchList(); + bool found = false; + for(DLDbList::const_iterator jt = commonList.begin(); jt != commonList.end(); ++jt) { + if((*jt) == dldbi) { + found = true; + } + } - --it_end; - if (!((*it_end)->dlDbIdentifier() == *it_common)) - { - ++it_end; - break; - } - } + DLDbList dynamicList = mDynamicList.searchList(); + for(DLDbList::const_iterator jt = dynamicList.begin(); jt != dynamicList.end(); ++jt) { + if((*jt) == dldbi) { + found = true; + } + } - /* it_end now points one past the last element in keychainList which is not in commonList. */ - DLDbList searchList, oldSearchList(mSavedList.searchList()); - for (KeychainList::const_iterator it = keychainList.begin(); it != it_end; ++it) - { - searchList.push_back((*it)->dlDbIdentifier()); + if(found) { + continue; + } + + searchList.push_back(dldbi); } { @@ -952,11 +1160,11 @@ StorageManager::domain(SecPreferencesDomain domain) switch (domain) { case kSecPreferencesDomainSystem: - secdebug("storagemgr", "switching to system domain"); break; + secnotice("storagemgr", "switching to system domain"); break; case kSecPreferencesDomainUser: - secdebug("storagemgr", "switching to user domain (uid %d)", getuid()); break; + secnotice("storagemgr", "switching to user domain (uid %d)", getuid()); break; default: - secdebug("storagemgr", "switching to weird prefs domain %d", domain); break; + secnotice("storagemgr", "switching to weird prefs domain %d", domain); break; } #endif @@ -1023,7 +1231,7 @@ void StorageManager::convertList(DLDbList &ids, const KeychainList &kcs) result.reserve(kcs.size()); for (KeychainList::const_iterator ix = kcs.begin(); ix != kcs.end(); ++ix) { - result.push_back((*ix)->dlDbIdentifier()); + result.push_back(demungeDLDbIdentifier((*ix)->dlDbIdentifier())); } ids.swap(result); } @@ -1043,7 +1251,7 @@ void StorageManager::convertList(KeychainList &kcs, const DLDbList &ids) #pragma mark ____ Login Functions ____ -void StorageManager::login(AuthorizationRef authRef, UInt32 nameLength, const char* name) +void StorageManager::login(AuthorizationRef authRef, UInt32 nameLength, const char* name, bool isReset) { StLock_(mMutex); @@ -1062,7 +1270,7 @@ void StorageManager::login(AuthorizationRef authRef, UInt32 nameLength, const ch // creates the login keychain with the specified password try { - login(nameLength, name, (UInt32)currItem->valueLength, currItem->value); + login(nameLength, name, (UInt32)currItem->valueLength, currItem->value, isReset); created = true; } catch(...) @@ -1087,15 +1295,15 @@ void StorageManager::login(ConstStringPtr name, ConstStringPtr password) if ( name == NULL || password == NULL ) MacOSError::throwMe(errSecParam); - login(name[0], name + 1, password[0], password + 1); + login(name[0], name + 1, password[0], password + 1, false); } void StorageManager::login(UInt32 nameLength, const void *name, - UInt32 passwordLength, const void *password) + UInt32 passwordLength, const void *password, bool isReset) { if (passwordLength != 0 && password == NULL) { - secdebug("KCLogin", "StorageManager::login: invalid argument (NULL password)"); + secnotice("KCLogin", "StorageManager::login: invalid argument (NULL password)"); MacOSError::throwMe(errSecParam); } @@ -1105,7 +1313,7 @@ void StorageManager::login(UInt32 nameLength, const void *name, loginDLDbIdentifier = mSavedList.loginDLDbIdentifier(); } - secdebug("KCLogin", "StorageManager::login: loginDLDbIdentifier is %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); + secnotice("KCLogin", "StorageManager::login: loginDLDbIdentifier is %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); if (!loginDLDbIdentifier) MacOSError::throwMe(errSecNoSuchKeychain); @@ -1118,7 +1326,7 @@ void StorageManager::login(UInt32 nameLength, const void *name, int uid = geteuid(); struct passwd *pw = getpwuid(uid); if (pw == NULL) { - secdebug("KCLogin", "StorageManager::login: invalid argument (NULL uid)"); + secnotice("KCLogin", "StorageManager::login: invalid argument (NULL uid)"); MacOSError::throwMe(errSecParam); } char *userName = pw->pw_name; @@ -1129,12 +1337,14 @@ void StorageManager::login(UInt32 nameLength, const void *name, std::string shortnameDotKeychain = shortnameKeychain + ".keychain"; std::string loginDotKeychain = keychainPath + "login.keychain"; std::string loginRenamed1Keychain = keychainPath + "login_renamed1.keychain"; + std::string loginKeychainDb = keychainPath + "login.keychain-db"; // check for existence of keychain files bool shortnameKeychainExists = false; bool shortnameDotKeychainExists = false; bool loginKeychainExists = false; bool loginRenamed1KeychainExists = false; + bool loginKeychainDbExists = false; { struct stat st; int stat_result; @@ -1146,8 +1356,14 @@ void StorageManager::login(UInt32 nameLength, const void *name, loginKeychainExists = (stat_result == 0); stat_result = ::stat(loginRenamed1Keychain.c_str(), &st); loginRenamed1KeychainExists = (stat_result == 0); + stat_result = ::stat(loginKeychainDb.c_str(), &st); + loginKeychainDbExists = (stat_result == 0); } + // login.keychain-db is considered to be the same as login.keychain. + // Our transparent keychain promotion on open will handle opening the right version of this file. + loginKeychainExists |= loginKeychainDbExists; + bool loginUnlocked = false; // make the keychain identifiers @@ -1210,11 +1426,11 @@ void StorageManager::login(UInt32 nameLength, const void *name, // "shortname.keychain" if it is not. if (loginRenamed1KeychainExists && (!loginKeychainExists || - (mSavedList.searchList().size() == 1 && mSavedList.member(loginDLDbIdentifier)) )) { + (mSavedList.searchList().size() == 1 && mSavedList.member(demungeDLDbIdentifier(loginDLDbIdentifier))) )) { try { Keychain loginRenamed1KC(keychain(loginRenamed1DLDbIdentifier)); - secdebug("KCLogin", "Attempting to unlock %s with %d-character password", + secnotice("KCLogin", "Attempting to unlock %s with %d-character password", (loginRenamed1KC) ? loginRenamed1KC->name() : "", (unsigned int)passwordLength); loginRenamed1KC->unlock(CssmData(const_cast(password), passwordLength)); // if we get here, we unlocked it @@ -1251,11 +1467,12 @@ void StorageManager::login(UInt32 nameLength, const void *name, } // if login.keychain does not exist at this point, create it - if (!loginKeychainExists) { - Keychain theKeychain(keychain(loginDLDbIdentifier)); - secdebug("KCLogin", "Creating login keychain %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); + if (!loginKeychainExists || (isReset && !loginKeychainDbExists)) { + // but don't add it to the search list yet; we'll do that later + Keychain theKeychain = makeKeychain(loginDLDbIdentifier, false, true); + secnotice("KCLogin", "Creating login keychain %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); theKeychain->create(passwordLength, password); - secdebug("KCLogin", "Login keychain created successfully"); + secnotice("KCLogin", "Login keychain created successfully"); loginKeychainExists = true; // Set the prefs for this new login keychain. loginKeychain(theKeychain); @@ -1270,24 +1487,26 @@ void StorageManager::login(UInt32 nameLength, const void *name, //*************************************************************** // if the shortname keychain exists in the search list, either rename or remove the entry - if (mSavedList.member(shortnameDLDbIdentifier)) { - if (shortnameDotKeychainExists && !mSavedList.member(shortnameDotDLDbIdentifier)) { + if (mSavedList.member(demungeDLDbIdentifier(shortnameDLDbIdentifier))) { + if (shortnameDotKeychainExists && !mSavedList.member(demungeDLDbIdentifier(shortnameDotDLDbIdentifier))) { // change shortname to shortname.keychain (login.keychain will be added later if not present) - secdebug("KCLogin", "Renaming %s to %s in keychain search list", + secnotice("KCLogin", "Renaming %s to %s in keychain search list", (shortnameDLDbIdentifier) ? shortnameDLDbIdentifier.dbName() : "", (shortnameDotDLDbIdentifier) ? shortnameDotDLDbIdentifier.dbName() : ""); - mSavedList.rename(shortnameDLDbIdentifier, shortnameDotDLDbIdentifier); - } else if (!mSavedList.member(loginDLDbIdentifier)) { + mSavedList.rename(demungeDLDbIdentifier(shortnameDLDbIdentifier), + demungeDLDbIdentifier(shortnameDotDLDbIdentifier)); + } else if (!mSavedList.member(demungeDLDbIdentifier(loginDLDbIdentifier))) { // change shortname to login.keychain - secdebug("KCLogin", "Renaming %s to %s in keychain search list", + secnotice("KCLogin", "Renaming %s to %s in keychain search list", (shortnameDLDbIdentifier) ? shortnameDLDbIdentifier.dbName() : "", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); - mSavedList.rename(shortnameDLDbIdentifier, loginDLDbIdentifier); + mSavedList.rename(demungeDLDbIdentifier(shortnameDLDbIdentifier), + demungeDLDbIdentifier(loginDLDbIdentifier)); } else { // already have login.keychain in list, and renaming to shortname.keychain isn't an option, // so just remove the entry - secdebug("KCLogin", "Removing %s from keychain search list", (shortnameDLDbIdentifier) ? shortnameDLDbIdentifier.dbName() : ""); - mSavedList.remove(shortnameDLDbIdentifier); + secnotice("KCLogin", "Removing %s from keychain search list", (shortnameDLDbIdentifier) ? shortnameDLDbIdentifier.dbName() : ""); + mSavedList.remove(demungeDLDbIdentifier(shortnameDLDbIdentifier)); } // note: save() will cause the plist to be unlinked if the only remaining entry is for login.keychain @@ -1296,24 +1515,24 @@ void StorageManager::login(UInt32 nameLength, const void *name, } // make sure that login.keychain is in the search list - if (!mSavedList.member(loginDLDbIdentifier)) { - secdebug("KCLogin", "Adding %s to keychain search list", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); - mSavedList.add(loginDLDbIdentifier); + if (!mSavedList.member(demungeDLDbIdentifier(loginDLDbIdentifier))) { + secnotice("KCLogin", "Adding %s to keychain search list", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); + mSavedList.add(demungeDLDbIdentifier(loginDLDbIdentifier)); mSavedList.save(); mSavedList.revert(true); } // if we have a shortname.keychain, always include it in the plist (after login.keychain) - if (shortnameDotKeychainExists && !mSavedList.member(shortnameDotDLDbIdentifier)) { - mSavedList.add(shortnameDotDLDbIdentifier); + if (shortnameDotKeychainExists && !mSavedList.member(demungeDLDbIdentifier(shortnameDotDLDbIdentifier))) { + mSavedList.add(demungeDLDbIdentifier(shortnameDotDLDbIdentifier)); mSavedList.save(); mSavedList.revert(true); } // make sure that the default keychain is in the search list; if not, reset the default to login.keychain if (!mSavedList.member(mSavedList.defaultDLDbIdentifier())) { - secdebug("KCLogin", "Changing default keychain to %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); - mSavedList.defaultDLDbIdentifier(loginDLDbIdentifier); + secnotice("KCLogin", "Changing default keychain to %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); + mSavedList.defaultDLDbIdentifier(demungeDLDbIdentifier(loginDLDbIdentifier)); mSavedList.save(); mSavedList.revert(true); } @@ -1328,8 +1547,8 @@ void StorageManager::login(UInt32 nameLength, const void *name, try { Keychain theKeychain(keychain(loginDLDbIdentifier)); - secdebug("KCLogin", "Attempting to unlock login keychain \"%s\" with %d-character password", - (theKeychain) ? theKeychain->name() : "", (unsigned int)passwordLength); + secnotice("KCLogin", "Attempting to unlock login keychain \"%s\"", + (theKeychain) ? theKeychain->name() : ""); theKeychain->unlock(CssmData(const_cast(password), passwordLength)); loginUnlocked = true; } @@ -1339,55 +1558,110 @@ void StorageManager::login(UInt32 nameLength, const void *name, } } - if (!loginUnlocked) { - try { - loginResult = errSecSuccess; - Keychain theKeychain(keychain(loginDLDbIdentifier)); + // is it token login? + CFRef tokenLoginContext; + OSStatus status = TokenLoginGetContext(password, passwordLength, tokenLoginContext.take()); + if (!loginUnlocked || status == errSecSuccess) { + Keychain theKeychain(keychain(loginDLDbIdentifier)); + bool tokenLoginDataUpdated = false; + + for (UInt32 i = 0; i < 2; i++) { + loginResult = errSecSuccess; + + CFRef tokenLoginData; + if (tokenLoginContext) { + status = TokenLoginGetLoginData(tokenLoginContext, tokenLoginData.take()); + if (status != errSecSuccess) { + if (tokenLoginDataUpdated) { + loginResult = status; + break; + } + // updating unlock key fails if it is not token login + secnotice("KCLogin", "Error %d, reconstructing unlock data", (int)status); + status = TokenLoginUpdateUnlockData(tokenLoginContext); + if (status == errSecSuccess) { + loginResult = TokenLoginGetLoginData(tokenLoginContext, tokenLoginData.take()); + if (loginResult != errSecSuccess) { + break; + } + tokenLoginDataUpdated = true; + } + } + } - // build a fake key - CssmKey key; - key.header().BlobType = CSSM_KEYBLOB_RAW; - key.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; - key.header().AlgorithmId = CSSM_ALGID_3DES_3KEY; - key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; - key.header().KeyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYATTR_EXTRACTABLE; - key.header().KeyAttr = 0; - key.KeyData = CssmData(const_cast(password), passwordLength); - - // unwrap it into the CSP (but keep it raw) - UnwrapKey unwrap(theKeychain->csp(), CSSM_ALGID_NONE); - CssmKey masterKey; - CssmData descriptiveData; - unwrap(key, - KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_EXTRACTABLE), - masterKey, &descriptiveData, NULL); - - CssmClient::Db db = theKeychain->database(); - - // create the keychain, using appropriate credentials - Allocator &alloc = db->allocator(); - AutoCredentials cred(alloc); // will leak, but we're quitting soon :-) - - // use this passphrase - cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, - new(alloc) ListElement(CSSM_SAMPLE_TYPE_SYMMETRIC_KEY), - new(alloc) ListElement(CssmData::wrap(theKeychain->csp()->handle())), - new(alloc) ListElement(CssmData::wrap(masterKey)), - new(alloc) ListElement(CssmData())); - db->authenticate(CSSM_DB_ACCESS_READ, &cred); - db->unlock(); - loginUnlocked = true; - } catch (const CssmError &e) { - loginResult = e.osStatus(); + try { + // first try to unlock login keychain because if this fails, token keychain unlock fails as well + if (tokenLoginData) { + secnotice("KCLogin", "Going to unlock keybag using scBlob"); + status = TokenLoginUnlockKeybag(tokenLoginContext, tokenLoginData); + secnotice("KCLogin", "Keybag unlock result %d", (int)status); + if (status) + CssmError::throwMe(status); // to trigger login data regeneration + } + + // build a fake key + CssmKey key; + key.header().BlobType = CSSM_KEYBLOB_RAW; + key.header().Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; + key.header().AlgorithmId = CSSM_ALGID_3DES_3KEY; + key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY; + key.header().KeyUsage = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYATTR_EXTRACTABLE; + key.header().KeyAttr = 0; + CFRef tokenLoginUnlockKey; + if (tokenLoginData) { + status = TokenLoginGetUnlockKey(tokenLoginContext, tokenLoginUnlockKey.take()); + if (status) + CssmError::throwMe(status); // to trigger login data regeneration + key.KeyData = CssmData(tokenLoginUnlockKey.get()); + } else { + key.KeyData = CssmData(const_cast(password), passwordLength); + } + // unwrap it into the CSP (but keep it raw) + UnwrapKey unwrap(theKeychain->csp(), CSSM_ALGID_NONE); + CssmKey masterKey; + CssmData descriptiveData; + unwrap(key, + KeySpec(CSSM_KEYUSE_ANY, CSSM_KEYATTR_EXTRACTABLE), + masterKey, &descriptiveData, NULL); + + CssmClient::Db db = theKeychain->database(); + + // create the keychain, using appropriate credentials + Allocator &alloc = db->allocator(); + AutoCredentials cred(alloc); // will leak, but we're quitting soon :-) + + // use this passphrase + cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, + new(alloc) ListElement(CSSM_SAMPLE_TYPE_SYMMETRIC_KEY), + new(alloc) ListElement(CssmData::wrap(theKeychain->csp()->handle())), + new(alloc) ListElement(CssmData::wrap(masterKey)), + new(alloc) ListElement(CssmData())); + db->authenticate(CSSM_DB_ACCESS_READ, &cred); + db->unlock(); + loginUnlocked = true; + } catch (const CssmError &e) { + if (tokenLoginData && !tokenLoginDataUpdated) { + // token login unlock key was invalid + loginResult = TokenLoginUpdateUnlockData(tokenLoginContext); + if (loginResult == errSecSuccess) { + tokenLoginDataUpdated = true; + continue; + } + } + else { + loginResult = e.osStatus(); + } + } + break; } } // if "shortname.keychain" exists and is in the search list, attempt to auto-unlock it with the same password - if (shortnameDotKeychainExists && mSavedList.member(shortnameDotDLDbIdentifier)) { + if (shortnameDotKeychainExists && mSavedList.member(demungeDLDbIdentifier(shortnameDotDLDbIdentifier))) { try { Keychain shortnameDotKC(keychain(shortnameDotDLDbIdentifier)); - secdebug("KCLogin", "Attempting to unlock %s", + secnotice("KCLogin", "Attempting to unlock %s", (shortnameDotKC) ? shortnameDotKC->name() : ""); shortnameDotKC->unlock(CssmData(const_cast(password), passwordLength)); } @@ -1412,7 +1686,7 @@ void StorageManager::stashLogin() loginDLDbIdentifier = mSavedList.loginDLDbIdentifier(); } - secdebug("KCLogin", "StorageManager::stash: loginDLDbIdentifier is %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); + secnotice("KCLogin", "StorageManager::stash: loginDLDbIdentifier is %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); if (!loginDLDbIdentifier) MacOSError::throwMe(errSecNoSuchKeychain); @@ -1420,7 +1694,7 @@ void StorageManager::stashLogin() { CssmData empty; Keychain theKeychain(keychain(loginDLDbIdentifier)); - secdebug("KCLogin", "Attempting to use stash for login keychain \"%s\"", + secnotice("KCLogin", "Attempting to use stash for login keychain \"%s\"", (theKeychain) ? theKeychain->name() : ""); theKeychain->stashCheck(); } @@ -1445,14 +1719,14 @@ void StorageManager::stashKeychain() loginDLDbIdentifier = mSavedList.loginDLDbIdentifier(); } - secdebug("KCLogin", "StorageManager::stash: loginDLDbIdentifier is %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); + secnotice("KCLogin", "StorageManager::stash: loginDLDbIdentifier is %s", (loginDLDbIdentifier) ? loginDLDbIdentifier.dbName() : ""); if (!loginDLDbIdentifier) MacOSError::throwMe(errSecNoSuchKeychain); try { Keychain theKeychain(keychain(loginDLDbIdentifier)); - secdebug("KCLogin", "Attempting to stash login keychain \"%s\"", + secnotice("KCLogin", "Attempting to stash login keychain \"%s\"", (theKeychain) ? theKeychain->name() : ""); theKeychain->stash(); } @@ -1477,7 +1751,7 @@ void StorageManager::changeLoginPassword(ConstStringPtr oldPassword, ConstString StLock_(mMutex); loginKeychain()->changePassphrase(oldPassword, newPassword); - secdebug("KClogin", "Changed login keychain password successfully"); + secnotice("KClogin", "Changed login keychain password successfully"); } @@ -1486,7 +1760,7 @@ void StorageManager::changeLoginPassword(UInt32 oldPasswordLength, const void *o StLock_(mMutex); loginKeychain()->changePassphrase(oldPasswordLength, oldPassword, newPasswordLength, newPassword); - secdebug("KClogin", "Changed login keychain password successfully"); + secnotice("KClogin", "Changed login keychain password successfully"); } // Clear out the keychain search list and rename the existing login.keychain. @@ -1518,15 +1792,23 @@ void StorageManager::resetKeychain(Boolean resetSearchList) { CFStringAppend(newName, currName); CFStringRef kcSuffix = CFSTR(kKeychainSuffix); + CFStringRef kcDbSuffix = CFSTR(kKeychainDbSuffix); + bool hasDbSuffix = false; if ( CFStringHasSuffix(newName, kcSuffix) ) // remove the .keychain extension { CFRange suffixRange = CFStringFind(newName, kcSuffix, 0); CFStringFindAndReplace(newName, kcSuffix, CFSTR(""), suffixRange, 0); } + if (CFStringHasSuffix(newName, kcDbSuffix)) { + hasDbSuffix = true; + CFRange suffixRange = CFStringFind(newName, kcDbSuffix, 0); + CFStringFindAndReplace(newName, kcDbSuffix, CFSTR(""), suffixRange, 0); + } + CFStringAppend(newName, CFSTR(kKeychainRenamedSuffix)); // add "_renamed_" try { - renameUnique(keychain, newName); + renameUnique(keychain, newName, hasDbSuffix); } catch(...) { @@ -1554,7 +1836,11 @@ Keychain StorageManager::make(const char *pathName) Keychain StorageManager::make(const char *pathName, bool add) { - return makeKeychain(makeDLDbIdentifier(pathName), add); + return make(pathName, add, false); +} + +Keychain StorageManager::make(const char *pathName, bool add, bool isReset) { + return makeKeychain(makeDLDbIdentifier(pathName), add, isReset); } DLDbIdentifier StorageManager::makeDLDbIdentifier(const char *pathName) { @@ -1606,7 +1892,7 @@ DLDbIdentifier StorageManager::makeDLDbIdentifier(const char *pathName) { return dlDbIdentifier; } -Keychain StorageManager::makeLoginAuthUI(const Item *item) +Keychain StorageManager::makeLoginAuthUI(const Item *item, bool isReset) { StLock_(mMutex); @@ -1772,7 +2058,7 @@ Keychain StorageManager::makeLoginAuthUI(const Item *item) catch (...) // can throw if no existing login.keychain is found { } - login(authRef, (UInt32)userName.length(), userName.c_str()); // Create login.keychain + login(authRef, (UInt32)userName.length(), userName.c_str(), isReset); // Create login.keychain keychain = loginKeychain(); // Get newly-created login keychain defaultKeychain(keychain); // Set it to be the default @@ -1809,7 +2095,7 @@ Keychain StorageManager::defaultKeychainUI(Item &item) } if ( globals().getUserInteractionAllowed() ) { - returnedKeychain = makeLoginAuthUI(&item); // If no Keychains is present, one will be created. + returnedKeychain = makeLoginAuthUI(&item, false); // If no Keychains is present, one will be created. if ( !returnedKeychain ) MacOSError::throwMe(errSecInvalidKeychain); // Something went wrong... } @@ -1838,7 +2124,7 @@ StorageManager::addToDomainList(SecPreferencesDomain domain, // manipulate the user's list { mSavedList.revert(true); - mSavedList.add(id); + mSavedList.add(demungeDLDbIdentifier(id)); mSavedList.save(); } @@ -1868,11 +2154,11 @@ StorageManager::isInDomainList(SecPreferencesDomain domain, bool result; if (domain == mDomain) { - result = mSavedList.member(id); + result = mSavedList.member(demungeDLDbIdentifier(id)); } else { - result = DLDbListCFPref(domain).member(id); + result = DLDbListCFPref(domain).member(demungeDLDbIdentifier(id)); } // do the search @@ -1901,7 +2187,7 @@ StorageManager::removeFromDomainList(SecPreferencesDomain domain, // manipulate the user's list { mSavedList.revert(true); - mSavedList.remove(id); + mSavedList.remove(demungeDLDbIdentifier(id)); mSavedList.save(); } diff --git a/OSX/libsecurity_keychain/lib/StorageManager.h b/OSX/libsecurity_keychain/lib/StorageManager.h index b1f82cf4..33f03033 100644 --- a/OSX/libsecurity_keychain/lib/StorageManager.h +++ b/OSX/libsecurity_keychain/lib/StorageManager.h @@ -62,7 +62,8 @@ public: // These will call addAndNotify() if the specified keychain already exists Keychain make(const char *fullPathName); Keychain make(const char *fullPathName, bool add); - Keychain makeLoginAuthUI(const Item *item); + Keychain make(const char *fullPathName, bool add, bool isReset); + Keychain makeLoginAuthUI(const Item *item, bool isReset); void created(const Keychain &keychain); // Be notified a Keychain just got created. // Misc @@ -90,11 +91,15 @@ public: void didRemoveKeychain(const DLDbIdentifier &dLDbIdentifier); // Create KC if it doesn't exist, add it to the search list if it exists and is not already on it. - Keychain makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add = true); + Keychain makeKeychain(const DLDbIdentifier &dLDbIdentifier, bool add, bool isReset); // Reload a keychain from the on-disk database void reloadKeychain(Keychain keychain); + // Register a keychain in the keychain cache + void registerKeychain(Keychain& kc); + void registerKeychainImpl(KeychainImpl* kc); + // Keychain list maintenance // remove kcsToRemove from the search list @@ -108,7 +113,7 @@ public: void setSearchList(SecPreferencesDomain domain, const KeychainList &keychainList); void rename(Keychain keychain, const char* newName); - void renameUnique(Keychain keychain, CFStringRef newName); + void renameUnique(Keychain keychain, CFStringRef newName, bool appendDbSuffix); // Iff keychainOrArray is NULL return the default KeychainList in keychainList otherwise // if keychainOrArray is a CFArrayRef containing SecKeychainRef's convernt it to KeychainList, @@ -122,15 +127,19 @@ public: static CFArrayRef convertFromKeychainList(const KeychainList &keychainList); // Login keychain support - void login(AuthorizationRef authRef, UInt32 nameLength, const char* name); + void login(AuthorizationRef authRef, UInt32 nameLength, const char* name, bool isReset); void login(ConstStringPtr name, ConstStringPtr password); - void login(UInt32 nameLength, const void *name, UInt32 passwordLength, const void *password); + void login(UInt32 nameLength, const void *name, UInt32 passwordLength, const void *password, bool isReset); void stashLogin(); void stashKeychain(); void logout(); void changeLoginPassword(ConstStringPtr oldPassword, ConstStringPtr newPassword); void changeLoginPassword(UInt32 oldPasswordLength, const void *oldPassword, UInt32 newPasswordLength, const void *newPassword); + // Token login support + CFDataRef getTokenLoginMasterKey(UInt32 passwordLength, const void *password); + CFDataRef unwrapTokenLoginMasterKey(CFDictionaryRef masterKeyData, CFStringRef tokenID, CFStringRef pin); + void resetKeychain(Boolean resetSearchList); Keychain defaultKeychain(); @@ -160,6 +169,37 @@ private: DLDbIdentifier makeDLDbIdentifier(const char* pathName); CssmClient::Db makeDb(DLDbIdentifier dLDbIdentifier); + // Use this when you want to be extra sure this keychain is removed from the + // cache. Iterates over the whole cache to find all instances. This function + // will take the cache map mutex. + void forceRemoveFromCache(KeychainImpl* inItemImpl); + +public: + // Change the DLDBIdentifier to reflect the files on-disk. Currently: + // If the keychain is in ~/Library/Keychains and either + // the .keychain-db version of the file exists or + // (global integrity protection is on AND isReset is true) + // then change the filename to include ".keychain-db". + // + // Otherwise, leave it alone. + static DLDbIdentifier mungeDLDbIdentifier(const DLDbIdentifier& dLDbIdentifier, bool isReset); + + // Due to compatibility requirements, we need the DLDbListCFPref lists to + // never see a ".keychain-db" filename. Call this function to give them what + // they need. + static DLDbIdentifier demungeDLDbIdentifier(const DLDbIdentifier& dLDbIdentifier); + + // Take a filename, and give it the extension .keychain-db + static string makeKeychainDbFilename(const string& filename); + + // Check if a keychain path is in some user's ~/Library/Keychains/ folder. + static bool pathInHomeLibraryKeychains(const string& path); + + // Notify the StorageManager that you're accessing this keychain. Used for + // time-based caching purposes. + void tickleKeychain(KeychainImpl *keychainImpl); + +private: // Only add if not there yet. Writes out CFPref and broadcasts KCPrefListChanged notification void addAndNotify(const Keychain& keychainToAdd); @@ -169,7 +209,7 @@ private: typedef map KeychainMap; // Reference map of all keychains we know about that aren't deleted // or removed - KeychainMap mKeychains; + KeychainMap mKeychainMap; // The dynamic search list. DynamicDLDBList mDynamicList; diff --git a/OSX/libsecurity_keychain/lib/TokenLogin.cpp b/OSX/libsecurity_keychain/lib/TokenLogin.cpp new file mode 100644 index 00000000..03255cd2 --- /dev/null +++ b/OSX/libsecurity_keychain/lib/TokenLogin.cpp @@ -0,0 +1,614 @@ +/* + * 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 "TokenLogin.h" + +#include +#include +#include +#include "SecBase64P.h" +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +} + +#define kSecTokenLoginDomain CFSTR("com.apple.security.tokenlogin") + +static CFStringRef cfDataToHex(CFDataRef bin) +{ + size_t len = CFDataGetLength(bin) * 2; + CFMutableStringRef str = CFStringCreateMutable(NULL, len); + + static const char* digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}; + + const uint8_t* data = CFDataGetBytePtr(bin); + for (size_t i = 0; i < CFDataGetLength(bin); i++) { + CFStringAppendCString(str, digits[data[i] >> 4], 1); + CFStringAppendCString(str, digits[data[i] & 0xf], 1); + } + return str; +} + +static CFStringRef getPin(CFDictionaryRef context) +{ + if (!context) { + return NULL; + } + + CFStringRef pin = (CFStringRef)CFDictionaryGetValue(context, kSecAttrService); + if (!pin || CFGetTypeID(pin) != CFStringGetTypeID()) { + return NULL; + } + return pin; +} + +static CFStringRef getTokenId(CFDictionaryRef context) +{ + if (!context) { + return NULL; + } + + CFStringRef tokenId = (CFStringRef)CFDictionaryGetValue(context, kSecAttrTokenID); + if (!tokenId || CFGetTypeID(tokenId) != CFStringGetTypeID()) { + secinfo("TokenLogin", "Invalid tokenId"); + return NULL; + } + return tokenId; +} + +static CFDataRef getPubKeyHash(CFDictionaryRef context) +{ + if (!context) { + return NULL; + } + + CFDataRef pubKeyHash = (CFDataRef)CFDictionaryGetValue(context, kSecAttrPublicKeyHash); + if (!pubKeyHash || CFGetTypeID(pubKeyHash) != CFDataGetTypeID()) { + secinfo("TokenLogin", "Invalid pubkeyhash"); + return NULL; + } + return pubKeyHash; +} + +static CFDataRef getPubKeyHashWrap(CFDictionaryRef context) +{ + if (!context) { + return NULL; + } + + CFDataRef pubKeyHashWrap = (CFDataRef)CFDictionaryGetValue(context, kSecAttrAccount); + if (!pubKeyHashWrap || CFGetTypeID(pubKeyHashWrap) != CFDataGetTypeID()) { + secinfo("TokenLogin", "Invalid pubkeyhashwrap"); + return NULL; + } + return pubKeyHashWrap; +} + +static OSStatus privKeyForPubKeyHash(CFDictionaryRef context, SecKeyRef *privKey, CFTypeRef *laCtx) +{ + if (!context) { + return errSecParam; + } + + CFRef tokenAttributes = makeCFMutableDictionary(1, kSecAttrTokenID, getTokenId(context)); + CFRef error; + + CFStringRef pin = getPin(context); + if (pin) { + CFRef LAParams = makeCFDictionary(1, CFSTR("useDaemon"), kCFBooleanFalse); + CFRef LAContext = LACreateNewContextWithACMContext(LAParams.as(), error.take()); + if (!LAContext) { + secinfo("TokenLogin", "Failed to LA Context: %@", error.get()); + return errSecParam; + } + if (laCtx) + *laCtx = (CFTypeRef)CFRetain(LAContext); + CFRef externalizedContext = LACopyACMContext(LAContext, error.take()); + if (!externalizedContext) { + secinfo("TokenLogin", "Failed to get externalized context: %@", error.get()); + return errSecParam; + } + CFDictionarySetValue(tokenAttributes, kSecUseCredentialReference, externalizedContext.get()); + CFDictionarySetValue(tokenAttributes, CFSTR("PIN"), pin); + } + + CFRef token = TKTokenCreate(tokenAttributes, error.take()); + if (!token) { + secinfo("TokenLogin", "Failed to create token: %@", error.get()); + return errSecParam; + } + + CFRef identities = TKTokenCopyIdentities(token, TKTokenKeyUsageAny, error.take()); + if (!identities || !CFArrayGetCount(identities)) { + secinfo("TokenLogin", "No identities found for token: %@", error.get()); + return errSecParam; + } + + CFDataRef desiredHash = getPubKeyHashWrap(context); + CFIndex idx, count = CFArrayGetCount(identities); + for (idx = 0; idx < count; ++idx) { + SecIdentityRef identity = (SecIdentityRef)CFArrayGetValueAtIndex(identities, idx); + CFRef certificate; + OSStatus result = SecIdentityCopyCertificate(identity, certificate.take()); + if (result != errSecSuccess) { + secinfo("TokenLogin", "Failed to get certificate for identity: %d", (int) result); + continue; + } + + CFRef identityHash = SecCertificateCopyPublicKeySHA1Digest(certificate); + if (identityHash && CFEqual(desiredHash, identityHash)) { + result = SecIdentityCopyPrivateKey(identity, privKey); + if (result != errSecSuccess) { + secinfo("TokenLogin", "Failed to get identity private key: %d", (int) result); + } + return result; + } + } + + return errSecParam; +} + +OSStatus TokenLoginGetContext(const void *base64TokenLoginData, UInt32 base64TokenLoginDataLength, CFDictionaryRef *context) +{ + if (!base64TokenLoginData || !context) { + return errSecParam; + } + + // Token data are base64 encoded in password. + size_t dataLen = SecBase64Decode((const char *)base64TokenLoginData, base64TokenLoginDataLength, NULL, 0); + if (!dataLen) { + secinfo("TokenLogin", "Invalid base64 encoded token data"); + return errSecParam; + } + + CFRef data = CFDataCreateMutable(kCFAllocatorDefault, dataLen); + dataLen = SecBase64Decode((const char *)base64TokenLoginData, base64TokenLoginDataLength, CFDataGetMutableBytePtr(data), dataLen); + if (!dataLen) { + secinfo("TokenLogin", "Invalid base64 encoded token data"); + return errSecParam; + } + CFDataSetLength(data, dataLen); + + // Content of the password consists of a serialized dictionary containing token ID, PIN, wrap key hash etc. + CFRef error; + *context = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorDefault, + data, + kCFPropertyListImmutable, + NULL, + error.take()); + if (!*context || CFGetTypeID(*context) != CFDictionaryGetTypeID()) { + secinfo("TokenLogin", "Invalid token login data property list, %@", error.get()); + return errSecParam; + } + + if (!getPin(*context) || !getTokenId(*context) || !getPubKeyHash(*context) || !getPubKeyHashWrap(*context)) { + secinfo("TokenLogin", "Invalid token login data context, %@", error.get()); + return errSecParam; + } + + return errSecSuccess; +} + +OSStatus TokenLoginGetUnlockKey(CFDictionaryRef context, CFDataRef *unlockKey) +{ + if (!context || !unlockKey) { + return errSecParam; + } + + CFRef loginData; + OSStatus result = TokenLoginGetLoginData(context, loginData.take()); + if (result != errSecSuccess) { + secinfo("TokenLogin", "Failed to get login data: %d", (int)result); + return result; + } + + CFDataRef wrappedUnlockKey = (CFDataRef)CFDictionaryGetValue(loginData, kSecValueData); + if (!wrappedUnlockKey) { + secinfo("TokenLogin", "Wrapped unlock key not found in unlock key data"); + return errSecParam; + } + SecKeyAlgorithm algorithm = (SecKeyAlgorithm)CFDictionaryGetValue(loginData, kSecAttrService); + if (!algorithm) { + secinfo("TokenLogin", "Algorithm not found in unlock key data"); + return errSecParam; + } + + CFRef privKey; + CFRef LAContext; + result = privKeyForPubKeyHash(context, privKey.take(), LAContext.take()); + if (result != errSecSuccess) { + secinfo("TokenLogin", "Failed to get private key for public key hash: %d", (int)result); + return result; + } + + CFRef pubKey = SecKeyCopyPublicKey(privKey); + if (!pubKey) { + secinfo("TokenLogin", "Failed to get public key from private key"); + return errSecParam; + } + CFRef error; + *unlockKey = SecKeyCreateDecryptedData(privKey, + algorithm, + wrappedUnlockKey, + error.take()); + if (!*unlockKey) { + secinfo("TokenLogin", "Failed to unwrap unlock key: %@", error.get()); + return errSecDecode; + } + + // we need to re-wrap already unwrapped data to avoid capturing and reusing communication with the smartcard + CFRef reWrappedUnlockKey = SecKeyCreateEncryptedData(pubKey, algorithm, *unlockKey, error.take()); + if (!reWrappedUnlockKey) { + secinfo("TokenLogin", "Failed to rewrap unlock key: %@", error.get()); + TokenLoginDeleteUnlockData(getPubKeyHash(context)); + return errSecParam; + } + + CFRef newDict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 4, loginData); + if (newDict) { + CFDictionarySetValue(newDict, kSecValueData, reWrappedUnlockKey); + TokenLoginStoreUnlockData(context, newDict); + } + + return errSecSuccess; +} + +OSStatus TokenLoginGetLoginData(CFDictionaryRef context, CFDictionaryRef *loginData) +{ + if (!loginData || !context) { + return errSecParam; + } + + CFRef pubKeyHashHex = cfDataToHex(getPubKeyHash(context)); + CFPreferencesSynchronize(kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFRef storedData = (CFDataRef)CFPreferencesCopyValue(pubKeyHashHex, kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + if (!storedData) { + secinfo("TokenLogin", "Failed to read token login plist"); + return errSecIO; + } + + CFRef error; + *loginData = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorDefault, + storedData, + kCFPropertyListImmutable, + NULL, + error.take()); + if (!*loginData || CFGetTypeID(*loginData) != CFDictionaryGetTypeID()) { + secinfo("TokenLogin", "Failed to deserialize unlock key data: %@", error.get()); + return errSecParam; + } + + return errSecSuccess; +} + +OSStatus TokenLoginUpdateUnlockData(CFDictionaryRef context) +{ + if (!context) { + return errSecParam; + } + + CFRef loginKeychain; + OSStatus result = SecKeychainCopyLogin(loginKeychain.take()); + if (result != errSecSuccess) { + secinfo("TokenLogin", "Failed to get user keychain: %d", (int) result); + return result; + } + + return SecKeychainStoreUnlockKeyWithPubKeyHash(getPubKeyHash(context), getTokenId(context), getPubKeyHashWrap(context), loginKeychain, NULL); +} + +OSStatus TokenLoginCreateLoginData(CFStringRef tokenId, CFDataRef pubKeyHash, CFDataRef pubKeyHashWrap, CFDataRef unlockKey, CFDataRef scBlob) +{ + if (!tokenId || !pubKeyHash || !pubKeyHashWrap || !unlockKey || !scBlob) + return errSecParam; + + CFRef ctx = makeCFDictionary(3, + kSecAttrTokenID, tokenId, + kSecAttrPublicKeyHash, pubKeyHash, + kSecAttrAccount, pubKeyHashWrap + ); + CFRef privKey; + OSStatus result = privKeyForPubKeyHash(ctx, privKey.take(), NULL); + if (result != errSecSuccess) { + secinfo("TokenLogin", "Failed to get private key for public key hash: %d", (int) result); + return result; + } + + CFRef pubKey = SecKeyCopyPublicKey(privKey); + if (!pubKey) { + secinfo("TokenLogin", "Failed to get public key from private key"); + return errSecParam; + } + + SecKeyAlgorithm algorithms[] = { + kSecKeyAlgorithmECIESEncryptionStandardX963SHA512AESGCM, + kSecKeyAlgorithmECIESEncryptionStandardX963SHA384AESGCM, + kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, + kSecKeyAlgorithmECIESEncryptionStandardX963SHA224AESGCM, + kSecKeyAlgorithmECIESEncryptionStandardX963SHA1AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM + }; + + SecKeyAlgorithm algorithm = NULL; + for (size_t i = 0; i < sizeof(algorithms) / sizeof(*algorithms); i++) { + if (SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeEncrypt, algorithms[i]) + && SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeDecrypt, algorithms[i])) { + algorithm = algorithms[i]; + break; + } + } + if (algorithm == NULL) { + secinfo("SecKeychain", "Failed to find supported wrap algorithm"); + return errSecParam; + } + + CFRef error; + CFRef wrappedUnlockKey = SecKeyCreateEncryptedData(pubKey, algorithm, unlockKey, error.take()); + if (!wrappedUnlockKey) { + secinfo("TokenLogin", "Failed to wrap unlock key: %@", error.get()); + return errSecParam; + } + + CFRef loginData = makeCFDictionary(4, + kSecAttrService, algorithm, + kSecAttrPublicKeyHash, pubKeyHashWrap, + kSecValueData, wrappedUnlockKey.get(), + kSecClassKey, scBlob + ); + return TokenLoginStoreUnlockData(ctx, loginData); +} + +OSStatus TokenLoginStoreUnlockData(CFDictionaryRef context, CFDictionaryRef loginData) +{ + + CFRef error; + CFRef data = CFPropertyListCreateData(kCFAllocatorDefault, + loginData, + kCFPropertyListBinaryFormat_v1_0, + 0, + error.take()); + if (!data) { + secdebug("TokenLogin", "Failed to create unlock data: %@", error.get()); + return errSecInternal; + } + CFRef pubKeyHashHex = cfDataToHex(getPubKeyHash(context)); + CFPreferencesSetValue(pubKeyHashHex, data, kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFPreferencesSynchronize(kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFRef storedData = (CFDataRef)CFPreferencesCopyValue(pubKeyHashHex, kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + + if (!storedData || !CFEqual(storedData, data)) { + secinfo("TokenLogin", "Failed to write token login plist"); + return errSecIO; + } + + return errSecSuccess; +} + +OSStatus TokenLoginDeleteUnlockData(CFDataRef pubKeyHash) +{ + CFRef pubKeyHashHex = cfDataToHex(pubKeyHash); + CFPreferencesSetValue(pubKeyHashHex, NULL, kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFPreferencesSynchronize(kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + CFRef storedData = (CFDataRef)CFPreferencesCopyValue(pubKeyHashHex, kSecTokenLoginDomain, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); + + if (storedData) { + secinfo("TokenLogin", "Failed to remove unlock data"); + return errSecIO; + } + + return errSecSuccess; +} + +OSStatus TokenLoginGetScBlob(CFDataRef pubKeyHashWrap, CFStringRef tokenId, CFStringRef password, CFDataRef *scBlob) +{ + if (scBlob == NULL || password == NULL || pubKeyHashWrap == NULL || tokenId == NULL) { + secinfo("TokenLogin", "TokenLoginGetScBlob wrong params"); + return errSecParam; + } + + CFRef ctx = makeCFDictionary(2, + kSecAttrTokenID, tokenId, + kSecAttrAccount, pubKeyHashWrap + ); + + CFRef privKey; + OSStatus retval = privKeyForPubKeyHash(ctx, privKey.take(), NULL); + if (retval != errSecSuccess) { + secinfo("TokenLogin", "TokenLoginGetScBlob failed to get private key for public key hash: %d", (int) retval); + return retval; + } + + CFRef pubKey = SecKeyCopyPublicKey(privKey); + if (!pubKey) { + secinfo("TokenLogin", "TokenLoginGetScBlob no pubkey"); + return errSecInternal; + } + + CFRef attributes = SecKeyCopyAttributes(pubKey); + if (!attributes) { + secinfo("TokenLogin", "TokenLoginGetScBlob no attributes"); + return errSecInternal; + } + + aks_smartcard_mode_t mode; + CFRef type = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrKeyType); + if (CFEqual(type, kSecAttrKeyTypeRSA)) + mode = AKS_SMARTCARD_MODE_RSA; + else if (CFEqual(type, kSecAttrKeyTypeEC)) + mode = AKS_SMARTCARD_MODE_ECDH; + else { + secinfo("TokenLogin", "TokenLoginGetScBlob bad type"); + return errSecNotAvailable; + } + + CFRef publicBytes = SecKeyCopyExternalRepresentation(pubKey, NULL); + if (!publicBytes) { + secinfo("TokenLogin", "TokenLoginGetScBlob cannot get public bytes"); + return retval; + } + + CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(password), kCFStringEncodingUTF8) + 1; + char* buf = (char*)malloc(maxLength); + if (buf == NULL) { + secinfo("TokenLogin", "TokenLoginGetScBlob no mem for buffer"); + return retval; + } + + if (CFStringGetCString(password, buf, maxLength, kCFStringEncodingUTF8) == FALSE) { + secinfo("TokenLogin", "TokenLoginGetScBlob no pwd cstr"); + free(buf); + return retval; + } + + void *sc_blob = NULL; + size_t sc_len = 0; + aks_smartcard_unregister(session_keybag_handle); // just to be sure no previous registration exist + kern_return_t aks_retval = aks_smartcard_register(session_keybag_handle, (uint8_t *)buf, strlen(buf), mode, (uint8_t *)CFDataGetBytePtr(publicBytes), (size_t)CFDataGetLength(publicBytes), &sc_blob, &sc_len); + free(buf); + secinfo("TokenLogin", "TokenLoginGetScBlob register result %d", aks_retval); + + if (sc_blob) { + *scBlob = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)sc_blob, (CFIndex)sc_len); + free(sc_blob); + } + return aks_retval; +} + +OSStatus TokenLoginUnlockKeybag(CFDictionaryRef context, CFDictionaryRef loginData) +{ + if (!loginData || !context) { + return errSecParam; + } + + CFDataRef scBlob = (CFDataRef)CFDictionaryGetValue(loginData, kSecClassKey); + if (scBlob == NULL) { + secinfo("TokenLogin", "Failed to get scblob"); + return errSecInternal; + } + + CFRef error; + CFRef privKey; + CFRef LAContext; + OSStatus retval = privKeyForPubKeyHash(context, privKey.take(), LAContext.take()); + if (retval != errSecSuccess) { + secinfo("TokenLogin", "Failed to get private key for public key hash: %d", (int) retval); + return retval; + } + + CFRef pubKey = SecKeyCopyPublicKey(privKey); + if (!pubKey) { + secinfo("TokenLogin", "Failed to get pubkey"); + return retval; + } + + CFRef attributes = SecKeyCopyAttributes(pubKey); + if (!attributes) { + secinfo("TokenLogin", "TokenLoginUnlockKeybag no attributes"); + return errSecInternal; + } + + aks_smartcard_mode_t mode; + CFStringRef type = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrKeyType); + if (CFEqual(type, kSecAttrKeyTypeRSA)) + mode = AKS_SMARTCARD_MODE_RSA; + else if (CFEqual(type, kSecAttrKeyTypeEC)) + mode = AKS_SMARTCARD_MODE_ECDH; + else { + secinfo("TokenLogin", "TokenLoginUnlockKeybag bad type"); + return errSecNotAvailable; + } + + void *scChallenge = NULL; + size_t scChallengeLen = 0; + int res = aks_smartcard_request_unlock(session_keybag_handle, (uint8_t *)CFDataGetBytePtr(scBlob), (size_t)CFDataGetLength(scBlob), &scChallenge, &scChallengeLen); + if (res != 0) { + secinfo("TokenLogin", "TokenLoginUnlockKeybag cannot request unlock: %x", res); + return errSecInternal; + } + const void *scUsk = NULL; + size_t scUskLen = 0; + res = aks_smartcard_get_sc_usk(scChallenge, scChallengeLen, &scUsk, &scUskLen); + + if (res != 0 || scUsk == NULL) { + free(scChallenge); + secinfo("TokenLogin", "TokenLoginUnlockKeybag cannot get usk: %x", res); + return errSecInternal; + } + + CFRef wrappedUsk; + if (mode == AKS_SMARTCARD_MODE_ECDH) { + const void *ecPub = NULL; + size_t ecPubLen = 0; + res = aks_smartcard_get_ec_pub(scChallenge, scChallengeLen, &ecPub, &ecPubLen); + if (res != 0 || ecPub == NULL) { + free(scChallenge); + secinfo("TokenLogin", "TokenLoginUnlockKeybag cannot get ecpub: %x", res); + return errSecInternal; + } + wrappedUsk = CFDataCreateMutable(kCFAllocatorDefault, ecPubLen + scUskLen); + if (!wrappedUsk) { + free(scChallenge); + secinfo("TokenLogin", "TokenLoginUnlockKeybag no mem for ecpubusk"); + return errSecInternal; + } + CFDataAppendBytes((CFMutableDataRef)wrappedUsk.get(), (const UInt8 *)ecPub, (CFIndex)ecPubLen); + CFDataAppendBytes((CFMutableDataRef)wrappedUsk.get(), (const UInt8 *)scUsk, (CFIndex)scUskLen); + } else { + wrappedUsk = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)scUsk, (CFIndex)scUskLen); + } + free(scChallenge); + // decrypt Usk with SC + CFRef unwrappedUsk = SecKeyCreateDecryptedData(privKey, + mode == AKS_SMARTCARD_MODE_RSA ? kSecKeyAlgorithmRSAEncryptionOAEPSHA256 : kSecKeyAlgorithmECIESEncryptionAKSSmartCard, + (CFDataRef)wrappedUsk.get(), + error.take()); + if (!unwrappedUsk) { + secinfo("TokenLogin", "TokenLoginUnlockKeybag failed to unwrap blob: %@", error.get()); + return errSecInternal; + } + + void *scNewBlob = NULL; + size_t scNewLen = 0; + res = aks_smartcard_unlock(session_keybag_handle, (uint8_t *)CFDataGetBytePtr(scBlob), (size_t)CFDataGetLength(scBlob), (uint8_t *)CFDataGetBytePtr(unwrappedUsk), (size_t)CFDataGetLength(unwrappedUsk), &scNewBlob, &scNewLen); + if (scNewBlob) { + CFRef newBlobData = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)scNewBlob, (CFIndex)scNewLen); + free(scNewBlob); + CFRef newDict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 4, loginData); + if (newDict) { + CFDictionarySetValue(newDict, kSecClassKey, newBlobData.get()); + TokenLoginStoreUnlockData(context, newDict); + } + } + return res; +} diff --git a/OSX/libsecurity_keychain/lib/TokenLogin.h b/OSX/libsecurity_keychain/lib/TokenLogin.h new file mode 100644 index 00000000..b7976bf8 --- /dev/null +++ b/OSX/libsecurity_keychain/lib/TokenLogin.h @@ -0,0 +1,49 @@ +/* + * 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@ + */ + +#ifndef TokenLogin_h +#define TokenLogin_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +OSStatus TokenLoginGetContext(const void *base64TokenLoginData, UInt32 base64TokenLoginDataLength, CFDictionaryRef *context); +OSStatus TokenLoginGetLoginData(CFDictionaryRef context, CFDictionaryRef *loginData); + +OSStatus TokenLoginCreateLoginData(CFStringRef tokenId, CFDataRef pubKeyHash, CFDataRef pubKeyHashWrap, CFDataRef unlockKey, CFDataRef scBlob); +OSStatus TokenLoginUpdateUnlockData(CFDictionaryRef context); +OSStatus TokenLoginStoreUnlockData(CFDictionaryRef context, CFDictionaryRef loginData); +OSStatus TokenLoginDeleteUnlockData(CFDataRef pubKeyHash); + +OSStatus TokenLoginGetUnlockKey(CFDictionaryRef context, CFDataRef *unlockKey); +OSStatus TokenLoginGetScBlob(CFDataRef pubKeyHash, CFStringRef tokenId, CFStringRef password, CFDataRef *scBlob); +OSStatus TokenLoginUnlockKeybag(CFDictionaryRef context, CFDictionaryRef loginData); + +#ifdef __cplusplus +} +#endif + +#endif /* TokenLogin_h */ diff --git a/OSX/libsecurity_keychain/lib/Trust.cpp b/OSX/libsecurity_keychain/lib/Trust.cpp index 45a28a49..a10e0528 100644 --- a/OSX/libsecurity_keychain/lib/Trust.cpp +++ b/OSX/libsecurity_keychain/lib/Trust.cpp @@ -96,6 +96,21 @@ TrustKeychains::TrustKeychains() : mRootStoreHandle = (*mRootStore)->database()->handle(); } +TrustKeychains::~TrustKeychains() { + if(mRootStoreDL) { + delete mRootStoreDL; + mRootStoreDL = NULL; + } + if(mRootStoreDb) { + delete mRootStoreDb; + mRootStoreDb = NULL; + } + if(mRootStore) { + delete mRootStore; + mRootStore = NULL; + } +} + RecursiveMutex& SecTrustKeychainsGetMutex() { return trustKeychainsMutex(); @@ -223,11 +238,11 @@ void Trust::evaluate(bool disableEV) } CFArrayRef filteredCerts = NULL; if (isEVCandidate) { - secdebug("evTrust", "Trust::evaluate() certificate is EV candidate"); + secinfo("evTrust", "Trust::evaluate() certificate is EV candidate"); filteredCerts = potentialEVChainWithCertificates(mCerts); mCerts = filteredCerts; } else { - secdebug("evTrust", "Trust::evaluate() performing standard evaluation"); + secinfo("evTrust", "Trust::evaluate() performing standard evaluation"); if (mCerts) { filteredCerts = CFArrayCreateMutableCopy(NULL, 0, mCerts); } @@ -247,7 +262,7 @@ void Trust::evaluate(bool disableEV) if (mAllowedAnchors) { - secdebug("trusteval", "Trust::evaluate: anchors: %ld", CFArrayGetCount(mAllowedAnchors)); + secinfo("trusteval", "Trust::evaluate: anchors: %ld", CFArrayGetCount(mAllowedAnchors)); #if !defined(NDEBUG) CFArrayApplyFunction(mAllowedAnchors, CFRangeMake(0, CFArrayGetCount(mAllowedAnchors)), showCertSKID, NULL); #endif @@ -328,7 +343,7 @@ void Trust::evaluate(bool disableEV) allPolicies = convertRevocationPolicy(numRevocationAdded, context.allocator); if (allPolicies) { // caller has explicitly set the revocation policy they want to use - secdebug("evTrust", "Trust::evaluate() using explicit revocation policy (%d)", + secinfo("evTrust", "Trust::evaluate() using explicit revocation policy (%d)", numRevocationAdded); if (numRevocationAdded == 0) isEVCandidate = false; @@ -337,13 +352,13 @@ void Trust::evaluate(bool disableEV) // caller explicitly provided empty anchors and no keychain list, // and did not explicitly specify the revocation policy; // override global revocation check setting for this evaluation - secdebug("evTrust", "Trust::evaluate() has empty anchors and no keychains"); + secinfo("evTrust", "Trust::evaluate() has empty anchors and no keychains"); allPolicies = NULL; // use only mPolicies isEVCandidate = false; } else if (isEVCandidate || requirePerCert) { // force revocation checking for this evaluation - secdebug("evTrust", "Trust::evaluate() forcing OCSP/CRL revocation check"); + secinfo("evTrust", "Trust::evaluate() forcing OCSP/CRL revocation check"); allPolicies = forceRevocationPolicies(true, requirePerCert, numRevocationAdded, context.allocator, requirePerCert); } @@ -354,7 +369,7 @@ void Trust::evaluate(bool disableEV) } if (allPolicies == NULL) { // use mPolicies; no revocation checking will be performed - secdebug("evTrust", "Trust::evaluate() will not perform revocation check"); + secinfo("evTrust", "Trust::evaluate() will not perform revocation check"); CFIndex numPolicies = CFArrayGetCount(mPolicies); CFAllocatorRef allocator = CFGetAllocator(mPolicies); allPolicies = CFArrayCreateMutableCopy(allocator, numPolicies, mPolicies); @@ -375,14 +390,14 @@ void Trust::evaluate(bool disableEV) // no anchor certificates were provided; // built-in anchors will be trusted unless explicitly disabled. mUsingTrustSettings = (mAnchorPolicy < useAnchorsOnly); - secdebug("userTrust", "Trust::evaluate() %s", + secinfo("userTrust", "Trust::evaluate() %s", (mUsingTrustSettings) ? "using UserTrust" : "has no trusted anchors!"); } else { // anchor certificates were provided; // built-in anchors will NOT also be trusted unless explicitly enabled. mUsingTrustSettings = (mAnchorPolicy == useAnchorsAndBuiltIns); - secdebug("userTrust", "Trust::evaluate() using %s %s anchors", + secinfo("userTrust", "Trust::evaluate() using %s %s anchors", (mUsingTrustSettings) ? "UserTrust AND" : "only", (isEVCandidate) ? "EV" : "caller"); context.anchors(roots, roots); @@ -465,7 +480,7 @@ void Trust::evaluate(bool disableEV) mTpReturn = errSecSuccess; } catch (CommonError &err) { mTpReturn = err.osStatus(); - secdebug("trusteval", "certGroupVerify exception: %d", (int)mTpReturn); + secinfo("trusteval", "certGroupVerify exception: %d", (int)mTpReturn); } mResult = diagnoseOutcome(); @@ -480,7 +495,7 @@ void Trust::evaluate(bool disableEV) mTpResult[2].as(), anchors); } else { // unexpected evidence information. Can't use it - secdebug("trusteval", "unexpected evidence ignored"); + secinfo("trusteval", "unexpected evidence ignored"); } /* do post-processing for the evaluated certificate chain */ @@ -623,7 +638,7 @@ void Trust::evaluateUserTrust(const CertGroup &chain, if (info.recordId()) { Keychain keychain = keychainByDLDb(info.DlDbHandle); DbUniqueRecord uniqueId(keychain->database()->newDbUniqueRecord()); - secdebug("trusteval", "evidence %lu from keychain \"%s\"", (unsigned long)n, keychain->name()); + secinfo("trusteval", "evidence %lu from keychain \"%s\"", (unsigned long)n, keychain->name()); *static_cast(uniqueId) = info.UniqueRecord; uniqueId->activate(); // transfers ownership Item ii = keychain->item(CSSM_DL_DB_RECORD_X509_CERTIFICATE, uniqueId); @@ -633,20 +648,20 @@ void Trust::evaluateUserTrust(const CertGroup &chain, } mCertChain[n] = cert; } else if (info.status(CSSM_CERT_STATUS_IS_IN_INPUT_CERTS)) { - secdebug("trusteval", "evidence %lu from input cert %lu", (unsigned long)n, (unsigned long)info.index()); + secinfo("trusteval", "evidence %lu from input cert %lu", (unsigned long)n, (unsigned long)info.index()); assert(info.index() < uint32(CFArrayGetCount(mCerts))); SecCertificateRef cert = SecCertificateRef(CFArrayGetValueAtIndex(mCerts, info.index())); mCertChain[n] = Certificate::required(cert); } else if (info.status(CSSM_CERT_STATUS_IS_IN_ANCHORS)) { - secdebug("trusteval", "evidence %lu from anchor cert %lu", (unsigned long)n, (unsigned long)info.index()); + secinfo("trusteval", "evidence %lu from anchor cert %lu", (unsigned long)n, (unsigned long)info.index()); assert(info.index() < uint32(CFArrayGetCount(anchors))); SecCertificateRef cert = SecCertificateRef(CFArrayGetValueAtIndex(anchors, info.index())); mCertChain[n] = Certificate::required(cert); } else { // unknown source; make a new Certificate for it - secdebug("trusteval", "evidence %lu from unknown source", (unsigned long)n); + secinfo("trusteval", "evidence %lu from unknown source", (unsigned long)n); mCertChain[n] = new Certificate(chain.blobCerts()[n], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER); @@ -665,7 +680,7 @@ void Trust::evaluateUserTrust(const CertGroup &chain, continue; } mResult = store.find(mCertChain[mResultIndex], policy, searchLibs()); - secdebug("trusteval", "trustResult=%d from cert %d", (int)mResult, (int)mResultIndex); + secinfo("trusteval", "trustResult=%d from cert %d", (int)mResult, (int)mResultIndex); } } @@ -698,12 +713,12 @@ void Trust::releaseTPEvidence(TPVerifyResult &result, Allocator &allocator) allocator.free(evidence[n].StatusCodes); allocator.free(result[2].data()); // array of (flat) info structs } else { - secdebug("trusteval", "unrecognized Apple TP evidence format"); + secinfo("trusteval", "unrecognized Apple TP evidence format"); // drop it -- better leak than kill } } else { // unknown format -- blindly assume flat blobs - secdebug("trusteval", "destroying unknown TP evidence format"); + secinfo("trusteval", "destroying unknown TP evidence format"); for (uint32 n = 0; n < result.count(); n++) { allocator.free(result[n].data()); @@ -724,6 +739,7 @@ void Trust::clearResults() if (mResult != kSecTrustResultInvalid) { releaseTPEvidence(mTpResult, mTP.allocator()); mResult = kSecTrustResultInvalid; + mExtendedResult = NULL; } } diff --git a/OSX/libsecurity_keychain/lib/Trust.h b/OSX/libsecurity_keychain/lib/Trust.h index 3ebdf780..db05aea2 100644 --- a/OSX/libsecurity_keychain/lib/Trust.h +++ b/OSX/libsecurity_keychain/lib/Trust.h @@ -194,7 +194,7 @@ class TrustKeychains { public: TrustKeychains(); - ~TrustKeychains() {} + ~TrustKeychains(); CSSM_DL_DB_HANDLE rootStoreHandle() { return mRootStoreHandle; } CSSM_DL_DB_HANDLE systemKcHandle() { return mSystem ? mSystem->database()->handle() : nullCSSMDLDBHandle; } Keychain &systemKc() { return mSystem; } diff --git a/OSX/libsecurity_keychain/lib/TrustAdditions.cpp b/OSX/libsecurity_keychain/lib/TrustAdditions.cpp index a5b3da47..a79bfaff 100644 --- a/OSX/libsecurity_keychain/lib/TrustAdditions.cpp +++ b/OSX/libsecurity_keychain/lib/TrustAdditions.cpp @@ -1,15 +1,15 @@ /* - * Copyright (c) 2002-2009,2011-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2002-2009,2011-2015 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@ */ @@ -65,7 +65,7 @@ #ifdef NDEBUG /* this actually compiles to nothing */ -#define trustDebug(args...) secdebug("trust", ## args) +#define trustDebug(args...) secinfo("trust", ## args) #else #define trustDebug(args...) printf(args) #endif @@ -334,7 +334,7 @@ CFArrayRef potentialEVChainWithCertificates(CFArrayRef certificates) // intermediate from the returned certificate array. CFIndex chainIndex, chainLen = (certificates) ? CFArrayGetCount(certificates) : 0; - secdebug("trusteval", "potentialEVChainWithCertificates: chainLen: %ld", chainLen); + secinfo("trusteval", "potentialEVChainWithCertificates: chainLen: %ld", chainLen); if (chainLen < 2) { if (certificates) { CFRetain(certificates); @@ -346,24 +346,24 @@ CFArrayRef potentialEVChainWithCertificates(CFArrayRef certificates) for (chainIndex = 0; chainIndex < chainLen; chainIndex++) { SecCertificateRef aCert = (SecCertificateRef) CFArrayGetValueAtIndex(certificates, chainIndex); SecCertificateRef replacementCert = NULL; - secdebug("trusteval", "potentialEVChainWithCertificates: examining chainIndex: %ld", chainIndex); + secinfo("trusteval", "potentialEVChainWithCertificates: examining chainIndex: %ld", chainIndex); if (chainIndex > 0) { // if this is not the leaf, then look for a possible replacement root to end the chain // Try lookup using Subject Key ID first replacementCert = _rootCertificateWithSubjectKeyIDOfCertificate(aCert); if (!replacementCert) { - secdebug("trusteval", " not found using SKID, try by subject"); + secinfo("trusteval", " not found using SKID, try by subject"); replacementCert = _rootCertificateWithSubjectOfCertificate(aCert); } } if (!replacementCert) { - secdebug("trusteval", " No replacement found using SKID or subject; keeping original intermediate"); + secinfo("trusteval", " No replacement found using SKID or subject; keeping original intermediate"); CFArrayAppendValue(certArray, aCert); } SafeCFRelease(&replacementCert); } - secdebug("trusteval", "potentialEVChainWithCertificates: exit: new chainLen: %ld", CFArrayGetCount(certArray)); + secinfo("trusteval", "potentialEVChainWithCertificates: exit: new chainLen: %ld", CFArrayGetCount(certArray)); #if !defined(NDEBUG) CFArrayApplyFunction(certArray, CFRangeMake(0, CFArrayGetCount(certArray)), showCertSKID, NULL); #endif @@ -496,7 +496,7 @@ static void logSKID(const char *msg, const CssmData &subjectKeyID) sprintf(bytes, "%02X", px[ix]); strcat(buffer, bytes); } - secdebug("trusteval", " SKID: %s",buffer); + secinfo("trusteval", " SKID: %s",buffer); } } @@ -572,7 +572,7 @@ CFArrayRef _possibleRootCertificatesForOidString(CFStringRef oidString) CFMutableArrayRef possibleRootCertificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFIndex hashCount = CFArrayGetCount(possibleCertificateHashes); - secdebug("evTrust", "_possibleRootCertificatesForOidString: %d possible hashes", (int)hashCount); + secinfo("evTrust", "_possibleRootCertificatesForOidString: %d possible hashes", (int)hashCount); OSStatus status = errSecSuccess; SecKeychainSearchRef searchRef = NULL; @@ -677,7 +677,7 @@ CFArrayRef _allowedRootCertificatesForOidString(CFStringRef oidString) &foundAny); /* foundAnyEntry */ if (status == errSecSuccess) { - secdebug("evTrust", "_allowedRootCertificatesForOidString: cert %lu has result %d from domain %d", + secinfo("evTrust", "_allowedRootCertificatesForOidString: cert %lu has result %d from domain %d", idx, (int)result, (int)foundDomain); // Root certificates must be trusted by the system (and not have // any explicit trust overrides) to be allowed for EV use. @@ -686,7 +686,7 @@ CFArrayRef _allowedRootCertificatesForOidString(CFStringRef oidString) CFArrayAppendValue(allowedRootCertificates, cert); } } else { - secdebug("evTrust", "_allowedRootCertificatesForOidString: cert %lu SecTrustSettingsEvaluateCert error %d", + secinfo("evTrust", "_allowedRootCertificatesForOidString: cert %lu SecTrustSettingsEvaluateCert error %d", idx, (int)status); } if (errors) { @@ -916,7 +916,7 @@ CFArrayRef allowedEVRootsForLeafCertificate(CFArrayRef certificates) // Fetch the allowed root CA certificates for this OID, if any CFArrayRef allowedRoots = (oidString) ? _allowedRootCertificatesForOidString(oidString) : NULL; CFIndex rootCount = (allowedRoots) ? CFArrayGetCount(allowedRoots) : 0; - secdebug("evTrust", "allowedEVRootsForLeafCertificate: found %d allowed roots", (int)rootCount); + secinfo("evTrust", "allowedEVRootsForLeafCertificate: found %d allowed roots", (int)rootCount); SafeCFRelease(&oidString); if (!allowedRoots || !rootCount) { SafeCFRelease(&allowedRoots); @@ -1021,7 +1021,7 @@ CFDictionaryRef extendedValidationResults(CFArrayRef certChain, SecTrustResultTy // check leaf certificate for wildcard names if (hasWildcardDNSName((SecCertificateRef) CFArrayGetValueAtIndex(certChain, 0))) { - trustDebug("has wildcard name (does not meet EV criteria)"); + trustDebug("has wildcard name (does not meet EV criteria)\n"); return NULL; } @@ -1073,7 +1073,7 @@ CFDictionaryRef extendedValidationResults(CFArrayRef certChain, SecTrustResultTy CFMutableDictionaryRef resultDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(resultDict, kSecEVOrganizationName, organizationName); - trustDebug("[EV] extended validation succeeded"); + trustDebug("[EV] extended validation succeeded\n"); SafeCFRelease(&organizationName); return resultDict; } @@ -1123,10 +1123,10 @@ static CFDictionaryRef _evCAOidDict() static CFDictionaryRef s_evCAOidDict = NULL; if (s_evCAOidDict) { CFRetain(s_evCAOidDict); - secdebug("evTrust", "_evCAOidDict: returning static instance (rc=%d)", (int)CFGetRetainCount(s_evCAOidDict)); + secinfo("evTrust", "_evCAOidDict: returning static instance (rc=%d)", (int)CFGetRetainCount(s_evCAOidDict)); return s_evCAOidDict; } - secdebug("evTrust", "_evCAOidDict: initializing static instance"); + secinfo("evTrust", "_evCAOidDict: initializing static instance"); s_evCAOidDict = dictionaryWithContentsOfPlistFile(EV_ROOTS_PLIST_SYSTEM_PATH); if (!s_evCAOidDict) @@ -1142,14 +1142,14 @@ static CFDictionaryRef _evCAOidDict() CFDataRef hashData = CFDataCreate(NULL, hashBytes, sizeof(hashBytes)); CFIndex hashCount = CFArrayGetCount(hashes); if (hashData && CFArrayContainsValue(hashes, CFRangeMake(0, hashCount), hashData)) { - secdebug("evTrust", "_evCAOidDict: added hardcoded hash value"); + secinfo("evTrust", "_evCAOidDict: added hardcoded hash value"); CFArrayAppendValue(hashes, hashData); } SafeCFRelease(&hashData); } #endif CFRetain(s_evCAOidDict); - secdebug("evTrust", "_evCAOidDict: returning static instance (rc=%d)", (int)CFGetRetainCount(s_evCAOidDict)); + secinfo("evTrust", "_evCAOidDict: returning static instance (rc=%d)", (int)CFGetRetainCount(s_evCAOidDict)); return s_evCAOidDict; } @@ -1190,7 +1190,7 @@ static CFStringRef _decimalStringForOid(CSSM_OID_PTR oid) char *nameBuf = (char *)malloc(bufLen); if (!CFStringGetCString(str, nameBuf, bufLen-1, kCFStringEncodingUTF8)) nameBuf[0]=0; - secdebug("evTrust", "_decimalStringForOid: \"%s\"", nameBuf); + secinfo("evTrust", "_decimalStringForOid: \"%s\"", nameBuf); free(nameBuf); #endif @@ -1217,13 +1217,13 @@ static CFStringRef _oidStringForCertificatePolicies(const CE_CertPolicies *certP // in an intermediate CA.) if (!certPolicies) { - secdebug("evTrust", "oidStringForCertificatePolicies: missing certPolicies!"); + secinfo("evTrust", "oidStringForCertificatePolicies: missing certPolicies!"); return NULL; } CFDictionaryRef evOidDict = _evCAOidDict(); if (!evOidDict) { - secdebug("evTrust", "oidStringForCertificatePolicies: nil OID dictionary!"); + secinfo("evTrust", "oidStringForCertificatePolicies: nil OID dictionary!"); return NULL; } diff --git a/OSX/libsecurity_keychain/lib/TrustItem.cpp b/OSX/libsecurity_keychain/lib/TrustItem.cpp index 4c2e3632..ac8567ff 100644 --- a/OSX/libsecurity_keychain/lib/TrustItem.cpp +++ b/OSX/libsecurity_keychain/lib/TrustItem.cpp @@ -47,7 +47,7 @@ UserTrustItem::UserTrustItem(Certificate *cert, Policy *policy, const TrustData reinterpret_cast(&trustData)), mCertificate(cert), mPolicy(policy) { - secdebug("usertrust", "%p create(%p,%p) = %d", + secinfo("usertrust", "%p create(%p,%p) = %d", this, cert, policy, SecTrustUserSetting(trustData.trust)); } @@ -57,7 +57,7 @@ UserTrustItem::UserTrustItem(Certificate *cert, Policy *policy, const TrustData // UserTrustItem::~UserTrustItem() { - secdebug("usertrust", "%p destroyed", this); + secinfo("usertrust", "%p destroyed", this); } @@ -94,7 +94,7 @@ PrimaryKey UserTrustItem::add(Keychain &keychain) try { mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); - secdebug("usertrust", "%p inserted", this); + secinfo("usertrust", "%p inserted", this); } catch (const CssmError &e) { @@ -102,7 +102,7 @@ PrimaryKey UserTrustItem::add(Keychain &keychain) throw; // Create the trust relation and try again. - secdebug("usertrust", "adding schema relation for user trusts"); + secinfo("usertrust", "adding schema relation for user trusts"); db->createRelation(CSSM_DL_DB_RECORD_USER_TRUST, "CSSM_DL_DB_RECORD_USER_TRUST", Schema::UserTrustSchemaAttributeCount, Schema::UserTrustSchemaAttributeList, @@ -117,7 +117,7 @@ PrimaryKey UserTrustItem::add(Keychain &keychain) Schema::UserTrustSchemaIndexList); mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); - secdebug("usertrust", "%p inserted now", this); + secinfo("usertrust", "%p inserted now", this); } mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); diff --git a/OSX/libsecurity_keychain/lib/TrustSettings.cpp b/OSX/libsecurity_keychain/lib/TrustSettings.cpp index bcd2d033..4d602799 100644 --- a/OSX/libsecurity_keychain/lib/TrustSettings.cpp +++ b/OSX/libsecurity_keychain/lib/TrustSettings.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -48,11 +49,17 @@ #include #include #include -#include +#include #include +#include -#define trustSettingsDbg(args...) secdebug("trustSettings", ## args) -#define trustSettingsEvalDbg(args...) secdebug("trustSettingsEval", ## args) +#if 0 +#define trustSettingsDbg(args...) syslog(LOG_ERR, ## args) +#define trustSettingsEvalDbg(args...) syslog(LOG_ERR, ## args) +#else +#define trustSettingsDbg(args...) secinfo("trustSettings", ## args) +#define trustSettingsEvalDbg(args...) secinfo("trustSettingsEval", ## args) +#endif /* * Common error return for "malformed TrustSettings record" @@ -108,7 +115,7 @@ static bool tsCheckApp( OSStatus ortn; ortn = SecTrustedApplicationCreateWithExternalRepresentation(certApp, &appRef); if(ortn) { - trustSettingsDbg("tsCheckApp: bad trustedApp data\n"); + trustSettingsDbg("tsCheckApp: bad trustedApp data"); return false; } ortn = SecTrustedApplicationValidateWithPath(appRef, NULL); @@ -803,17 +810,23 @@ void TrustSettings::findQualifiedCerts( KCCursor cursor(keychains, CSSM_DL_DB_RECORD_X509_CERTIFICATE, NULL); Item certItem; bool found; + unsigned int total=0, entries=0, qualified=0; do { found = cursor->next(certItem); if(!found) { break; } + ++total; #if !SECTRUST_OSX CFRef certRef((SecCertificateRef)certItem->handle()); #else /* must convert to unified SecCertificateRef */ SecPointer certificate(static_cast(&*certItem)); - CssmData certCssmData = certificate->data(); + CssmData certCssmData; + try { + certCssmData = certificate->data(); + } + catch (...) {} if (!(certCssmData.Data && certCssmData.Length)) { continue; } @@ -826,6 +839,7 @@ void TrustSettings::findQualifiedCerts( if(certDict == NULL) { continue; } + ++entries; if(!findAll) { /* qualify */ @@ -834,6 +848,7 @@ void TrustSettings::findQualifiedCerts( continue; } } + ++qualified; /* see if we already have this one - get in CFData form */ CSSM_DATA certData; @@ -843,7 +858,7 @@ void TrustSettings::findQualifiedCerts( continue; } CFRef cfData(CFDataCreate(NULL, certData.Data, certData.Length)); - CFDataRef cfd = cfData; + CFDataRef cfd = cfData.get(); if(CFSetContainsValue(certSet, cfd)) { trustSettingsEvalDbg("findQualifiedCerts: dup cert"); continue; @@ -855,6 +870,9 @@ void TrustSettings::findQualifiedCerts( CFArrayAppendValue(certArray, certRef); } } while(found); + + trustSettingsEvalDbg("findQualifiedCerts: examined %d certs, qualified %d of %d", + total, qualified, entries); } /* @@ -893,7 +911,8 @@ CFArrayRef TrustSettings::copyTrustSettings( /* already validated... */ assert(CFGetTypeID(diskTsDict) == CFDictionaryGetTypeID()); - CFDataRef certPolicy = (CFDataRef) CFDictionaryGetValue(diskTsDict, kSecTrustSettingsPolicy); + CFTypeRef certPolicy = (CFTypeRef) CFDictionaryGetValue(diskTsDict, kSecTrustSettingsPolicy); + CFStringRef policyName = (CFStringRef)CFDictionaryGetValue(diskTsDict, kSecTrustSettingsPolicyName); CFDataRef certApp = (CFDataRef) CFDictionaryGetValue(diskTsDict, kSecTrustSettingsApplication); CFStringRef policyStr = (CFStringRef)CFDictionaryGetValue(diskTsDict, kSecTrustSettingsPolicyString); CFNumberRef allowedErr = (CFNumberRef)CFDictionaryGetValue(diskTsDict, kSecTrustSettingsAllowedError); @@ -915,17 +934,33 @@ CFArrayRef TrustSettings::copyTrustSettings( &kCFTypeDictionaryValueCallBacks)); if(certPolicy != NULL) { - /* convert OID as CFDataRef to SecPolicyRef */ SecPolicyRef policyRef = NULL; - CSSM_OID policyOid = { CFDataGetLength(certPolicy), - (uint8 *)CFDataGetBytePtr(certPolicy) }; - OSStatus ortn = SecPolicyCopy(CSSM_CERT_X_509v3, &policyOid, &policyRef); - if(ortn) { - trustSettingsDbg("copyTrustSettings: OID conversion error"); - abort("Bad Policy OID in trusted root list", errSecInvalidTrustedRootRecord); + if (CFDataGetTypeID() == CFGetTypeID(certPolicy)) { + /* convert OID as CFDataRef to SecPolicyRef */ + CSSM_OID policyOid = { CFDataGetLength((CFDataRef)certPolicy), + (uint8 *)CFDataGetBytePtr((CFDataRef)certPolicy) }; + OSStatus ortn = SecPolicyCopy(CSSM_CERT_X_509v3, &policyOid, &policyRef); + if(ortn) { + trustSettingsDbg("copyTrustSettings: OID conversion error"); + abort("Bad Policy OID in trusted root list", errSecInvalidTrustedRootRecord); + } + } else if (CFStringGetTypeID() == CFGetTypeID(certPolicy)) { + policyRef = SecPolicyCreateWithProperties(certPolicy, NULL); } - CFDictionaryAddValue(outTsDict, kSecTrustSettingsPolicy, policyRef); - CFRelease(policyRef); // owned by dictionary + if (policyRef) { + CFDictionaryAddValue(outTsDict, kSecTrustSettingsPolicy, policyRef); + CFRelease(policyRef); // owned by dictionary + } + } + + if (policyName != NULL) { + /* + * copy, since policyName is in our mutable dictionary and could change out from + * under the caller + */ + CFStringRef str = CFStringCreateCopy(NULL, policyName); + CFDictionaryAddValue(outTsDict, kSecTrustSettingsPolicyName, str); + CFRelease(str); // owned by dictionary } if(certApp != NULL) { @@ -1135,7 +1170,7 @@ CFDictionaryRef TrustSettings::findDictionaryForCert( return NULL; } - return findDictionaryForCertHash(static_cast(certHashStr)); + return findDictionaryForCertHash(static_cast(certHashStr.get())); } /* @@ -1163,15 +1198,11 @@ CFArrayRef TrustSettings::validateApiTrustSettings( CFArrayRef tmpInArray = NULL; if(trustSettingsDictOrArray == NULL) { -#if SECTRUST_OSX -#warning STU: temporarily unblocking build -#else /* trivial case, only valid for roots */ if(!isSelfSigned) { trustSettingsDbg("validateApiUsageConstraints: !isSelfSigned, no settings"); MacOSError::throwMe(errSecParam); } -#endif return CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks); } else if(CFGetTypeID(trustSettingsDictOrArray) == CFDictionaryGetTypeID()) { @@ -1198,7 +1229,8 @@ CFArrayRef TrustSettings::validateApiTrustSettings( /* convert */ for(CFIndex dex=0; dexcopyTo(location); // add cert to the trust item's keychain } catch (...) { - secdebug("trusteval", "failed to add certificate %p to keychain \"%s\"", + secinfo("trusteval", "failed to add certificate %p to keychain \"%s\"", cert, location->name()); try { if (&*location != &*defaultKeychain) cert->copyTo(defaultKeychain); // try the default (if it's not the same) } catch (...) { // unable to add the certificate - secdebug("trusteval", "failed to add certificate %p to keychain \"%s\"", + secinfo("trusteval", "failed to add certificate %p to keychain \"%s\"", cert, defaultKeychain->name()); } } @@ -138,14 +138,14 @@ void TrustStore::assign(Certificate *cert, Policy *policy, SecTrustUserSetting t try { cert->copyTo(trustLocation); // add cert to the trust item's keychain } catch (...) { - secdebug("trusteval", "failed to add certificate %p to keychain \"%s\"", + secinfo("trusteval", "failed to add certificate %p to keychain \"%s\"", cert, trustLocation->name()); try { if (&*trustLocation != &*defaultKeychain) cert->copyTo(defaultKeychain); // try the default (if it's not the same) } catch (...) { // unable to add the certificate - secdebug("trusteval", "failed to add certificate %p to keychain \"%s\"", + secinfo("trusteval", "failed to add certificate %p to keychain \"%s\"", cert, defaultKeychain->name()); } } @@ -170,6 +170,7 @@ Item TrustStore::findItem(Certificate *cert, Policy *policy, // we no longer need or want to look for them anymore. return ((ItemImpl*)NULL); +#if 0 StLock _(mMutex); try { @@ -192,6 +193,7 @@ Item TrustStore::findItem(Certificate *cert, Policy *policy, catch (const CommonError &error) {} return ((ItemImpl*)NULL); // no trust schema, no records, no error +#endif } void TrustStore::getCssmRootCertificates(CertGroup &rootCerts) @@ -252,7 +254,7 @@ void TrustStore::loadRootCertificates() base += certData.Length; } - secdebug("anchors", "%ld anchors loaded", (long)numCerts); + secinfo("anchors", "%ld anchors loaded", (long)numCerts); mRootsValid = true; // ready to roll } diff --git a/OSX/libsecurity_keychain/lib/TrustedApplication.cpp b/OSX/libsecurity_keychain/lib/TrustedApplication.cpp index 977eba37..a07da4f1 100644 --- a/OSX/libsecurity_keychain/lib/TrustedApplication.cpp +++ b/OSX/libsecurity_keychain/lib/TrustedApplication.cpp @@ -44,7 +44,7 @@ TrustedApplication::TrustedApplication(const TypedList &subject) try { CodeSignatureAclSubject::Maker maker; mForm = maker.make(subject); - secdebug("trustedapp", "%p created from list form", this); + secinfo("trustedapp", "%p created from list form", this); IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from list")); } catch (...) { throw ACL::ParseError(); @@ -59,7 +59,7 @@ TrustedApplication::TrustedApplication(const std::string &path) { RefPointer code(OSXCode::at(path)); mForm = new CodeSignatureAclSubject(OSXVerifier(code)); - secdebug("trustedapp", "%p created from path %s", this, path.c_str()); + secinfo("trustedapp", "%p created from path %s", this, path.c_str()); IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from path")); } @@ -72,7 +72,7 @@ TrustedApplication::TrustedApplication() //@@@@ should use CS's idea of "self" RefPointer me(OSXCode::main()); mForm = new CodeSignatureAclSubject(OSXVerifier(me)); - secdebug("trustedapp", "%p created from self", this); + secinfo("trustedapp", "%p created from self", this); IFDUMPING("codesign", mForm->AclSubject::dump("STApp created from self")); } @@ -88,7 +88,7 @@ TrustedApplication::TrustedApplication(const std::string &path, SecRequirementRe MacOSError::check(SecRequirementCopyData(reqRef, kSecCSDefaultFlags, &reqData.aref())); mForm = new CodeSignatureAclSubject(NULL, path); mForm->add((const BlobCore *)CFDataGetBytePtr(reqData)); - secdebug("trustedapp", "%p created from path %s and requirement %p", + secinfo("trustedapp", "%p created from path %s and requirement %p", this, path.c_str(), reqRef); IFDUMPING("codesign", mForm->debugDump()); } @@ -142,7 +142,7 @@ void TrustedApplication::data(CFDataRef data) bool TrustedApplication::verifyToDisk(const char *path) { if (SecRequirementRef requirement = mForm->requirement()) { - secdebug("trustedapp", "%p validating requirement against path %s", this, path); + secinfo("trustedapp", "%p validating requirement against path %s", this, path); CFRef ondisk; if (path) MacOSError::check(SecStaticCodeCreateWithPath(CFTempURL(path), @@ -151,7 +151,7 @@ bool TrustedApplication::verifyToDisk(const char *path) MacOSError::check(SecCodeCopySelf(kSecCSDefaultFlags, (SecCodeRef *)&ondisk.aref())); return SecStaticCodeCheckValidity(ondisk, kSecCSDefaultFlags, requirement) == errSecSuccess; } else { - secdebug("trustedapp", "%p validating hash against path %s", this, path); + secinfo("trustedapp", "%p validating hash against path %s", this, path); RefPointer code = path ? OSXCode::at(path) : OSXCode::main(); SHA1::Digest ondiskDigest; OSXVerifier::makeLegacyHash(code, ondiskDigest); diff --git a/OSX/libsecurity_keychain/lib/UnlockReferralItem.cpp b/OSX/libsecurity_keychain/lib/UnlockReferralItem.cpp index f9b004a3..382ed8f4 100644 --- a/OSX/libsecurity_keychain/lib/UnlockReferralItem.cpp +++ b/OSX/libsecurity_keychain/lib/UnlockReferralItem.cpp @@ -42,7 +42,7 @@ UnlockReferralItem::UnlockReferralItem() : UInt32(0/*size*/), NULL/*data*/) { - secdebug("referral", "create %p", this); + secinfo("referral", "create %p", this); } @@ -51,7 +51,7 @@ UnlockReferralItem::UnlockReferralItem() : // UnlockReferralItem::~UnlockReferralItem() { - secdebug("referral", "destroy %p", this); + secinfo("referral", "destroy %p", this); } @@ -74,7 +74,7 @@ PrimaryKey UnlockReferralItem::add(Keychain &keychain) try { mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); - secdebug("usertrust", "%p inserted", this); + secinfo("usertrust", "%p inserted", this); } catch (const CssmError &e) { @@ -82,7 +82,7 @@ PrimaryKey UnlockReferralItem::add(Keychain &keychain) throw; // Create the referral relation and try again. - secdebug("usertrust", "adding schema relation for user trusts"); + secinfo("usertrust", "adding schema relation for user trusts"); #if 0 db->createRelation(CSSM_DL_DB_RECORD_UNLOCK_REFERRAL, "CSSM_DL_DB_RECORD_UNLOCK_REFERRAL", @@ -101,7 +101,7 @@ PrimaryKey UnlockReferralItem::add(Keychain &keychain) //keychain->resetSchema(); mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); - secdebug("usertrust", "%p inserted now", this); + secinfo("usertrust", "%p inserted now", this); } mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); diff --git a/OSX/libsecurity_keychain/lib/defaultcreds.cpp b/OSX/libsecurity_keychain/lib/defaultcreds.cpp index 5188b0e0..cee6e780 100644 --- a/OSX/libsecurity_keychain/lib/defaultcreds.cpp +++ b/OSX/libsecurity_keychain/lib/defaultcreds.cpp @@ -78,15 +78,15 @@ bool DefaultCredentials::operator () (Db database) keyReferral(**it); break; default: - secdebug("kcreferral", "referral type %lu (to %s) not supported", + secinfo("kcreferral", "referral type %lu (to %s) not supported", (unsigned long)(*it)->type(), (*it)->dbName().c_str()); break; } } } - secdebug("kcreferral", "%lu samples generated", (unsigned long)size()); + secinfo("kcreferral", "%lu samples generated", (unsigned long)size()); } catch (...) { - secdebug("kcreferral", "exception setting default credentials for %s; using standard value", database->name()); + secinfo("kcreferral", "exception setting default credentials for %s; using standard value", database->name()); } mMade = true; } @@ -101,7 +101,7 @@ bool DefaultCredentials::operator () (Db database) // void DefaultCredentials::keyReferral(const UnlockReferralRecord &ref) { - secdebug("kcreferral", "processing type %ld referral to %s", + secinfo("kcreferral", "processing type %ld referral to %s", (long)ref.type(), ref.dbName().c_str()); DLDbIdentifier identifier(ref.dbName().c_str(), ref.dbGuid(), ref.dbSSID(), ref.dbSSType()); @@ -115,12 +115,12 @@ void DefaultCredentials::keyReferral(const UnlockReferralRecord &ref) // try the entire search list (just in case) try { - secdebug("kcreferral", "no joy with %s; trying the entire keychain list for guid %s", + secinfo("kcreferral", "no joy with %s; trying the entire keychain list for guid %s", ref.dbName().c_str(), ref.dbGuid().toString().c_str()); unlockKey(ref, fallbackSearchList(identifier)); return; } catch (...) { } - secdebug("kcreferral", "no luck at all; we'll skip this record"); + secinfo("kcreferral", "no luck at all; we'll skip this record"); } @@ -140,7 +140,7 @@ bool DefaultCredentials::unlockKey(const UnlockReferralRecord &ref, const Keycha Item keyItem; while (cursor->next(keyItem)) { - secdebug("kcreferral", "located source key in %s", keyItem->keychain()->name()); + secinfo("kcreferral", "located source key in %s", keyItem->keychain()->name()); // get a reference to the key in the provider keychain CssmClient::Key key = dynamic_cast(*keyItem).key(); diff --git a/OSX/libsecurity_keychain/lib/security_keychain.exp b/OSX/libsecurity_keychain/lib/security_keychain.exp index e0fcb27d..e2b051de 100644 --- a/OSX/libsecurity_keychain/lib/security_keychain.exp +++ b/OSX/libsecurity_keychain/lib/security_keychain.exp @@ -110,6 +110,7 @@ _kSecAttrHasCustomIcon _kSecAttrCRLType _kSecAttrCRLEncoding _kSecAttrAccessGroup +_kSecAttrAccessGroupToken _kSecAttrSynchronizable _kSecAttrSyncViewHint _kSecMatchPolicy @@ -212,12 +213,12 @@ _kSecPolicyAppleProfileSigner _kSecPolicyAppleQAProfileSigner _kSecPolicyAppleTestMobileStore _kSecPolicyAppleServerAuthentication -_kSecPolicyAppleATVAppSigning -_kSecPolicyAppleTestATVAppSigning _kSecPolicyApplePayIssuerEncryption _kSecPolicyAppleOSXProvisioningProfileSigning _kSecPolicyAppleATVVPNProfileSigning _kSecPolicyAppleAST2DiagnosticsServerAuth +_kSecPolicyAppleEscrowProxyServerAuth +_kSecPolicyAppleFMiPServerAuth _kSecPolicyOid _kSecPolicyName _kSecPolicyClient @@ -406,6 +407,8 @@ _SecCertificateCopyFirstFieldValue _SecCertificateCopyPreference _SecCertificateCopyPreferred _SecCertificateCopyPublicKey +_SecCertificateCopySubjectPublicKeyInfoSHA1Digest +_SecCertificateCopySubjectPublicKeyInfoSHA256Digest _SecCertificateCopySubjectSummary _SecCertificateCopyDNSNames _SecCertificateCreateItemImplInstance @@ -430,7 +433,9 @@ _SecCertificateGetSubject _SecCertificateGetType _SecCertificateGetTypeID _SecCertificateInferLabel +_SecCertificateIsCA _SecCertificateIsSelfSigned +_SecCertificateIsSelfSignedCA _SecCertificateRequestCreate _SecCertificateRequestGetTypeID _SecCertificateRequestSubmit @@ -472,6 +477,8 @@ _SecInferLabelFromX509Name _SecItemAdd _SecItemCopyDisplayNames _SecItemCopyMatching +_SecItemCopyParentCertificates +_SecItemCopyStoredCertificate _SecItemDelete _SecItemUpdate _kSecAttrKeyTypeRSA @@ -484,6 +491,7 @@ _kSecAttrKeyTypeRC2 _kSecAttrKeyTypeCAST _kSecAttrKeyTypeECDSA _kSecAttrKeyTypeEC +_kSecAttrKeyTypeECSECPrimeRandom _kSecAttrPRF _kSecAttrPRFHmacAlgSHA1 _kSecAttrPRFHmacAlgSHA224 @@ -495,7 +503,9 @@ _kSecAttrRounds _SecECKeyGetNamedCurve _SecItemExport _SecItemImport +_SecKeyCopyAttestationKey _SecKeyCreate +_SecKeyCreateAttestation _SecKeyCreatePair _SecKeyCreateWithCSSMKey _SecKeyDecrypt @@ -527,6 +537,7 @@ _SecKeychainAddGenericPassword _SecKeychainAddIToolsPassword _SecKeychainAddInternetPassword _SecKeychainAttributeInfoForItemID +_SecKeychainAttemptMigrationWithMasterKey _SecKeychainChangePassword _SecKeychainCopyAccess _SecKeychainCopyBlob @@ -555,6 +566,7 @@ _SecKeychainGetTypeID _SecKeychainGetUserInteractionAllowed _SecKeychainGetVersion _SecKeychainGetKeychainVersion +_SecKeychainGetUserPromptAttempts _SecKeychainIsValid _SecKeychainMDSInstall _SecKeychainItemAdd @@ -638,8 +650,8 @@ _SecPolicyCreateApplePushService _SecPolicyCreateAppleMMCSService _SecPolicyCreateApplePPQService _SecPolicyCreateAppleAST2Service -_SecPolicyCreateAppleATVAppSigning -_SecPolicyCreateTestAppleATVAppSigning +_SecPolicyCreateAppleEscrowProxyService +_SecPolicyCreateAppleFMiPService _SecPolicyCreateAppleATVVPNProfileSigning _SecPolicyCreateApplePayIssuerEncryption _SecPolicyCreateAppleSSLService @@ -686,6 +698,9 @@ _SecTrustGetTPHandle _SecTrustGetTypeID _SecTrustGetUserTrust _SecTrustGetVerifyTime +_SecTrustLegacySourcesEventRunloopCreate +_SecTrustLegacyCRLFetch +_SecTrustLegacyCRLStatus _SecTrustSetAnchorCertificates _SecTrustSetAnchorCertificatesOnly _SecTrustSetExceptions @@ -768,3 +783,4 @@ _SecFDERecoveryUnwrapCRSKWithPrivKey _SecKeychainSearchCreateForCertificateByIssuerAndSN_CF _SecRandomCopyBytes _SecRandomCopyData +_SecItemUpdateTokenItems diff --git a/OSX/libsecurity_keychain/libDER/Tests/parseTicket.c b/OSX/libsecurity_keychain/libDER/Tests/parseTicket.c index a55cee53..1d707341 100644 --- a/OSX/libsecurity_keychain/libDER/Tests/parseTicket.c +++ b/OSX/libsecurity_keychain/libDER/Tests/parseTicket.c @@ -257,29 +257,6 @@ dumpBytes( const char *title, const unsigned char *data, int len, int nonewline printf("\n"); } -static void -readFile(char *filename, unsigned char **data, unsigned *len) -{ - int size = 0; - FILE *file = NULL; - if ((file = fopen(filename, "r")) == NULL) { - fprintf(stderr, "could not open file=%s", filename); - return; - } - fseek(file, 0, SEEK_END); - size = ftell(file); - *len = size; - *data = (unsigned char*)malloc(*len); - if (!*data) { - fprintf(stderr, "Out of memory"); - fclose(file); - return; - } - rewind(file); - (void)fread(*data, size, 1, file); - fclose(file); -} - static void writeFile( char* filename, unsigned char* buf, int len ) { diff --git a/OSX/libsecurity_keychain/libDER/config/base.xcconfig b/OSX/libsecurity_keychain/libDER/config/base.xcconfig index b6aaf1bc..04320bd9 100644 --- a/OSX/libsecurity_keychain/libDER/config/base.xcconfig +++ b/OSX/libsecurity_keychain/libDER/config/base.xcconfig @@ -5,7 +5,7 @@ CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) VERSIONING_SYSTEM = apple-generic; DEAD_CODE_STRIPPING = YES; -ARCHS = $(ARCHS_STANDARD_32_64_BIT) +ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) // Debug symbols should be on obviously GCC_GENERATE_DEBUGGING_SYMBOLS = YES @@ -14,3 +14,4 @@ STRIP_STYLE = debugging STRIP_INSTALLED_PRODUCT = NO WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_keychain/libDER/config/lib.xcconfig b/OSX/libsecurity_keychain/libDER/config/lib.xcconfig index 18b501cb..18995ac2 100644 --- a/OSX/libsecurity_keychain/libDER/config/lib.xcconfig +++ b/OSX/libsecurity_keychain/libDER/config/lib.xcconfig @@ -7,11 +7,12 @@ CODE_SIGN_IDENTITY = HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) -HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) +HEADER_SEARCH_PATHS[sdk=embedded*] = $(PROJECT_DIR) $(BUILT_PRODUCTS_DIR)/usr/local/include $(inherited) INSTALL_PATH = /usr/local/lib -SKIP_INSTALL[sdk=macosx*] = NO -SKIP_INSTALL[sdk=iphone*] = YES +PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_libDER/libDER + +SKIP_INSTALL = YES ALWAYS_SEARCH_USER_PATHS = NO @@ -29,6 +30,4 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES GCC_WARN_ABOUT_RETURN_TYPE = YES GCC_WARN_UNUSED_VARIABLE = YES -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator - -GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) \ No newline at end of file +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator diff --git a/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj b/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj index f14c162a..ee9390e8 100644 --- a/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj @@ -22,6 +22,31 @@ name = World; productName = World; }; + D46B07A51C8FB22900B5939A /* libDERInstall */ = { + isa = PBXAggregateTarget; + buildConfigurationList = D46B07A81C8FB22900B5939A /* Build configuration list for PBXAggregateTarget "libDERInstall" */; + buildPhases = ( + D46B07AB1C8FB23500B5939A /* Copy Static Library File */, + ); + dependencies = ( + D46B08741C8FC18700B5939A /* PBXTargetDependency */, + D46B07FD1C8FBE1900B5939A /* PBXTargetDependency */, + ); + name = libDERInstall; + productName = libDERInstall; + }; + D46B07EB1C8FBDC600B5939A /* libDERHeaders */ = { + isa = PBXAggregateTarget; + buildConfigurationList = D46B07EC1C8FBDC600B5939A /* Build configuration list for PBXAggregateTarget "libDERHeaders" */; + buildPhases = ( + D46B07EF1C8FBDD700B5939A /* Copy Headers */, + ); + dependencies = ( + D46B07FB1C8FBE0B00B5939A /* PBXTargetDependency */, + ); + name = libDERHeaders; + productName = libDERHeaders; + }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ @@ -46,7 +71,7 @@ 058F15C20922B73F009FA1C5 /* printFields.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F15C00922B73F009FA1C5 /* printFields.h */; }; 058F15C30922B73F009FA1C5 /* printFields.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F15C10922B73F009FA1C5 /* printFields.c */; }; 058F163109250D16009FA1C5 /* oids.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F162D09250D0D009FA1C5 /* oids.c */; }; - 058F163209250D17009FA1C5 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F162E09250D0D009FA1C5 /* oids.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 058F163209250D17009FA1C5 /* oids.h in Headers */ = {isa = PBXBuildFile; fileRef = 058F162E09250D0D009FA1C5 /* oids.h */; }; 058F1659092513A7009FA1C5 /* parseCrl.c in Sources */ = {isa = PBXBuildFile; fileRef = 058F1658092513A7009FA1C5 /* parseCrl.c */; }; 058F16710925230E009FA1C5 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; 058F16720925230F009FA1C5 /* libDERUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA46B091FE63E00A7007A /* libDERUtils.a */; }; @@ -57,6 +82,17 @@ 4C96C8E2113F4232005483E8 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; 4C96C8ED113F42D1005483E8 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C96C8EC113F42C4005483E8 /* libcrypto.dylib */; }; D467903C1B39FDB500D26E2F /* oidsPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = D467903B1B39FDB500D26E2F /* oidsPriv.h */; }; + D46B07EA1C8FBDAF00B5939A /* libDER.a in Copy Static Library File */ = {isa = PBXBuildFile; fileRef = 053BA314091C00BF00A7007A /* libDER.a */; }; + D46B07F01C8FBDFC00B5939A /* DER_Keys.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 058ECD340920F5E30050AA30 /* DER_Keys.h */; }; + D46B07F11C8FBDFC00B5939A /* asn1Types.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 053BA342091C089B00A7007A /* asn1Types.h */; }; + D46B07F21C8FBDFC00B5939A /* DER_CertCrl.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 053BA398091C258100A7007A /* DER_CertCrl.h */; }; + D46B07F31C8FBDFC00B5939A /* DER_Decode.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 053BA321091C02B700A7007A /* DER_Decode.h */; }; + D46B07F41C8FBDFC00B5939A /* DER_Encode.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 0544AE9F0940939C00DD6C0B /* DER_Encode.h */; }; + D46B07F51C8FBDFC00B5939A /* libDER_config.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 053BA322091C02B700A7007A /* libDER_config.h */; }; + D46B07F61C8FBDFC00B5939A /* libDER.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 053BA323091C02B700A7007A /* libDER.h */; }; + D46B07F71C8FBDFC00B5939A /* DER_Digest.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 05E0E40509228A5E005F4693 /* DER_Digest.h */; }; + D46B07F81C8FBDFC00B5939A /* oids.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 058F162E09250D0D009FA1C5 /* oids.h */; }; + D46B07F91C8FBDFC00B5939A /* oidsPriv.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = D467903B1B39FDB500D26E2F /* oidsPriv.h */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -130,8 +166,63 @@ remoteGlobalIDString = 053BA313091C00BF00A7007A; remoteInfo = libDER; }; + D46B07FA1C8FBE0B00B5939A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; + D46B07FC1C8FBE1900B5939A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = D46B07EB1C8FBDC600B5939A; + remoteInfo = libDERHeaders; + }; + D46B08731C8FC18700B5939A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 053BA30A091C00A400A7007A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 053BA313091C00BF00A7007A; + remoteInfo = libDER; + }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + D46B07AB1C8FB23500B5939A /* Copy Static Library File */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/lib; + dstSubfolderSpec = 0; + files = ( + D46B07EA1C8FBDAF00B5939A /* libDER.a in Copy Static Library File */, + ); + name = "Copy Static Library File"; + runOnlyForDeploymentPostprocessing = 1; + }; + D46B07EF1C8FBDD700B5939A /* Copy Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/local/include/security_libDER/libDER; + dstSubfolderSpec = 0; + files = ( + D46B07F01C8FBDFC00B5939A /* DER_Keys.h in Copy Headers */, + D46B07F11C8FBDFC00B5939A /* asn1Types.h in Copy Headers */, + D46B07F21C8FBDFC00B5939A /* DER_CertCrl.h in Copy Headers */, + D46B07F31C8FBDFC00B5939A /* DER_Decode.h in Copy Headers */, + D46B07F41C8FBDFC00B5939A /* DER_Encode.h in Copy Headers */, + D46B07F51C8FBDFC00B5939A /* libDER_config.h in Copy Headers */, + D46B07F61C8FBDFC00B5939A /* libDER.h in Copy Headers */, + D46B07F71C8FBDFC00B5939A /* DER_Digest.h in Copy Headers */, + D46B07F81C8FBDFC00B5939A /* oids.h in Copy Headers */, + D46B07F91C8FBDFC00B5939A /* oidsPriv.h in Copy Headers */, + ); + name = "Copy Headers"; + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 053BA314091C00BF00A7007A /* libDER.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDER.a; sourceTree = BUILT_PRODUCTS_DIR; }; 053BA321091C02B700A7007A /* DER_Decode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DER_Decode.h; sourceTree = ""; }; @@ -317,16 +408,16 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 053BA325091C02B700A7007A /* libDER_config.h in Headers */, D467903C1B39FDB500D26E2F /* oidsPriv.h in Headers */, 053BA326091C02B700A7007A /* libDER.h in Headers */, - 053BA325091C02B700A7007A /* libDER_config.h in Headers */, - 058F163209250D17009FA1C5 /* oids.h in Headers */, 053BA324091C02B700A7007A /* DER_Decode.h in Headers */, - 053BA344091C089B00A7007A /* asn1Types.h in Headers */, 053BA39A091C258100A7007A /* DER_CertCrl.h in Headers */, - 058ECD360920F5E30050AA30 /* DER_Keys.h in Headers */, 05E0E40709228A5E005F4693 /* DER_Digest.h in Headers */, 0544AEA10940939C00DD6C0B /* DER_Encode.h in Headers */, + 058ECD360920F5E30050AA30 /* DER_Keys.h in Headers */, + 058F163209250D17009FA1C5 /* oids.h in Headers */, + 053BA344091C089B00A7007A /* asn1Types.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -436,7 +527,15 @@ 053BA30A091C00A400A7007A /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; + TargetAttributes = { + D46B07A51C8FB22900B5939A = { + CreatedOnToolsVersion = 7.3; + }; + D46B07EB1C8FBDC600B5939A = { + CreatedOnToolsVersion = 7.3; + }; + }; }; buildConfigurationList = 4CD81A7109BE1FD2000A9641 /* Build configuration list for PBXProject "libDER" */; compatibilityVersion = "Xcode 3.2"; @@ -454,6 +553,8 @@ projectRoot = ""; targets = ( 053BA30F091C00B100A7007A /* World */, + D46B07A51C8FB22900B5939A /* libDERInstall */, + D46B07EB1C8FBDC600B5939A /* libDERHeaders */, 053BA313091C00BF00A7007A /* libDER */, 053BA444091FE58C00A7007A /* parseCert */, 053BA46A091FE63E00A7007A /* libDERUtils */, @@ -565,6 +666,21 @@ target = 053BA313091C00BF00A7007A /* libDER */; targetProxy = 4C96C8E0113F4223005483E8 /* PBXContainerItemProxy */; }; + D46B07FB1C8FBE0B00B5939A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA313091C00BF00A7007A /* libDER */; + targetProxy = D46B07FA1C8FBE0B00B5939A /* PBXContainerItemProxy */; + }; + D46B07FD1C8FBE1900B5939A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D46B07EB1C8FBDC600B5939A /* libDERHeaders */; + targetProxy = D46B07FC1C8FBE1900B5939A /* PBXContainerItemProxy */; + }; + D46B08741C8FC18700B5939A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 053BA313091C00BF00A7007A /* libDER */; + targetProxy = D46B08731C8FC18700B5939A /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -587,7 +703,6 @@ baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - SDKROOT = macosx.internal; }; name = Debug; }; @@ -596,7 +711,6 @@ baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; - SDKROOT = macosx.internal; }; name = Release; }; @@ -605,6 +719,7 @@ baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + SDKROOT = macosx.internal; }; name = Debug; }; @@ -613,6 +728,7 @@ baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + SDKROOT = macosx.internal; }; name = Release; }; @@ -664,6 +780,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1828EAA214E334E200BE00C2 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -673,9 +790,12 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx.internal; }; @@ -685,6 +805,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1828EAA214E334E200BE00C2 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; CLANG_STATIC_ANALYZER_MODE = deep; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -694,6 +815,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; @@ -702,6 +824,34 @@ }; name = Release; }; + D46B07A61C8FB22900B5939A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D46B07A71C8FB22900B5939A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + D46B07ED1C8FBDC600B5939A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D46B07EE1C8FBDC600B5939A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -768,6 +918,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D46B07A81C8FB22900B5939A /* Build configuration list for PBXAggregateTarget "libDERInstall" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D46B07A61C8FB22900B5939A /* Debug */, + D46B07A71C8FB22900B5939A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D46B07EC1C8FBDC600B5939A /* Build configuration list for PBXAggregateTarget "libDERHeaders" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D46B07ED1C8FBDC600B5939A /* Debug */, + D46B07EE1C8FBDC600B5939A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 053BA30A091C00A400A7007A /* Project object */; diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_CertCrl.h b/OSX/libsecurity_keychain/libDER/libDER/DER_CertCrl.h index 6e3c4e63..db36e5cc 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_CertCrl.h +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_CertCrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2009,2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,13 +30,11 @@ #ifndef _DER_CERT_CRL_H_ #define _DER_CERT_CRL_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include #include +__BEGIN_DECLS + /* * Top level cert or CRL - the two are identical at this level - three * components. The tbs field is saved in full DER form for sig verify. @@ -271,9 +269,7 @@ typedef struct { extern const DERItemSpec DERRevokedCertItemSpecs[]; extern const DERSize DERNumRevokedCertItemSpecs; -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _DER_CERT_CRL_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.c b/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.c index 78df3f10..6e8802b4 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.c +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2012 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -53,41 +53,64 @@ /* * Basic decoding primitive. Only works with: * - * -- definite length encoding - * -- one-byte tags + * -- definite length encoding + * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined) * -- max content length fits in a DERSize * - * No malloc or copy of the contents is performed; the returned + * No malloc or copy of the contents is performed; the returned * content->content.data is a pointer into the incoming der data. */ DERReturn DERDecodeItem( + const DERItem *der, /* data to decode */ + DERDecodedInfo *decoded) /* RETURNED */ +{ + return DERDecodeItemPartialBuffer(der, decoded, false); +} + +/* + * Basic decoding primitive. Allows for decoding with a partial buffer. + * if allowPartialBuffer is true. A partial buffer would normally fail + * because the encoded length would be greater than the size of the buffer passed in. + * Only works with: + * + * -- definite length encoding + * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined) + * -- max content length fits in a DERSize + * + * No malloc or copy of the contents is performed; the returned + * content->content.data is a pointer into the incoming der data. + */ +DERReturn DERDecodeItemPartialBuffer( const DERItem *der, /* data to decode */ - DERDecodedInfo *decoded) /* RETURNED */ + DERDecodedInfo *decoded, /* RETURNED */ + bool allowPartialBuffer) { - DERByte tag1; /* first tag byte */ - DERByte len1; /* first length byte */ - DERTag tagNumber; /* tag number without class and method bits */ - DERByte *derPtr = der->data; - DERSize derLen = der->length; - + DERByte tag1; /* first tag byte */ + DERByte len1; /* first length byte */ + DERTag tagNumber; /* tag number without class and method bits */ + DERByte *derPtr = der->data; + DERSize derLen = der->length; + /* The tag decoding below is fully BER complient. We support a max tag - value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we - support tag values from 0 - 0x1F. For tag size 2 tag values - from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */ - if(derLen < 2) { - return DR_DecodeError; - } + value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we + support tag values from 0 - 0x1F. For tag size 2 tag values + from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */ + if(derLen < 2) { + return DR_DecodeError; + } /* Grab the first byte of the tag. */ - tag1 = *derPtr++; - derLen--; - tagNumber = tag1 & 0x1F; - if(tagNumber == 0x1F) { + tag1 = *derPtr++; + derLen--; + tagNumber = tag1 & 0x1F; + if(tagNumber == 0x1F) { #ifdef DER_MULTIBYTE_TAGS /* Long tag form: bit 8 of each octet shall be set to one unless it is - the last octet of the tag */ + the last octet of the tag */ const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7)); DERByte tagByte; tagNumber = 0; + if (*derPtr == 0x80 || *derPtr < 0x1F) + return DR_DecodeError; do { if(derLen < 2 || (tagNumber & overflowMask) != 0) { return DR_DecodeError; @@ -96,55 +119,55 @@ DERReturn DERDecodeItem( derLen--; tagNumber = (tagNumber << 7) | (tagByte & 0x7F); } while((tagByte & 0x80) != 0); - + /* Check for any of the top 3 reserved bits being set. */ if ((tagNumber & (overflowMask << 4)) != 0) #endif return DR_DecodeError; - } + } /* Returned tag, top 3 bits are class/method remaining bits are number. */ decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber; /* Tag decoding above ensured we have at least one more input byte left. */ - len1 = *derPtr++; - derLen--; - if(len1 & 0x80) { - /* long length form - first byte is length of length */ - DERSize longLen = 0; /* long form length */ - unsigned dex; - - len1 &= 0x7f; - if((len1 > sizeof(DERSize)) || (len1 > derLen)) { - /* no can do */ - return DR_DecodeError; - } - for(dex=0; dex derLen) { - /* not enough data left for this encoding */ - return DR_DecodeError; - } - decoded->content.data = derPtr; - decoded->content.length = longLen; - } - else { - /* short length form, len1 is the length */ - if(len1 > derLen) { - /* not enough data left for this encoding */ - return DR_DecodeError; - } - decoded->content.data = derPtr; - decoded->content.length = len1; - } + len1 = *derPtr++; + derLen--; + if(len1 & 0x80) { + /* long length form - first byte is length of length */ + DERSize longLen = 0; /* long form length */ - return DR_Success; - } + unsigned dex; + len1 &= 0x7f; + if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) { + /* no can do */ + return DR_DecodeError; + } + for(dex=0; dex derLen && !allowPartialBuffer) { + /* not enough data left for this encoding */ + return DR_DecodeError; + } + decoded->content.data = derPtr; + decoded->content.length = longLen; + } + else { + /* short length form, len1 is the length */ + if(len1 > derLen && !allowPartialBuffer) { + /* not enough data left for this encoding */ + return DR_DecodeError; + } + decoded->content.data = derPtr; + decoded->content.length = len1; + } -/* - * Given a BIT_STRING, in the form of its raw content bytes, + return DR_Success; +} + +/* + * Given a BIT_STRING, in the form of its raw content bytes, * obtain the number of unused bits and the raw bit string bytes. */ DERReturn DERParseBitString( @@ -171,12 +194,7 @@ DERReturn DERParseBitString( */ DERReturn DERParseBoolean( const DERItem *contents, - bool defaultValue, bool *value) { /* RETURNED */ - if (contents->length == 0) { - *value = defaultValue; - return DR_Success; - } if (contents->length != 1 || (contents->data[0] != 0 && contents->data[0] != 0xFF)) return DR_DecodeError; @@ -185,13 +203,53 @@ DERReturn DERParseBoolean( return DR_Success; } +/* + * Given a BOOLEAN, in the form of its raw content bytes, + * obtain it's value. + */ +DERReturn DERParseBooleanWithDefault( + const DERItem *contents, + bool defaultValue, + bool *value) { /* RETURNED */ + if (contents->length == 0) { + *value = defaultValue; + return DR_Success; + } + return DERParseBoolean(contents, value); +} + + DERReturn DERParseInteger( - const DERItem *contents, - uint32_t *result) { /* RETURNED */ + const DERItem *contents, + uint32_t *result) { /* RETURNED */ + uint64_t value; + DERReturn drtn = DERParseInteger64(contents, &value); + if (drtn == DR_Success) { + if (value > UINT32_MAX) + drtn = DR_BufOverflow; + else + *result = (uint32_t)value; + } + return drtn; +} + +DERReturn DERParseInteger64( + const DERItem *contents, + uint64_t *result) { /* RETURNED */ DERSize ix, length = contents->length; - if (length > 4) + if (length == 0) + return DR_DecodeError; + if (contents->data[0] & 0x80) + return DR_DecodeError; + if (contents->data[0] == 0) { + if (length > 1 && (contents->data[1] & 0x80) == 0) + return DR_DecodeError; + if (length > sizeof(*result) + 1) + return DR_BufOverflow; + } else if (length > sizeof(*result)) { return DR_BufOverflow; - uint32_t value = 0; + } + uint64_t value = 0; for (ix = 0; ix < length; ++ix) { value <<= 8; value += contents->data[ix]; @@ -262,7 +320,7 @@ DERReturn DERDecodeSeqNext( /* decode next item */ item.data = derSeq->nextItem; - item.length = derSeq->end - derSeq->nextItem; + item.length = (DERSize) (derSeq->end - derSeq->nextItem); drtn = DERDecodeItem(&item, decoded); if(drtn) { return drtn; @@ -358,12 +416,12 @@ DERReturn DERParseSequenceContent( * over optional items. */ foundTag = currDecoded.tag; - derDecDbg1("--- foundTag 0x%x\n", foundTag); + derDecDbg1("--- foundTag 0x%llx\n", foundTag); for(i=itemDex; ioptions; - derDecDbg3("--- currItem %u expectTag 0x%x currOptions 0x%x\n", + derDecDbg3("--- currItem %u expectTag 0x%llx currOptions 0x%x\n", i, currItemSpec->tag, currOptions); if((currOptions & DER_DEC_ASN_ANY) || @@ -427,11 +485,12 @@ DERReturn DERParseSequenceContent( /* else on to next item */ } /* main loop */ - /* - * If we get here, there appears to be more to process, but we've - * given the caller everything they want. - */ - return DR_Success; + /* Template has 0 items if we get here. */ + /* normal termination if we consumed everything, (the sequence was empty) */ + if (derSeq.nextItem == derSeq.end) + return DR_Success; + else + return DR_DecodeError; } #if 0 diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.h b/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.h index 827c2bcf..048739fa 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.h +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_Decode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2011 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -28,13 +28,11 @@ #ifndef _DER_DECODE_H_ #define _DER_DECODE_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include #include +__BEGIN_DECLS + /* * Decoding one item consists of extracting its tag, a pointer * to the actual content, and the length of the content. Those @@ -59,6 +57,24 @@ DERReturn DERDecodeItem( const DERItem *der, /* data to decode */ DERDecodedInfo *decoded); /* RETURNED */ +/* + * Basic decoding primitive. Allows for decoding with a partial buffer. + * if allowPartialBuffer is true. A partial buffer would normally fail + * because the encoded length would be greater than the size of the buffer passed in. + * Only works with: + * + * -- definite length encoding + * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined) + * -- max content length fits in a DERSize + * + * No malloc or copy of the contents is performed; the returned + * content->content.data is a pointer into the incoming der data. + */ +DERReturn DERDecodeItemPartialBuffer( + const DERItem *der, /* data to decode */ + DERDecodedInfo *decoded, /* RETURNED */ + bool allowPartialBuffer); + /* * Given a BIT_STRING, in the form of its raw content bytes, * obtain the number of unused bits and the raw bit string bytes. @@ -73,14 +89,27 @@ DERReturn DERParseBitString( * obtain it's value. */ DERReturn DERParseBoolean( - const DERItem *contents, - bool defaultValue, - bool *value); /* RETURNED */ + const DERItem *contents, + bool *value); /* RETURNED */ + +DERReturn DERParseBooleanWithDefault( + const DERItem *contents, + bool defaultValue, + bool *value); /* RETURNED */ +/* + * Given a positive INTEGER, in the form of its raw content bytes, + * obtain it's value as a 32 bit or 64 bit quantity. + * Returns DR_BufOverflow if the value is too large to fit in the return type + */ DERReturn DERParseInteger( const DERItem *contents, uint32_t *value); /* RETURNED */ +DERReturn DERParseInteger64( + const DERItem *contents, + uint64_t *value); /* RETURNED */ + /* * Sequence/set decode support. */ @@ -187,9 +216,7 @@ DERReturn DERParseSequenceContent( void *dest, /* DERDecodedInfo(s) here RETURNED */ DERSize sizeToZero); /* optional */ -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _DER_DECODE_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_Digest.h b/OSX/libsecurity_keychain/libDER/libDER/DER_Digest.h index 68503a35..734d752c 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_Digest.h +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_Digest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2008,2010-2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,12 +30,10 @@ #ifndef _DER_DIGEST_H_ #define _DER_DIGEST_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include +__BEGIN_DECLS + /* * Create an encoded DigestInfo based on the specified SHA1 digest. * The incoming digest must be 20 bytes long. @@ -87,9 +85,7 @@ DERReturn DEREncodeMDDigestInfo( #define DER_MAX_DIGEST_LEN DER_SHA256_DIGEST_LEN #define DER_MAX_ENCODED_INFO_LEN DER_SHA256_DIGEST_INFO_LEN -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _DER_DIGEST_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.c b/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.c index 9b694617..bd8e607a 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.c +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -72,7 +72,7 @@ static DERReturn DEREncodeTag( if(outLen == 1) { /* short form */ - *buf = tag1 | tagNumber; + *buf = (DERByte)(tag1 | tagNumber); } else { /* long form */ @@ -180,6 +180,7 @@ DERReturn DEREncodeItem( bytesLeft -= itemLen; DERMemmove(currPtr, src, length); + // Silence unused variable warning. (void) bytesLeft; return DR_Success; @@ -341,7 +342,7 @@ DERReturn DEREncodeSequence( currPtr += itemSrc->length; bytesLeft -= itemSrc->length; } - *inOutLen = (currPtr - derOut); + *inOutLen = (DERSize)(currPtr - derOut); return DR_Success; } diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.h b/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.h index 6dc3d636..bcde9757 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.h +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_Encode.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2011,2013-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,12 +30,10 @@ #ifndef _DER_ENCODE_H_ #define _DER_ENCODE_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include +__BEGIN_DECLS + /* * Max size of an encoded item given its length. * This includes a possible leading zero prepended to a signed integer @@ -116,9 +114,6 @@ DERSize DERLengthOfEncodedSequence( const DERItemSpec *itemSpecs); -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _DER_ENCODE_H_ */ - diff --git a/OSX/libsecurity_keychain/libDER/libDER/DER_Keys.h b/OSX/libsecurity_keychain/libDER/libDER/DER_Keys.h index 849974fc..41f24d67 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/DER_Keys.h +++ b/OSX/libsecurity_keychain/libDER/libDER/DER_Keys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,13 +30,11 @@ #ifndef _DER_KEYS_H_ #define _DER_KEYS_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include #include +__BEGIN_DECLS + /* Algorithm Identifier components */ typedef struct { DERItem oid; /* OID */ @@ -117,9 +115,7 @@ typedef struct { extern const DERItemSpec DERRSAKeyPairItemSpecs[]; extern const DERSize DERNumRSAKeyPairItemSpecs; -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _DER_KEYS_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/asn1Types.h b/OSX/libsecurity_keychain/libDER/libDER/asn1Types.h index 5275af3c..e1e9510c 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/asn1Types.h +++ b/OSX/libsecurity_keychain/libDER/libDER/asn1Types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,12 +30,15 @@ #ifndef _ASN1_TYPES_H_ #define _ASN1_TYPES_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include + +#include + +__BEGIN_DECLS /* copied from libsecurity_asn1 project */ +/* Type tag numbers */ #define ASN1_BOOLEAN 0x01 #define ASN1_INTEGER 0x02 #define ASN1_BIT_STRING 0x03 @@ -69,8 +72,7 @@ extern "C" { #define ASN1_HIGH_TAG_NUMBER 0x1f #define ASN1_TELETEX_STRING ASN1_T61_STRING -#ifdef DER_MULTIBYTE_TAGS - +/* Tag modifiers */ #define ASN1_TAG_MASK ((DERTag)~0) #define ASN1_TAGNUM_MASK ((DERTag)~((DERTag)7 << (sizeof(DERTag) * 8 - 3))) @@ -84,29 +86,26 @@ extern "C" { #define ASN1_CONTEXT_SPECIFIC ((DERTag)2 << (sizeof(DERTag) * 8 - 2)) #define ASN1_PRIVATE ((DERTag)3 << (sizeof(DERTag) * 8 - 2)) -#else /* DER_MULTIBYTE_TAGS */ - -#define ASN1_TAG_MASK 0xff -#define ASN1_TAGNUM_MASK 0x1f -#define ASN1_METHOD_MASK 0x20 -#define ASN1_PRIMITIVE 0x00 -#define ASN1_CONSTRUCTED 0x20 +/* One-byte tag modifiers */ +#define ONE_BYTE_ASN1_TAG_MASK 0xff +#define ONE_BYTE_ASN1_TAGNUM_MASK 0x1f +#define ONE_BYTE_ASN1_METHOD_MASK 0x20 +#define ONE_BYTE_ASN1_PRIMITIVE 0x00 +#define ONE_BYTE_ASN1_CONSTRUCTED 0x20 -#define ASN1_CLASS_MASK 0xc0 -#define ASN1_UNIVERSAL 0x00 -#define ASN1_APPLICATION 0x40 -#define ASN1_CONTEXT_SPECIFIC 0x80 -#define ASN1_PRIVATE 0xc0 - -#endif /* !DER_MULTIBYTE_TAGS */ +#define ONE_BYTE_ASN1_CLASS_MASK 0xc0 +#define ONE_BYTE_ASN1_UNIVERSAL 0x00 +#define ONE_BYTE_ASN1_APPLICATION 0x40 +#define ONE_BYTE_ASN1_CONTEXT_SPECIFIC 0x80 +#define ONE_BYTE_ASN1_PRIVATE 0xc0 /* sequence and set appear as the following */ -#define ASN1_CONSTR_SEQUENCE (ASN1_CONSTRUCTED | ASN1_SEQUENCE) -#define ASN1_CONSTR_SET (ASN1_CONSTRUCTED | ASN1_SET) +#define ASN1_CONSTR_SEQUENCE ((DERTag)(ASN1_CONSTRUCTED | ASN1_SEQUENCE)) +#define ASN1_CONSTR_SET ((DERTag)(ASN1_CONSTRUCTED | ASN1_SET)) -#ifdef __cplusplus -} -#endif +#define ONE_BYTE_ASN1_CONSTR_SEQUENCE ((uint8_t)(ONE_BYTE_ASN1_CONSTRUCTED | ASN1_SEQUENCE)) +#define ONE_BYTE_ASN1_CONSTR_SET ((uint8_t)(ONE_BYTE_ASN1_CONSTRUCTED | ASN1_SET)) -#endif /* _ASN1_TYPES_H_ */ +__END_DECLS +#endif /* _ASN1_TYPES_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/libDER.h b/OSX/libsecurity_keychain/libDER/libDER/libDER.h index b17e4ba3..e5e4b127 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/libDER.h +++ b/OSX/libsecurity_keychain/libDER/libDER/libDER.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2007,2011,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,16 +30,15 @@ #ifndef _LIB_DER_H_ #define _LIB_DER_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include + +__BEGIN_DECLS + /* * Error returns generated by this library. */ typedef enum { - DR_Success, + DR_Success = 0, DR_EndOfSequence, /* end of sequence or set */ DR_UnexpectedTag, /* unexpected tag found while decoding */ DR_DecodeError, /* misc. decoding error (badly formatted DER) */ @@ -70,9 +69,7 @@ typedef struct { */ #define DER_OFFSET(type, field) ((DERSize)(&((type *)0)->field)) -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _LIB_DER_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/libDER_config.h b/OSX/libsecurity_keychain/libDER/libDER/libDER_config.h index 976af6c0..6280ee3f 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/libDER_config.h +++ b/OSX/libsecurity_keychain/libDER/libDER/libDER_config.h @@ -36,9 +36,7 @@ /* include defintion of DERSize and DERByte */ #include "libDER/oids.h" -#ifdef __cplusplus -extern "C" { -#endif +__BEGIN_DECLS /* * Basic data types: unsigned 8-bit integer, unsigned 32-bit integer @@ -74,9 +72,8 @@ typedef uint16_t DERShort; #ifndef DER_TAG_SIZE /* Iff DER_MULTIBYTE_TAGS is 1 this is the sizeof(DERTag) in bytes. Note that tags are still encoded and decoded from a minimally encoded DER - represantation. This value determines how big each DERItemSpecs is, we - choose 2 since that makes DERItemSpecs 8 bytes wide. */ -#define DER_TAG_SIZE 2 + represantation. This value maintains compatibility with libImg4Decode/Encode. */ +#define DER_TAG_SIZE 8 #endif @@ -108,8 +105,6 @@ typedef uint64_t DERTag; typedef DERByte DERTag; #endif /* !DER_MULTIBYTE_TAGS */ -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _LIB_DER_CONFIG_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/oids.c b/OSX/libsecurity_keychain/libDER/libDER/oids.c index 58bb7dd2..7e62427e 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/oids.c +++ b/OSX/libsecurity_keychain/libDER/libDER/oids.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2009,2011-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2009,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -65,9 +65,14 @@ /* ANSI X9.62 */ #define OID_ANSI_X9_62 OID_US, 206, 61 #define OID_PUBLIC_KEY_TYPE OID_ANSI_X9_62, 2 +#define OID_EC_CURVE OID_ANSI_X9_62, 3, 1 #define OID_EC_SIG_TYPE OID_ANSI_X9_62, 4 #define OID_ECDSA_WITH_SHA2 OID_EC_SIG_TYPE, 3 +/* Certicom */ +#define OID_CERTICOM OID_ISO_IDENTIFIED_ORG, 132 +#define OID_CERTICOM_EC_CURVE OID_CERTICOM, 0 + /* ANSI X9.42 */ #define OID_ANSI_X9_42 OID_US, 206, 62, 2 #define OID_ANSI_X9_42_SCHEME OID_ANSI_X9_42, 3 @@ -256,6 +261,9 @@ /* Secure Boot Embedded Image3 value, co-opted by desktop for "Apple Released Code Signature", without value */ #define APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 1 +#define APPLE_SBOOT_CERT_EXTEN_SBOOT_TICKET_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 11 +#define APPLE_SBOOT_CERT_EXTEN_IMG4_MANIFEST_SPEC_OID APPLE_CERT_EXTENSION_CODESIGNING, 15 + /* iPhone Provisioning Profile Signing leaf - on the intermediate marker arc? */ #define APPLE_PROVISIONING_PROFILE_OID APPLE_CERT_EXT_INTERMEDIATE_MARKER, 1 /* iPhone Application Signing leaf */ @@ -320,6 +328,20 @@ #define APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_TEST APPLE_SERVER_AUTHENTICATION, 8, 1 #define APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 8, 2 +/* Escrow Proxy Server Authentication + * Test Marker OID 1.2.840.113635.100.6.27.7.1 + * Prod Marker OID 1.2.840.113635.100.6.27.7.2 + */ +#define APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_TEST APPLE_SERVER_AUTHENTICATION, 7, 1 +#define APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 7, 2 + +/* FMiP Server Authentication + * Test Marker OID 1.2.840.113635.100.6.27.6.1 + * Prod Marker OID 1.2.840.113635.100.6.27.6.2 + */ +#define APPLE_CERT_EXT_FMIP_SERVER_AUTH_TEST APPLE_SERVER_AUTHENTICATION, 6, 1 +#define APPLE_CERT_EXT_FMIP_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 6, 2 + /* HomeKit Server Authentication * Intermediate Marker OID: 1.2.840.113635.100.6.2.16 * Leaf Marker OID: 1.2.840.113635.100.6.27.9 @@ -327,6 +349,13 @@ #define APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_HOME_KIT_SERVER_AUTH APPLE_CERT_EXT_INTERMEDIATE_MARKER, 16 #define APPLE_CERT_EXT_HOME_KIT_SERVER_AUTH APPLE_SERVER_AUTHENTICATION, 9 +/* MMCS Server Authentication + * Test Marker OID 1.2.840.113635.100.6.27.11.1 + * Prod Marker OID 1.2.840.113635.100.6.27.11.2 + */ +#define APPLE_CERT_EXT_MMCS_SERVER_AUTH_TEST APPLE_SERVER_AUTHENTICATION, 11, 1 +#define APPLE_CERT_EXT_MMCS_SERVER_AUTH_PROD APPLE_SERVER_AUTHENTICATION, 11, 2 + /* * Netscape OIDs. */ @@ -375,10 +404,10 @@ static const DERByte _oidMd4Rsa[] = { OID_PKCS_1, 3 }, _oidMd5Rsa[] = { OID_PKCS_1, 4 }, _oidSha1Rsa[] = { OID_PKCS_1, 5 }, - _oidSha256Rsa[] = { OID_PKCS_1, 11 }, - _oidSha384Rsa[] = { OID_PKCS_1, 12 }, - _oidSha512Rsa[] = { OID_PKCS_1, 13 }, - _oidSha224Rsa[] = { OID_PKCS_1, 14 }, + _oidSha256Rsa[] = { OID_PKCS_1, 11 }, /* rfc5754 */ + _oidSha384Rsa[] = { OID_PKCS_1, 12 }, /* rfc5754 */ + _oidSha512Rsa[] = { OID_PKCS_1, 13 }, /* rfc5754 */ + _oidSha224Rsa[] = { OID_PKCS_1, 14 }, /* rfc5754 */ _oidEcPubKey[] = { OID_PUBLIC_KEY_TYPE, 1 }, _oidSha1Ecdsa[] = { OID_EC_SIG_TYPE, 1 }, /* rfc3279 */ _oidSha224Ecdsa[] = { OID_ECDSA_WITH_SHA2, 1 }, /* rfc5758 */ @@ -399,7 +428,11 @@ static const DERByte _oidSha224[] = { OID_NIST_HASHALG, 4 }, _oidFee[] = { APPLE_ALG_OID, 1 }, _oidMd5Fee[] = { APPLE_ALG_OID, 3 }, - _oidSha1Fee[] = { APPLE_ALG_OID, 4 }; + _oidSha1Fee[] = { APPLE_ALG_OID, 4 }, + _oidEcPrime192v1[] = { OID_EC_CURVE, 1 }, + _oidEcPrime256v1[] = { OID_EC_CURVE, 7 }, + _oidAnsip384r1[] = { OID_CERTICOM_EC_CURVE, 34 }, + _oidAnsip521r1[] = { OID_CERTICOM_EC_CURVE, 35 }; const DERItem oidRsa = { (DERByte *)_oidRsa, @@ -461,7 +494,15 @@ const DERItem oidMd5Fee = { (DERByte *)_oidMd5Fee, sizeof(_oidMd5Fee) }, oidSha1Fee = { (DERByte *)_oidSha1Fee, - sizeof(_oidSha1Fee) }; + sizeof(_oidSha1Fee) }, + oidEcPrime192v1 = { (DERByte *)_oidEcPrime192v1, + sizeof(_oidEcPrime192v1) }, + oidEcPrime256v1 = { (DERByte *)_oidEcPrime256v1, + sizeof(_oidEcPrime256v1) }, + oidAnsip384r1 = { (DERByte *)_oidAnsip384r1, + sizeof(_oidAnsip384r1) }, + oidAnsip521r1 = { (DERByte *)_oidAnsip521r1, + sizeof(_oidAnsip521r1) }; /* Extension OIDs. */ @@ -513,6 +554,8 @@ __unused static const DERByte _oidExtendedKeyUsageMicrosoftSGC[] = { MICROSOFT_BASE_OID, 10, 3, 3 }, _oidExtendedKeyUsageNetscapeSGC[] = { NETSCAPE_CERT_POLICY, 1 }, _oidAppleSecureBootCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_SPEC_OID }, + _oidAppleSecureBootTicketCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_SBOOT_TICKET_SPEC_OID }, + _oidAppleImg4ManifestCertSpec[] = { APPLE_SBOOT_CERT_EXTEN_IMG4_MANIFEST_SPEC_OID }, _oidAppleProvisioningProfile[] = {APPLE_PROVISIONING_PROFILE_OID }, _oidAppleApplicationSigning[] = { APPLE_APP_SIGNING_OID }, _oidAppleInstallerPackagingSigningExternal[] = { APPLE_INSTALLER_PACKAGE_SIGNING_EXTERNAL_OID }, @@ -555,8 +598,14 @@ __unused static const DERByte _oidAppleCertExtCryptoServicesExtEncryption[] = {APPLE_CERT_EXT_CRYPTO_SERVICES_EXT_ENCRYPTION}, _oidAppleCertExtAST2DiagnosticsServerAuthTest[] = {APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_TEST}, _oidAppleCertExtAST2DiagnosticsServerAuthProd[] = {APPLE_CERT_EXT_AST2_DIAGNOSTICS_SERVER_AUTH_PROD}, + _oidAppleCertExtEscrowProxyServerAuthTest[] = {APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_TEST}, + _oidAppleCertExtEscrowProxyServerAuthProd[] = {APPLE_CERT_EXT_ESCROW_PROXY_SERVER_AUTH_PROD}, + _oidAppleCertExtFMiPServerAuthTest[] = {APPLE_CERT_EXT_FMIP_SERVER_AUTH_TEST}, + _oidAppleCertExtFMiPServerAuthProd[] = {APPLE_CERT_EXT_FMIP_SERVER_AUTH_PROD}, _oidAppleCertExtHomeKitServerAuth[] = {APPLE_CERT_EXT_HOME_KIT_SERVER_AUTH}, - _oidAppleIntmMarkerAppleHomeKitServerCA[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_HOME_KIT_SERVER_AUTH}; + _oidAppleIntmMarkerAppleHomeKitServerCA[] = {APPLE_CERT_EXT_INTERMEDIATE_MARKER_APPLE_HOME_KIT_SERVER_AUTH}, + _oidAppleCertExtMMCSServerAuthTest[] = {APPLE_CERT_EXT_MMCS_SERVER_AUTH_TEST}, + _oidAppleCertExtMMCSServerAuthProd[] = {APPLE_CERT_EXT_MMCS_SERVER_AUTH_PROD}; __unused const DERItem oidSubjectKeyIdentifier = { (DERByte *)_oidSubjectKeyIdentifier, @@ -651,6 +700,10 @@ __unused const DERItem sizeof(_oidExtendedKeyUsageNetscapeSGC) }, oidAppleSecureBootCertSpec = { (DERByte *)_oidAppleSecureBootCertSpec, sizeof(_oidAppleSecureBootCertSpec) }, + oidAppleSecureBootTicketCertSpec = { (DERByte *)_oidAppleSecureBootTicketCertSpec, + sizeof(_oidAppleSecureBootTicketCertSpec) }, + oidAppleImg4ManifestCertSpec = { (DERByte *)_oidAppleImg4ManifestCertSpec, + sizeof(_oidAppleImg4ManifestCertSpec) }, oidAppleProvisioningProfile = { (DERByte *)_oidAppleProvisioningProfile, sizeof(_oidAppleProvisioningProfile) }, oidAppleApplicationSigning = { (DERByte *)_oidAppleApplicationSigning, @@ -748,10 +801,24 @@ __unused const DERItem sizeof(_oidAppleCertExtAST2DiagnosticsServerAuthTest)}, oidAppleCertExtAST2DiagnosticsServerAuthProd = { (DERByte *)_oidAppleCertExtAST2DiagnosticsServerAuthProd, sizeof(_oidAppleCertExtAST2DiagnosticsServerAuthProd)}, + oidAppleCertExtEscrowProxyServerAuthTest = { (DERByte *)_oidAppleCertExtEscrowProxyServerAuthTest, + sizeof(_oidAppleCertExtEscrowProxyServerAuthTest)}, + oidAppleCertExtEscrowProxyServerAuthProd = { (DERByte *)_oidAppleCertExtEscrowProxyServerAuthProd, + sizeof(_oidAppleCertExtEscrowProxyServerAuthProd)}, + oidAppleCertExtFMiPServerAuthTest = { (DERByte *)_oidAppleCertExtFMiPServerAuthTest, + sizeof(_oidAppleCertExtFMiPServerAuthTest)}, + oidAppleCertExtFMiPServerAuthProd = { (DERByte *)_oidAppleCertExtFMiPServerAuthProd, + sizeof(_oidAppleCertExtFMiPServerAuthProd)}, oidAppleCertExtHomeKitServerAuth = { (DERByte *)_oidAppleCertExtHomeKitServerAuth, sizeof(_oidAppleCertExtHomeKitServerAuth)}, oidAppleIntmMarkerAppleHomeKitServerCA = { (DERByte *)_oidAppleIntmMarkerAppleHomeKitServerCA, - sizeof(_oidAppleIntmMarkerAppleHomeKitServerCA) }; + sizeof(_oidAppleIntmMarkerAppleHomeKitServerCA) }, + oidAppleCertExtAppleServerAuthenticationMMCSTest + = { (DERByte *)_oidAppleCertExtMMCSServerAuthTest, + sizeof(_oidAppleCertExtMMCSServerAuthTest) }, + oidAppleCertExtAppleServerAuthenticationMMCSProd + = { (DERByte *)_oidAppleCertExtMMCSServerAuthProd, + sizeof(_oidAppleCertExtMMCSServerAuthProd) }; diff --git a/OSX/libsecurity_keychain/libDER/libDER/oids.h b/OSX/libsecurity_keychain/libDER/libDER/oids.h index 094200d0..7f78053d 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/oids.h +++ b/OSX/libsecurity_keychain/libDER/libDER/oids.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2009,2011-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2009,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -33,9 +33,7 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +__BEGIN_DECLS /* * Basic data types @@ -82,7 +80,11 @@ extern const DERItem oidSha224, /* OID_NIST_HASHALG 4 */ oidFee, /* APPLE_ALG_OID 1 */ oidMd5Fee, /* APPLE_ALG_OID 3 */ - oidSha1Fee; /* APPLE_ALG_OID 4 */ + oidSha1Fee, /* APPLE_ALG_OID 4 */ + oidEcPrime192v1, /* OID_EC_CURVE 1 prime192v1/secp192r1/ansiX9p192r1*/ + oidEcPrime256v1, /* OID_EC_CURVE 7 prime256v1/secp256r1*/ + oidAnsip384r1, /* OID_CERTICOM_EC_CURVE 34 ansip384r1/secp384r1*/ + oidAnsip521r1; /* OID_CERTICOM_EC_CURVE 35 ansip521r1/secp521r1*/ /* Standard X.509 Cert and CRL extensions. */ extern const DERItem @@ -145,8 +147,6 @@ extern const DERItem oidGoogleEmbeddedSignedCertificateTimestamp, oidGoogleOCSPSignedCertificateTimestamp; -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _LIB_DER_OIDS_H_ */ diff --git a/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h b/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h index 8fa2f0b3..71c11568 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h +++ b/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2009,2011-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2005-2009,2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -33,13 +33,13 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +__BEGIN_DECLS /* Apple Oids */ extern const DERItem oidAppleSecureBootCertSpec, + oidAppleSecureBootTicketCertSpec, + oidAppleImg4ManifestCertSpec, oidAppleProvisioningProfile, oidAppleApplicationSigning, oidAppleTVOSApplicationSigningProd, @@ -80,14 +80,18 @@ extern const DERItem oidAppleCertExtCryptoServicesExtEncryption, oidAppleCertExtAST2DiagnosticsServerAuthTest, oidAppleCertExtAST2DiagnosticsServerAuthProd, + oidAppleCertExtEscrowProxyServerAuthTest, + oidAppleCertExtEscrowProxyServerAuthProd, + oidAppleCertExtFMiPServerAuthTest, + oidAppleCertExtFMiPServerAuthProd, oidAppleCertExtHomeKitServerAuth, - oidAppleIntmMarkerAppleHomeKitServerCA; + oidAppleIntmMarkerAppleHomeKitServerCA, + oidAppleCertExtAppleServerAuthenticationMMCSTest, + oidAppleCertExtAppleServerAuthenticationMMCSProd; /* Compare two decoded OIDs. Returns true iff they are equivalent. */ bool DEROidCompare(const DERItem *oid1, const DERItem *oid2); -#ifdef __cplusplus -} -#endif +__END_DECLS #endif /* _LIB_DER_UTILS_H_ */ diff --git a/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj b/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj index 57e98c0b..7ea76c9f 100644 --- a/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj @@ -41,12 +41,14 @@ 05AE954A0AA748580076501C /* SecImportExportOpenSSH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05AE95480AA748570076501C /* SecImportExportOpenSSH.cpp */; }; 05FB016805E54A3A00A5194C /* SecNetscapeTemplates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */; }; 05FB016905E54A3A00A5194C /* SecNetscapeTemplates.h in Headers */ = {isa = PBXBuildFile; fileRef = 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */; }; - 0CBD509A16C3246D00713B6C /* kc-40-seckey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509816C3246D00713B6C /* kc-40-seckey.c */; }; - 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */; }; + 0CBD509A16C3246D00713B6C /* kc-40-seckey.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509816C3246D00713B6C /* kc-40-seckey.m */; }; + 0CBD509B16C3246D00713B6C /* kc-41-sececkey.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CBD509916C3246D00713B6C /* kc-41-sececkey.m */; }; 182BB5CD146FF72B000BF1F3 /* libDER.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5297A731112CB13800EAA0C0 /* libDER.a */; }; 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */; }; 1B11967B062F4C1800F3B659 /* SecKeychainSearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */; settings = {ATTRIBUTES = (); }; }; 30E17F5B062B0A25004208EB /* SecIdentitySearchPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */; settings = {ATTRIBUTES = (); }; }; + 3A353D7D1CC50583000446F4 /* TokenLogin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3A353D7B1CC50583000446F4 /* TokenLogin.cpp */; }; + 3A353D7E1CC50583000446F4 /* TokenLogin.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A353D7C1CC50583000446F4 /* TokenLogin.h */; }; 407AC2C0066661620030E07D /* SecPassword.h in Headers */ = {isa = PBXBuildFile; fileRef = 407AC2BE066661620030E07D /* SecPassword.h */; settings = {ATTRIBUTES = (); }; }; 407AC2C1066661620030E07D /* SecPassword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407AC2BF066661620030E07D /* SecPassword.cpp */; }; 407AC2C5066798420030E07D /* Password.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 407AC2C3066798420030E07D /* Password.cpp */; }; @@ -103,6 +105,7 @@ 52E950CD1509B47000DA6511 /* tsaDERUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */; }; 52E950D61509B48D00DA6511 /* tsaDERUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; 52FB44A91146D769006D3B0A /* SecCertificateOIDs.h in Headers */ = {isa = PBXBuildFile; fileRef = 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */; settings = {ATTRIBUTES = (); }; }; + 87701A8E1C4B91E300CB437B /* kc-43-seckey-interop.m in Sources */ = {isa = PBXBuildFile; fileRef = 87701A841C4B91D000CB437B /* kc-43-seckey-interop.m */; }; AA31456F134B716B00133245 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA31456E134B716B00133245 /* CoreFoundation.framework */; }; AC9ADAD3199AD6BA00BDAF54 /* kc-42-trust-revocation.c in Sources */ = {isa = PBXBuildFile; fileRef = AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */; }; BE296DBF0EAC299C00FD22BE /* SecImportExport.c in Sources */ = {isa = PBXBuildFile; fileRef = BE296DBE0EAC299C00FD22BE /* SecImportExport.c */; }; @@ -157,10 +160,45 @@ C2AA2C22052E099D006D0211 /* TrustStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2AA2BB2052E099D006D0211 /* TrustStore.cpp */; }; C2FD26380731CEFB0027896A /* defaultcreds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2FD26370731CEE60027896A /* defaultcreds.cpp */; }; C429431E053B2F8B00470431 /* KCUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C429431C053B2F8B00470431 /* KCUtilities.cpp */; }; + D4486BCF1C65528B0040880D /* SecTrustOSXEntryPoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4486BCD1C65528B0040880D /* SecTrustOSXEntryPoints.cpp */; }; + D45FA39C1C6578CE003DBB97 /* SecTrustOSXEntryPoints.h in Headers */ = {isa = PBXBuildFile; fileRef = D45FA39B1C6578CE003DBB97 /* SecTrustOSXEntryPoints.h */; }; D4A2FC821BC8A65B00BF6E56 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A2FC811BC8A65B00BF6E56 /* Security.framework */; }; D6095E960A94F17C0026C68B /* KCEventNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */; }; + DC196F691CBD70B400A66F4B /* kc-12-key-create-symmetric-and-use.m in Sources */ = {isa = PBXBuildFile; fileRef = DC7EFCA61CBD6ADC005F9624 /* kc-12-key-create-symmetric-and-use.m */; }; + DC196F6A1CBD70C100A66F4B /* kc-12-key-create-symmetric.c in Sources */ = {isa = PBXBuildFile; fileRef = DC7EFCA71CBD6ADC005F9624 /* kc-12-key-create-symmetric.c */; }; + DC196F6D1CBD77CD00A66F4B /* kc-15-key-update-valueref.c in Sources */ = {isa = PBXBuildFile; fileRef = DC196F6B1CBD77C300A66F4B /* kc-15-key-update-valueref.c */; }; + DC19708A1CBEC2FA00A66F4B /* kc-15-item-update-label-skimaad.m in Sources */ = {isa = PBXBuildFile; fileRef = DC1970801CBEC2EE00A66F4B /* kc-15-item-update-label-skimaad.m */; }; + DC19708D1CBEE43E00A66F4B /* kc-16-item-update-password.c in Sources */ = {isa = PBXBuildFile; fileRef = DC19708B1CBEE43600A66F4B /* kc-16-item-update-password.c */; }; + DC247FDB1CBF22AD00527D67 /* kc-27-key-non-extractable.c in Sources */ = {isa = PBXBuildFile; fileRef = DC247FD91CBF1FF800527D67 /* kc-27-key-non-extractable.c */; }; + DC2480511CC1B58B00527D67 /* kc-21-item-use-callback.c in Sources */ = {isa = PBXBuildFile; fileRef = DC2480471CC1B58200527D67 /* kc-21-item-use-callback.c */; }; + DC336B3C1D246E4C00D24F15 /* kc-20-identity-find-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC336B3B1D246E4C00D24F15 /* kc-20-identity-find-stress.c */; }; DC3C16001BAB76B50041A23A /* kc-30-xara.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3C15F81BAB6FE20041A23A /* kc-30-xara.c */; }; + DC6B46641C90EE1200D899C6 /* kc-01-keychain-creation.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46421C90E36900D899C6 /* kc-01-keychain-creation.c */; }; + DC6B46651C90EE1200D899C6 /* kc-02-unlock-noui.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46431C90E36900D899C6 /* kc-02-unlock-noui.c */; }; + DC6B46661C90EE1A00D899C6 /* kc-03-status.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46441C90E36900D899C6 /* kc-03-status.c */; }; + DC6B46671C90EE1A00D899C6 /* kc-10-item-add-generic.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46451C90E36900D899C6 /* kc-10-item-add-generic.c */; }; + DC6B46681C90EE1A00D899C6 /* kc-10-item-add-certificate.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46461C90E36900D899C6 /* kc-10-item-add-certificate.c */; }; + DC6B46691C90EE1A00D899C6 /* kc-12-item-create-keypair.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46471C90E36900D899C6 /* kc-12-item-create-keypair.c */; }; + DC6B466A1C90EE1A00D899C6 /* kc-10-item-add-internet.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46481C90E36900D899C6 /* kc-10-item-add-internet.c */; }; + DC6B466B1C90EE1A00D899C6 /* kc-19-item-copy-internet.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B46491C90E36900D899C6 /* kc-19-item-copy-internet.c */; }; + DC6B466C1C90EE1A00D899C6 /* kc-21-item-use-callback.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B464A1C90E36900D899C6 /* kc-21-item-use-callback.c */; }; + DC6B466E1C90EE1A00D899C6 /* kc-04-is-valid.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B464E1C90E36900D899C6 /* kc-04-is-valid.c */; }; + DC6B466F1C90EE1A00D899C6 /* kc-18-find-combined.c in Sources */ = {isa = PBXBuildFile; fileRef = DC6B464F1C90E36900D899C6 /* kc-18-find-combined.c */; }; + DC7EFBA91CBC4448005F9624 /* kc-06-cert-search-email.m in Sources */ = {isa = PBXBuildFile; fileRef = DC7EFBA71CBC4443005F9624 /* kc-06-cert-search-email.m */; }; + DC840D871CBEF5CB0083F55C /* kc-20-identity-persistent-refs.c in Sources */ = {isa = PBXBuildFile; fileRef = DC19708E1CBEF00F00A66F4B /* kc-20-identity-persistent-refs.c */; }; + DC840D8A1CBEFC6A0083F55C /* kc-20-identity-key-attributes.c in Sources */ = {isa = PBXBuildFile; fileRef = DC840D881CBEFC640083F55C /* kc-20-identity-key-attributes.c */; }; + DC840D8E1CBF13C00083F55C /* kc-23-key-export-symmetric.m in Sources */ = {isa = PBXBuildFile; fileRef = DC840D8C1CBF121F0083F55C /* kc-23-key-export-symmetric.m */; }; + DC840D911CBF17AF0083F55C /* kc-26-key-import-public.m in Sources */ = {isa = PBXBuildFile; fileRef = DC840D8F1CBF179C0083F55C /* kc-26-key-import-public.m */; }; + DC9642751D25F4650073E0C5 /* kc-20-item-find-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC9642741D25F4650073E0C5 /* kc-20-item-find-stress.c */; }; + DC9642771D25F5DD0073E0C5 /* kc-20-key-find-stress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC9642761D25F5DD0073E0C5 /* kc-20-key-find-stress.c */; }; + DC9A61A21CCA9279002793D6 /* kc-03-keychain-list.c in Sources */ = {isa = PBXBuildFile; fileRef = DC9A61A01CCA9273002793D6 /* kc-03-keychain-list.c */; }; + DC9A61AF1CCAA4CF002793D6 /* kc-24-key-copy-keychains.c in Sources */ = {isa = PBXBuildFile; fileRef = DC9A61A51CCAA0A1002793D6 /* kc-24-key-copy-keychains.c */; }; + DC9A61B21CCAAE05002793D6 /* kc-28-cert-sign.c in Sources */ = {isa = PBXBuildFile; fileRef = DC9A61B01CCAA91F002793D6 /* kc-28-cert-sign.c */; }; + DC9A61B51CCABD1F002793D6 /* kc-21-item-xattrs.c in Sources */ = {isa = PBXBuildFile; fileRef = DC9A61B31CCABD18002793D6 /* kc-21-item-xattrs.c */; }; + DCA424031CB81EF20095B7DF /* kc-05-find-existing-items.c in Sources */ = {isa = PBXBuildFile; fileRef = DCA424021CB81EF20095B7DF /* kc-05-find-existing-items.c */; }; + DCBD63151CC86028008C27FC /* kc-28-p12-import.m in Sources */ = {isa = PBXBuildFile; fileRef = DCBD630B1CC86020008C27FC /* kc-28-p12-import.m */; }; DCD20F421BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD20F411BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h */; }; + DCE537591D2EE36800A12A95 /* kc-05-find-existing-items-locked.c in Sources */ = {isa = PBXBuildFile; fileRef = DCE537581D2EE36800A12A95 /* kc-05-find-existing-items-locked.c */; }; F92321381ACF69EE00634C21 /* si-34-one-true-keychain.c in Sources */ = {isa = PBXBuildFile; fileRef = F92321371ACF69EE00634C21 /* si-34-one-true-keychain.c */; }; /* End PBXBuildFile section */ @@ -172,13 +210,6 @@ remoteGlobalIDString = 4CA2A53A0523D32800978A7B; remoteInfo = libsecurity_utilities; }; - 182BB340146F106C000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB30C146F0AE6000BF1F3 /* libsecurity_utilities.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C9C69D0CECBE8400B3FE07; - remoteInfo = libsecurity_utilitiesDTrace; - }; 521FBA8B112CB465002BEF54 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */; @@ -231,7 +262,7 @@ 051A053205DAC86400E02A64 /* SecImportExportPem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportPem.cpp; sourceTree = ""; }; 052AF722060A3472003FEB8D /* SecWrappedKeys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecWrappedKeys.cpp; sourceTree = ""; }; 054F90AD05E2860E0013C1D1 /* SecImportExportUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportUtils.cpp; sourceTree = ""; }; - 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportUtils.h; sourceTree = ""; }; + 054F90AF05E286180013C1D1 /* SecImportExportUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = SecImportExportUtils.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 055EA6B006AC5C13005079CE /* TrustRevocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrustRevocation.cpp; sourceTree = ""; }; 056CDA3805FD573B00820BC3 /* SecImportExportPkcs8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecImportExportPkcs8.cpp; sourceTree = ""; }; 056CDA5C05FD5AEB00820BC3 /* SecPkcs8Templates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPkcs8Templates.h; sourceTree = ""; }; @@ -245,8 +276,8 @@ 058AAA9105D97EAE00F543ED /* SecImportExportPem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecImportExportPem.h; sourceTree = ""; }; 058C796F09F56CCB00DB7E98 /* SecTrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettings.h; sourceTree = ""; }; 058C797009F56CCB00DB7E98 /* SecTrustSettingsPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustSettingsPriv.h; sourceTree = ""; }; - 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrustSettings.cpp; sourceTree = ""; }; - 058C797709F56D1400DB7E98 /* TrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustSettings.cpp; sourceTree = ""; }; + 058C797509F56CFB00DB7E98 /* SecTrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecTrustSettings.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 058C797709F56D1400DB7E98 /* TrustSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TrustSettings.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 058C797809F56D1400DB7E98 /* TrustSettings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettings.h; sourceTree = ""; }; 058C797909F56D1400DB7E98 /* TrustSettingsSchema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustSettingsSchema.h; sourceTree = ""; }; 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustSettingsUtils.cpp; sourceTree = ""; }; @@ -260,8 +291,8 @@ 05FB016605E54A3A00A5194C /* SecNetscapeTemplates.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecNetscapeTemplates.cpp; sourceTree = ""; }; 05FB016705E54A3A00A5194C /* SecNetscapeTemplates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecNetscapeTemplates.h; sourceTree = ""; }; 0CBD509716C3242200713B6C /* libsecurity_keychain_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_keychain_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 0CBD509816C3246D00713B6C /* kc-40-seckey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-40-seckey.c"; path = "regressions/kc-40-seckey.c"; sourceTree = ""; }; - 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-41-sececkey.c"; path = "regressions/kc-41-sececkey.c"; sourceTree = ""; }; + 0CBD509816C3246D00713B6C /* kc-40-seckey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-40-seckey.m"; path = "regressions/kc-40-seckey.m"; sourceTree = ""; }; + 0CBD509916C3246D00713B6C /* kc-41-sececkey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-41-sececkey.m"; path = "regressions/kc-41-sececkey.m"; sourceTree = ""; }; 0CBD509C16C324B100713B6C /* keychain_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keychain_regressions.h; path = regressions/keychain_regressions.h; sourceTree = ""; }; 182BB224146F063C000BF1F3 /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; 182BB225146F063C000BF1F3 /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; @@ -271,8 +302,10 @@ 188BB53F171DD774009D22CE /* si-33-keychain-backup.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = "si-33-keychain-backup.c"; path = "regressions/si-33-keychain-backup.c"; sourceTree = ""; }; 1B11967A062F4C1800F3B659 /* SecKeychainSearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecKeychainSearchPriv.h; sourceTree = ""; }; 30E17F5A062B0A25004208EB /* SecIdentitySearchPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecIdentitySearchPriv.h; path = lib/SecIdentitySearchPriv.h; sourceTree = SOURCE_ROOT; }; + 3A353D7B1CC50583000446F4 /* TokenLogin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TokenLogin.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 3A353D7C1CC50583000446F4 /* TokenLogin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TokenLogin.h; sourceTree = ""; }; 407AC2BE066661620030E07D /* SecPassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecPassword.h; sourceTree = ""; }; - 407AC2BF066661620030E07D /* SecPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecPassword.cpp; sourceTree = ""; }; + 407AC2BF066661620030E07D /* SecPassword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecPassword.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 407AC2C2066798420030E07D /* Password.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Password.h; sourceTree = ""; }; 407AC2C3066798420030E07D /* Password.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Password.cpp; sourceTree = ""; }; 4885CFF611C8182D0093ECF6 /* SecRecoveryPassword.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecRecoveryPassword.c; sourceTree = ""; }; @@ -291,12 +324,11 @@ 4CFDC28306CD9C6A007BEE7E /* DynamicDLDBList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicDLDBList.cpp; sourceTree = ""; }; 4CFDC28406CD9C6A007BEE7E /* DynamicDLDBList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DynamicDLDBList.h; sourceTree = ""; }; 52008C6311496BD200E8CA78 /* SecCertificateInternalP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateInternalP.h; sourceTree = ""; }; - 521DC57D1125FEE300937BF2 /* SecCertificateP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCertificateP.c; sourceTree = ""; }; + 521DC57D1125FEE300937BF2 /* SecCertificateP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = SecCertificateP.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; 521DC57E1125FEE300937BF2 /* SecCertificateP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateP.h; sourceTree = ""; }; 52200F8F14F2B88000F7F6E7 /* XPCTimeStampingService.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XPCTimeStampingService.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; 52200F9B14F2B93700F7F6E7 /* XPCTimeStampingService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "XPCTimeStampingService-Info.plist"; sourceTree = ""; }; 5261C289112F0D570047EF8B /* SecFrameworkP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecFrameworkP.c; sourceTree = ""; }; - 5261C2E1112F19BA0047EF8B /* debuggingP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debuggingP.c; sourceTree = ""; }; 5261C30F112F1C560047EF8B /* SecBase64P.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecBase64P.c; sourceTree = ""; }; 527067DB070246B300C5D30E /* iToolsTrustedApps.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; name = iToolsTrustedApps.plist; path = plist/iToolsTrustedApps.plist; sourceTree = SOURCE_ROOT; }; 5297A586112B78BB00EAA0C0 /* libDER.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libDER.xcodeproj; path = libDER/libDER.xcodeproj; sourceTree = ""; }; @@ -311,14 +343,14 @@ 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificatePrivP.h; sourceTree = ""; }; 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaDERUtilities.c; sourceTree = ""; }; 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaDERUtilities.h; sourceTree = ""; }; - 52FB42C1113F056D006D3B0A /* debuggingP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debuggingP.h; sourceTree = ""; }; 52FB44A81146D769006D3B0A /* SecCertificateOIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCertificateOIDs.h; sourceTree = ""; }; + 87701A841C4B91D000CB437B /* kc-43-seckey-interop.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-43-seckey-interop.m"; path = "regressions/kc-43-seckey-interop.m"; sourceTree = ""; }; AA31456E134B716B00133245 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-42-trust-revocation.c"; path = "regressions/kc-42-trust-revocation.c"; sourceTree = ""; }; BE0FAED51B967FB30017DAC9 /* si-20-sectrust-provisioning.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "si-20-sectrust-provisioning.h"; path = "regressions/si-20-sectrust-provisioning.h"; sourceTree = ""; }; BE296DBE0EAC299C00FD22BE /* SecImportExport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecImportExport.c; sourceTree = ""; }; BE296DC40EAC2B5600FD22BE /* SecInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecInternal.h; sourceTree = ""; }; - BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrustAdditions.cpp; sourceTree = ""; }; + BE50AE650F687AB900D28C54 /* TrustAdditions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TrustAdditions.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; BE50AE660F687AB900D28C54 /* TrustAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustAdditions.h; sourceTree = ""; }; BECE5140106B056C0091E644 /* TrustKeychains.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrustKeychains.h; sourceTree = ""; }; BED2BCA11B96217B006CF43A /* si-20-sectrust-provisioning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "si-20-sectrust-provisioning.c"; path = "regressions/si-20-sectrust-provisioning.c"; sourceTree = ""; }; @@ -326,14 +358,14 @@ BEE896E10A61F0BB00BF88A5 /* SecItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecItemPriv.h; sourceTree = ""; }; BEE896E60A61F12300BF88A5 /* SecItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SecItem.cpp; sourceTree = ""; usesTabs = 1; }; BEE897100A62CDD800BF88A5 /* SecItemConstants.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecItemConstants.c; sourceTree = ""; }; - C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = UnlockReferralItem.cpp; path = lib/UnlockReferralItem.cpp; sourceTree = SOURCE_ROOT; }; + C26BA9FE072580AE0049AF3C /* UnlockReferralItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = UnlockReferralItem.cpp; path = lib/UnlockReferralItem.cpp; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2975B9B072580DC00AFECAD /* UnlockReferralItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = UnlockReferralItem.h; path = lib/UnlockReferralItem.h; sourceTree = SOURCE_ROOT; }; - C2AA2B42052E099D006D0211 /* Access.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Access.cpp; sourceTree = ""; }; + C2AA2B42052E099D006D0211 /* Access.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Access.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B43052E099D006D0211 /* Access.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Access.h; sourceTree = ""; }; - C2AA2B44052E099D006D0211 /* ACL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ACL.cpp; sourceTree = ""; }; + C2AA2B44052E099D006D0211 /* ACL.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ACL.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B45052E099D006D0211 /* ACL.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ACL.h; sourceTree = ""; }; C2AA2B46052E099D006D0211 /* CCallbackMgr.cp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CCallbackMgr.cp; sourceTree = ""; }; - C2AA2B47052E099D006D0211 /* CCallbackMgr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CCallbackMgr.h; sourceTree = ""; }; + C2AA2B47052E099D006D0211 /* CCallbackMgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCallbackMgr.h; sourceTree = ""; }; C2AA2B48052E099D006D0211 /* Certificate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Certificate.cpp; sourceTree = ""; }; C2AA2B49052E099D006D0211 /* Certificate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Certificate.h; sourceTree = ""; }; C2AA2B4A052E099D006D0211 /* CertificateRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CertificateRequest.cpp; sourceTree = ""; }; @@ -349,16 +381,16 @@ C2AA2B59052E099D006D0211 /* Identity.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Identity.h; sourceTree = ""; }; C2AA2B5A052E099D006D0211 /* IdentityCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentityCursor.cpp; sourceTree = ""; }; C2AA2B5B052E099D006D0211 /* IdentityCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IdentityCursor.h; sourceTree = ""; }; - C2AA2B5C052E099D006D0211 /* Item.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Item.cpp; sourceTree = ""; }; + C2AA2B5C052E099D006D0211 /* Item.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Item.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B5D052E099D006D0211 /* Item.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Item.h; sourceTree = ""; }; - C2AA2B5E052E099D006D0211 /* KCCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCCursor.cpp; sourceTree = ""; }; + C2AA2B5E052E099D006D0211 /* KCCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KCCursor.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B5F052E099D006D0211 /* KCCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCCursor.h; sourceTree = ""; }; C2AA2B64052E099D006D0211 /* KCExceptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCExceptions.h; sourceTree = ""; }; - C2AA2B67052E099D006D0211 /* Keychains.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Keychains.cpp; sourceTree = ""; }; + C2AA2B67052E099D006D0211 /* Keychains.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Keychains.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B68052E099D006D0211 /* Keychains.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Keychains.h; sourceTree = ""; }; - C2AA2B69052E099D006D0211 /* KeyItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KeyItem.cpp; sourceTree = ""; }; + C2AA2B69052E099D006D0211 /* KeyItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KeyItem.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B6A052E099D006D0211 /* KeyItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KeyItem.h; sourceTree = ""; }; - C2AA2B6B052E099D006D0211 /* Policies.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Policies.cpp; sourceTree = ""; }; + C2AA2B6B052E099D006D0211 /* Policies.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Policies.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2B6C052E099D006D0211 /* Policies.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Policies.h; sourceTree = ""; }; C2AA2B6D052E099D006D0211 /* PolicyCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PolicyCursor.cpp; sourceTree = ""; }; C2AA2B6E052E099D006D0211 /* PolicyCursor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PolicyCursor.h; sourceTree = ""; }; @@ -407,30 +439,70 @@ C2AA2BA3052E099D006D0211 /* SecTrustedApplicationPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustedApplicationPriv.h; sourceTree = ""; }; C2AA2BA4052E099D006D0211 /* SecTrustPriv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecTrustPriv.h; sourceTree = ""; }; C2AA2BA5052E099D006D0211 /* Security.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Security.h; sourceTree = ""; }; - C2AA2BAA052E099D006D0211 /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StorageManager.cpp; sourceTree = ""; }; + C2AA2BAA052E099D006D0211 /* StorageManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = StorageManager.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2BAB052E099D006D0211 /* StorageManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StorageManager.h; sourceTree = ""; }; - C2AA2BAC052E099D006D0211 /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Trust.cpp; sourceTree = ""; }; + C2AA2BAC052E099D006D0211 /* Trust.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = Trust.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2BAD052E099D006D0211 /* Trust.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Trust.h; sourceTree = ""; }; - C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustedApplication.cpp; sourceTree = ""; }; + C2AA2BAE052E099D006D0211 /* TrustedApplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TrustedApplication.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2BAF052E099D006D0211 /* TrustedApplication.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustedApplication.h; sourceTree = ""; }; - C2AA2BB0052E099D006D0211 /* TrustItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustItem.cpp; sourceTree = ""; }; + C2AA2BB0052E099D006D0211 /* TrustItem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TrustItem.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2BB1052E099D006D0211 /* TrustItem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustItem.h; sourceTree = ""; }; - C2AA2BB2052E099D006D0211 /* TrustStore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TrustStore.cpp; sourceTree = ""; }; + C2AA2BB2052E099D006D0211 /* TrustStore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = TrustStore.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C2AA2BB3052E099D006D0211 /* TrustStore.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TrustStore.h; sourceTree = ""; }; C2FD262F0731CEB40027896A /* defaultcreds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = defaultcreds.h; path = lib/defaultcreds.h; sourceTree = SOURCE_ROOT; }; - C2FD26370731CEE60027896A /* defaultcreds.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = defaultcreds.cpp; path = lib/defaultcreds.cpp; sourceTree = SOURCE_ROOT; }; + C2FD26370731CEE60027896A /* defaultcreds.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = defaultcreds.cpp; path = lib/defaultcreds.cpp; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; C429431C053B2F8B00470431 /* KCUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCUtilities.cpp; sourceTree = ""; }; C429431D053B2F8B00470431 /* KCUtilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCUtilities.h; sourceTree = ""; }; C4A397A1053B1D50000E1B34 /* SecKeychainPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainPriv.h; sourceTree = ""; }; C4A397FA053B21F9000E1B34 /* SecKeychainItemPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecKeychainItemPriv.h; sourceTree = ""; }; + D4486BCD1C65528B0040880D /* SecTrustOSXEntryPoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SecTrustOSXEntryPoints.cpp; sourceTree = ""; }; + D45FA39B1C6578CE003DBB97 /* SecTrustOSXEntryPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTrustOSXEntryPoints.h; path = ../../trustd/SecTrustOSXEntryPoints.h; sourceTree = ""; }; D4A2FC811BC8A65B00BF6E56 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = KCEventNotifier.cpp; sourceTree = ""; }; D6E1457C0A632A5A008AA7E8 /* KCEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCEventNotifier.h; sourceTree = ""; }; - DC3C15F81BAB6FE20041A23A /* kc-30-xara.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-30-xara.c"; path = "regressions/kc-30-xara.c"; sourceTree = ""; }; - DC6949791BC71B2300AB4DC3 /* kc-30-xara-item-helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "kc-30-xara-item-helpers.h"; path = "regressions/kc-30-xara-item-helpers.h"; sourceTree = ""; }; - DC6949801BC71B3B00AB4DC3 /* kc-30-xara-key-helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "kc-30-xara-key-helpers.h"; path = "regressions/kc-30-xara-key-helpers.h"; sourceTree = ""; }; + DC196F6B1CBD77C300A66F4B /* kc-15-key-update-valueref.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-15-key-update-valueref.c"; path = "regressions/kc-15-key-update-valueref.c"; sourceTree = ""; }; + DC1970801CBEC2EE00A66F4B /* kc-15-item-update-label-skimaad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-15-item-update-label-skimaad.m"; path = "regressions/kc-15-item-update-label-skimaad.m"; sourceTree = ""; }; + DC19708B1CBEE43600A66F4B /* kc-16-item-update-password.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-16-item-update-password.c"; path = "regressions/kc-16-item-update-password.c"; sourceTree = ""; }; + DC19708E1CBEF00F00A66F4B /* kc-20-identity-persistent-refs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-20-identity-persistent-refs.c"; path = "regressions/kc-20-identity-persistent-refs.c"; sourceTree = ""; }; + DC247FD91CBF1FF800527D67 /* kc-27-key-non-extractable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-27-key-non-extractable.c"; path = "regressions/kc-27-key-non-extractable.c"; sourceTree = ""; }; + DC2480471CC1B58200527D67 /* kc-21-item-use-callback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-21-item-use-callback.c"; path = "regressions/kc-21-item-use-callback.c"; sourceTree = ""; }; + DC336B3B1D246E4C00D24F15 /* kc-20-identity-find-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-20-identity-find-stress.c"; path = "regressions/kc-20-identity-find-stress.c"; sourceTree = ""; }; + DC3C15F81BAB6FE20041A23A /* kc-30-xara.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; name = "kc-30-xara.c"; path = "regressions/kc-30-xara.c"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + DC6949791BC71B2300AB4DC3 /* kc-30-xara-item-helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "kc-30-xara-item-helpers.h"; path = "regressions/kc-30-xara-item-helpers.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + DC6949801BC71B3B00AB4DC3 /* kc-30-xara-key-helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "kc-30-xara-key-helpers.h"; path = "regressions/kc-30-xara-key-helpers.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; DC6949821BC71C7600AB4DC3 /* kc-30-xara-helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "kc-30-xara-helpers.h"; path = "regressions/kc-30-xara-helpers.h"; sourceTree = ""; }; + DC6B46421C90E36900D899C6 /* kc-01-keychain-creation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-01-keychain-creation.c"; path = "regressions/kc-01-keychain-creation.c"; sourceTree = ""; }; + DC6B46431C90E36900D899C6 /* kc-02-unlock-noui.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-02-unlock-noui.c"; path = "regressions/kc-02-unlock-noui.c"; sourceTree = ""; }; + DC6B46441C90E36900D899C6 /* kc-03-status.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-03-status.c"; path = "regressions/kc-03-status.c"; sourceTree = ""; }; + DC6B46451C90E36900D899C6 /* kc-10-item-add-generic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-10-item-add-generic.c"; path = "regressions/kc-10-item-add-generic.c"; sourceTree = ""; }; + DC6B46461C90E36900D899C6 /* kc-10-item-add-certificate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-10-item-add-certificate.c"; path = "regressions/kc-10-item-add-certificate.c"; sourceTree = ""; }; + DC6B46471C90E36900D899C6 /* kc-12-item-create-keypair.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-12-item-create-keypair.c"; path = "regressions/kc-12-item-create-keypair.c"; sourceTree = ""; }; + DC6B46481C90E36900D899C6 /* kc-10-item-add-internet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-10-item-add-internet.c"; path = "regressions/kc-10-item-add-internet.c"; sourceTree = ""; }; + DC6B46491C90E36900D899C6 /* kc-19-item-copy-internet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-19-item-copy-internet.c"; path = "regressions/kc-19-item-copy-internet.c"; sourceTree = ""; }; + DC6B464A1C90E36900D899C6 /* kc-21-item-use-callback.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-21-item-use-callback.c"; path = "regressions/kc-21-item-use-callback.c"; sourceTree = ""; }; + DC6B464E1C90E36900D899C6 /* kc-04-is-valid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-04-is-valid.c"; path = "regressions/kc-04-is-valid.c"; sourceTree = ""; }; + DC6B464F1C90E36900D899C6 /* kc-18-find-combined.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-18-find-combined.c"; path = "regressions/kc-18-find-combined.c"; sourceTree = ""; }; + DC6B46701C90F2C100D899C6 /* kc-helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "kc-helpers.h"; path = "regressions/kc-helpers.h"; sourceTree = ""; }; + DC7EFBA71CBC4443005F9624 /* kc-06-cert-search-email.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-06-cert-search-email.m"; path = "regressions/kc-06-cert-search-email.m"; sourceTree = ""; }; + DC7EFCA61CBD6ADC005F9624 /* kc-12-key-create-symmetric-and-use.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-12-key-create-symmetric-and-use.m"; path = "regressions/kc-12-key-create-symmetric-and-use.m"; sourceTree = ""; }; + DC7EFCA71CBD6ADC005F9624 /* kc-12-key-create-symmetric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-12-key-create-symmetric.c"; path = "regressions/kc-12-key-create-symmetric.c"; sourceTree = ""; }; + DC840D881CBEFC640083F55C /* kc-20-identity-key-attributes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-20-identity-key-attributes.c"; path = "regressions/kc-20-identity-key-attributes.c"; sourceTree = ""; }; + DC840D8B1CBEFCAD0083F55C /* kc-identity-helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "kc-identity-helpers.h"; path = "regressions/kc-identity-helpers.h"; sourceTree = ""; }; + DC840D8C1CBF121F0083F55C /* kc-23-key-export-symmetric.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-23-key-export-symmetric.m"; path = "regressions/kc-23-key-export-symmetric.m"; sourceTree = ""; }; + DC840D8F1CBF179C0083F55C /* kc-26-key-import-public.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-26-key-import-public.m"; path = "regressions/kc-26-key-import-public.m"; sourceTree = ""; }; + DC9642741D25F4650073E0C5 /* kc-20-item-find-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-20-item-find-stress.c"; path = "regressions/kc-20-item-find-stress.c"; sourceTree = ""; }; + DC9642761D25F5DD0073E0C5 /* kc-20-key-find-stress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-20-key-find-stress.c"; path = "regressions/kc-20-key-find-stress.c"; sourceTree = ""; }; + DC9A61A01CCA9273002793D6 /* kc-03-keychain-list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-03-keychain-list.c"; path = "regressions/kc-03-keychain-list.c"; sourceTree = ""; }; + DC9A61A51CCAA0A1002793D6 /* kc-24-key-copy-keychains.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-24-key-copy-keychains.c"; path = "regressions/kc-24-key-copy-keychains.c"; sourceTree = ""; }; + DC9A61B01CCAA91F002793D6 /* kc-28-cert-sign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-28-cert-sign.c"; path = "regressions/kc-28-cert-sign.c"; sourceTree = ""; }; + DC9A61B31CCABD18002793D6 /* kc-21-item-xattrs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-21-item-xattrs.c"; path = "regressions/kc-21-item-xattrs.c"; sourceTree = ""; }; + DCA424021CB81EF20095B7DF /* kc-05-find-existing-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-05-find-existing-items.c"; path = "regressions/kc-05-find-existing-items.c"; sourceTree = ""; }; + DCA4240C1CB81FE90095B7DF /* kc-keychain-file-helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "kc-keychain-file-helpers.h"; path = "regressions/kc-keychain-file-helpers.h"; sourceTree = ""; }; + DCA4240D1CB8240E0095B7DF /* kc-item-helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "kc-item-helpers.h"; path = "regressions/kc-item-helpers.h"; sourceTree = ""; }; + DCA4240E1CB828D80095B7DF /* kc-key-helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "kc-key-helpers.h"; path = "regressions/kc-key-helpers.h"; sourceTree = ""; }; + DCBD630B1CC86020008C27FC /* kc-28-p12-import.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "kc-28-p12-import.m"; path = "regressions/kc-28-p12-import.m"; sourceTree = ""; }; DCD20F411BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "kc-30-xara-upgrade-helpers.h"; path = "regressions/kc-30-xara-upgrade-helpers.h"; sourceTree = ""; }; + DCE537581D2EE36800A12A95 /* kc-05-find-existing-items-locked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "kc-05-find-existing-items-locked.c"; path = "regressions/kc-05-find-existing-items-locked.c"; sourceTree = ""; }; F92321371ACF69EE00634C21 /* 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 = ""; }; /* End PBXFileReference section */ @@ -592,6 +664,8 @@ 058C797709F56D1400DB7E98 /* TrustSettings.cpp */, 058C797809F56D1400DB7E98 /* TrustSettings.h */, BECE5140106B056C0091E644 /* TrustKeychains.h */, + D4486BCD1C65528B0040880D /* SecTrustOSXEntryPoints.cpp */, + D45FA39B1C6578CE003DBB97 /* SecTrustOSXEntryPoints.h */, ); name = "API Classes"; sourceTree = ""; @@ -630,10 +704,8 @@ C2975B9B072580DC00AFECAD /* UnlockReferralItem.h */, 058C797A09F56D1400DB7E98 /* TrustSettingsUtils.cpp */, 058C797B09F56D1400DB7E98 /* TrustSettingsUtils.h */, - 52FB42C1113F056D006D3B0A /* debuggingP.h */, 52C23EF71135AE5100E079D2 /* SecCertificatePrivP.h */, 5261C30F112F1C560047EF8B /* SecBase64P.c */, - 5261C2E1112F19BA0047EF8B /* debuggingP.c */, 5261C289112F0D570047EF8B /* SecFrameworkP.c */, 521DC57D1125FEE300937BF2 /* SecCertificateP.c */, 521DC57E1125FEE300937BF2 /* SecCertificateP.h */, @@ -642,6 +714,8 @@ C2AA2B55052E099D006D0211 /* generateErrStrings.pl */, 52E950CC1509B47000DA6511 /* tsaDERUtilities.c */, 52E950D51509B48D00DA6511 /* tsaDERUtilities.h */, + 3A353D7B1CC50583000446F4 /* TokenLogin.cpp */, + 3A353D7C1CC50583000446F4 /* TokenLogin.h */, ); name = Internal; sourceTree = ""; @@ -679,13 +753,51 @@ isa = PBXGroup; children = ( 0CBD509C16C324B100713B6C /* keychain_regressions.h */, + DC6B46701C90F2C100D899C6 /* kc-helpers.h */, + DCA4240D1CB8240E0095B7DF /* kc-item-helpers.h */, + DCA4240E1CB828D80095B7DF /* kc-key-helpers.h */, + DC840D8B1CBEFCAD0083F55C /* kc-identity-helpers.h */, + DCA4240C1CB81FE90095B7DF /* kc-keychain-file-helpers.h */, + DC6B46421C90E36900D899C6 /* kc-01-keychain-creation.c */, + DC6B46431C90E36900D899C6 /* kc-02-unlock-noui.c */, + DC6B46441C90E36900D899C6 /* kc-03-status.c */, + DC9A61A01CCA9273002793D6 /* kc-03-keychain-list.c */, + DC6B464E1C90E36900D899C6 /* kc-04-is-valid.c */, + DCA424021CB81EF20095B7DF /* kc-05-find-existing-items.c */, + DCE537581D2EE36800A12A95 /* kc-05-find-existing-items-locked.c */, + DC7EFBA71CBC4443005F9624 /* kc-06-cert-search-email.m */, + DC6B46451C90E36900D899C6 /* kc-10-item-add-generic.c */, + DC6B46481C90E36900D899C6 /* kc-10-item-add-internet.c */, + DC6B46461C90E36900D899C6 /* kc-10-item-add-certificate.c */, + DC7EFCA71CBD6ADC005F9624 /* kc-12-key-create-symmetric.c */, + DC7EFCA61CBD6ADC005F9624 /* kc-12-key-create-symmetric-and-use.m */, + DC6B46471C90E36900D899C6 /* kc-12-item-create-keypair.c */, + DC196F6B1CBD77C300A66F4B /* kc-15-key-update-valueref.c */, + DC1970801CBEC2EE00A66F4B /* kc-15-item-update-label-skimaad.m */, + DC19708B1CBEE43600A66F4B /* kc-16-item-update-password.c */, + DC6B464F1C90E36900D899C6 /* kc-18-find-combined.c */, + DC6B46491C90E36900D899C6 /* kc-19-item-copy-internet.c */, + DC19708E1CBEF00F00A66F4B /* kc-20-identity-persistent-refs.c */, + DC840D881CBEFC640083F55C /* kc-20-identity-key-attributes.c */, + DC9642741D25F4650073E0C5 /* kc-20-item-find-stress.c */, + DC9642761D25F5DD0073E0C5 /* kc-20-key-find-stress.c */, + DC336B3B1D246E4C00D24F15 /* kc-20-identity-find-stress.c */, + DC6B464A1C90E36900D899C6 /* kc-21-item-use-callback.c */, + DC9A61B31CCABD18002793D6 /* kc-21-item-xattrs.c */, + DC840D8C1CBF121F0083F55C /* kc-23-key-export-symmetric.m */, + DC9A61A51CCAA0A1002793D6 /* kc-24-key-copy-keychains.c */, + DC840D8F1CBF179C0083F55C /* kc-26-key-import-public.m */, + DC247FD91CBF1FF800527D67 /* kc-27-key-non-extractable.c */, + DCBD630B1CC86020008C27FC /* kc-28-p12-import.m */, + DC9A61B01CCAA91F002793D6 /* kc-28-cert-sign.c */, DC3C15F81BAB6FE20041A23A /* kc-30-xara.c */, DC6949821BC71C7600AB4DC3 /* kc-30-xara-helpers.h */, DCD20F411BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h */, DC6949791BC71B2300AB4DC3 /* kc-30-xara-item-helpers.h */, DC6949801BC71B3B00AB4DC3 /* kc-30-xara-key-helpers.h */, - 0CBD509816C3246D00713B6C /* kc-40-seckey.c */, - 0CBD509916C3246D00713B6C /* kc-41-sececkey.c */, + 0CBD509816C3246D00713B6C /* kc-40-seckey.m */, + 0CBD509916C3246D00713B6C /* kc-41-sececkey.m */, + 87701A841C4B91D000CB437B /* kc-43-seckey-interop.m */, AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */, BED2BCA11B96217B006CF43A /* si-20-sectrust-provisioning.c */, BE0FAED51B967FB30017DAC9 /* si-20-sectrust-provisioning.h */, @@ -801,6 +913,7 @@ 4CF36F680581376700834D11 /* SecACL.h in Headers */, 4CF36F6A0581376700834D11 /* SecBase.h in Headers */, 4CF36F690581376700834D11 /* SecCertificate.h in Headers */, + 3A353D7E1CC50583000446F4 /* TokenLogin.h in Headers */, 4CF36F6C0581376700834D11 /* SecIdentity.h in Headers */, 4CF36F670581376700834D11 /* SecIdentitySearch.h in Headers */, BEE896E20A61F0BB00BF88A5 /* SecItem.h in Headers */, @@ -846,6 +959,7 @@ 058C797209F56CCC00DB7E98 /* SecTrustSettingsPriv.h in Headers */, 058C797D09F56D1400DB7E98 /* TrustSettings.h in Headers */, 058C797E09F56D1400DB7E98 /* TrustSettingsSchema.h in Headers */, + D45FA39C1C6578CE003DBB97 /* SecTrustOSXEntryPoints.h in Headers */, 058C798009F56D1400DB7E98 /* TrustSettingsUtils.h in Headers */, BEE896E30A61F0BB00BF88A5 /* SecItemPriv.h in Headers */, 05A83C380AAF591100906F28 /* SecKeychainItemExtendedAttributes.h in Headers */, @@ -905,7 +1019,6 @@ buildRules = ( ); dependencies = ( - 182BB341146F106C000BF1F3 /* PBXTargetDependency */, 521FBA8C112CB465002BEF54 /* PBXTargetDependency */, ); name = libsecurity_keychain; @@ -935,7 +1048,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3810987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_keychain" */; compatibilityVersion = "Xcode 3.2"; @@ -1020,13 +1133,47 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DC6B46641C90EE1200D899C6 /* kc-01-keychain-creation.c in Sources */, + DC196F691CBD70B400A66F4B /* kc-12-key-create-symmetric-and-use.m in Sources */, + DC9A61A21CCA9279002793D6 /* kc-03-keychain-list.c in Sources */, + DC6B46651C90EE1200D899C6 /* kc-02-unlock-noui.c in Sources */, + DC840D8A1CBEFC6A0083F55C /* kc-20-identity-key-attributes.c in Sources */, + DC6B46661C90EE1A00D899C6 /* kc-03-status.c in Sources */, + DCBD63151CC86028008C27FC /* kc-28-p12-import.m in Sources */, + DC6B46671C90EE1A00D899C6 /* kc-10-item-add-generic.c in Sources */, + DC6B46681C90EE1A00D899C6 /* kc-10-item-add-certificate.c in Sources */, + DC6B46691C90EE1A00D899C6 /* kc-12-item-create-keypair.c in Sources */, + DC196F6D1CBD77CD00A66F4B /* kc-15-key-update-valueref.c in Sources */, + DC6B466A1C90EE1A00D899C6 /* kc-10-item-add-internet.c in Sources */, + DC6B466B1C90EE1A00D899C6 /* kc-19-item-copy-internet.c in Sources */, + DC6B466C1C90EE1A00D899C6 /* kc-21-item-use-callback.c in Sources */, + DC6B466E1C90EE1A00D899C6 /* kc-04-is-valid.c in Sources */, + DC6B466F1C90EE1A00D899C6 /* kc-18-find-combined.c in Sources */, + DC336B3C1D246E4C00D24F15 /* kc-20-identity-find-stress.c in Sources */, + 87701A8E1C4B91E300CB437B /* kc-43-seckey-interop.m in Sources */, + DC9A61B51CCABD1F002793D6 /* kc-21-item-xattrs.c in Sources */, DC3C16001BAB76B50041A23A /* kc-30-xara.c in Sources */, AC9ADAD3199AD6BA00BDAF54 /* kc-42-trust-revocation.c in Sources */, - 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */, + DC2480511CC1B58B00527D67 /* kc-21-item-use-callback.c in Sources */, + DCE537591D2EE36800A12A95 /* kc-05-find-existing-items-locked.c in Sources */, + 0CBD509B16C3246D00713B6C /* kc-41-sececkey.m in Sources */, + DC19708A1CBEC2FA00A66F4B /* kc-15-item-update-label-skimaad.m in Sources */, 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */, + DC840D871CBEF5CB0083F55C /* kc-20-identity-persistent-refs.c in Sources */, + DC19708D1CBEE43E00A66F4B /* kc-16-item-update-password.c in Sources */, + DC9642751D25F4650073E0C5 /* kc-20-item-find-stress.c in Sources */, + DC9A61AF1CCAA4CF002793D6 /* kc-24-key-copy-keychains.c in Sources */, BED2BCA21B96217B006CF43A /* si-20-sectrust-provisioning.c in Sources */, + DC840D8E1CBF13C00083F55C /* kc-23-key-export-symmetric.m in Sources */, + DC840D911CBF17AF0083F55C /* kc-26-key-import-public.m in Sources */, + DC247FDB1CBF22AD00527D67 /* kc-27-key-non-extractable.c in Sources */, F92321381ACF69EE00634C21 /* si-34-one-true-keychain.c in Sources */, - 0CBD509A16C3246D00713B6C /* kc-40-seckey.c in Sources */, + DC9642771D25F5DD0073E0C5 /* kc-20-key-find-stress.c in Sources */, + DC196F6A1CBD70C100A66F4B /* kc-12-key-create-symmetric.c in Sources */, + DC7EFBA91CBC4448005F9624 /* kc-06-cert-search-email.m in Sources */, + 0CBD509A16C3246D00713B6C /* kc-40-seckey.m in Sources */, + DCA424031CB81EF20095B7DF /* kc-05-find-existing-items.c in Sources */, + DC9A61B21CCAAE05002793D6 /* kc-28-cert-sign.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1101,6 +1248,7 @@ 05012D46060B94A000C044CB /* SecImportExportCrypto.cpp in Sources */, 055EA6B106AC5C13005079CE /* TrustRevocation.cpp in Sources */, C26BA9FF072580AE0049AF3C /* UnlockReferralItem.cpp in Sources */, + 3A353D7D1CC50583000446F4 /* TokenLogin.cpp in Sources */, 058C797609F56CFB00DB7E98 /* SecTrustSettings.cpp in Sources */, 058C797C09F56D1400DB7E98 /* TrustSettings.cpp in Sources */, 058C797F09F56D1400DB7E98 /* TrustSettingsUtils.cpp in Sources */, @@ -1119,6 +1267,7 @@ 52B88DFB11DD0D2D005BCA6B /* SecFDERecoveryAsymmetricCrypto.cpp in Sources */, 48E66AE3120254D700E878AD /* SecRandom.c in Sources */, 52E950CD1509B47000DA6511 /* tsaDERUtilities.c in Sources */, + D4486BCF1C65528B0040880D /* SecTrustOSXEntryPoints.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1134,11 +1283,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 182BB341146F106C000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_utilitiesDTrace; - targetProxy = 182BB340146F106C000BF1F3 /* PBXContainerItemProxy */; - }; 521FBA8C112CB465002BEF54 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = libDER; @@ -1152,6 +1296,15 @@ baseConfigurationReference = 182BB225146F063C000BF1F3 /* debug.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../regressions", + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/../utilities", + "$(inherited)", + ); WARNING_CFLAGS = ( "$(inherited)", "-Wno-error=overloaded-virtual", @@ -1180,6 +1333,7 @@ GCC_MODEL_TUNING = G5; INFOPLIST_FILE = "xpc/XPCKeychainSandboxCheck-Info.plist"; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = XPCKeychainSandboxCheck; PROVISIONING_PROFILE = ""; SKIP_INSTALL = NO; @@ -1196,6 +1350,7 @@ GCC_MODEL_TUNING = G5; INFOPLIST_FILE = "xpc/XPCKeychainSandboxCheck-Info.plist"; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = XPCKeychainSandboxCheck; PROVISIONING_PROFILE = ""; SKIP_INSTALL = NO; @@ -1212,6 +1367,7 @@ GCC_MODEL_TUNING = G5; INFOPLIST_FILE = "xpc-tsa/XPCTimeStampingService-Info.plist"; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = XPCTimeStampingService; PROVISIONING_PROFILE = ""; SKIP_INSTALL = NO; @@ -1228,6 +1384,7 @@ GCC_MODEL_TUNING = G5; INFOPLIST_FILE = "xpc-tsa/XPCTimeStampingService-Info.plist"; INSTALL_PATH = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Security.framework/Versions/${FRAMEWORK_VERSION}/XPCServices"; + PRODUCT_BUNDLE_IDENTIFIER = "com.apple.security.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = XPCTimeStampingService; PROVISIONING_PROFILE = ""; SKIP_INSTALL = NO; @@ -1242,11 +1399,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", - "SECTRUST_OSX=0", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/libDER", + "SECTRUST_OSX=1", ); WARNING_CFLAGS = ( "$(inherited)", @@ -1262,11 +1415,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", - "SECTRUST_OSX=0", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/libDER", + "SECTRUST_OSX=1", ); WARNING_CFLAGS = ( "$(inherited)", @@ -1279,13 +1428,32 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB226146F063C000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../regressions", + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/../utilities", + "$(PROJECT_DIR)/libDER", + "$(inherited)", + ); + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -1293,13 +1461,30 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB226146F063C000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/../regressions", + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(BUILT_PRODUCTS_DIR)", + "$(PROJECT_DIR)/lib", + "$(PROJECT_DIR)/../utilities", + "$(PROJECT_DIR)/libDER", + "$(inherited)", + ); }; name = Release; }; diff --git a/OSX/libsecurity_keychain/regressions/kc-01-keychain-creation.c b/OSX/libsecurity_keychain/regressions/kc-01-keychain-creation.c new file mode 100644 index 00000000..c07b0517 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-01-keychain-creation.c @@ -0,0 +1,35 @@ +#include +#include + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +int kc_01_keychain_creation(int argc, char *const *argv) +{ + plan_tests(9); + + ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "disable ui"); + SecKeychainRef keychain = createNewKeychain("test", "test"); + SKIP: { + skip("can't continue without keychain", 2, ok(keychain, "keychain not NULL")); + + is(CFGetRetainCount(keychain), 1, "retaincount of created keychain is 1"); + } + + SecKeychainRef keychain2 = NULL; + ok_status(SecKeychainOpen("test", &keychain2), "SecKeychainOpen"); + SKIP: { + skip("can't continue without keychain", 2, ok(keychain, "keychain not NULL")); + CFIndex retCount = CFGetRetainCount(keychain2); + is(retCount, 2, "retaincount of created+opened keychain is 2"); // 2, because we opened and created the same keychain. + } + + is(keychain, keychain2, "SecKeychainCreate and SecKeychainOpen returned a different handle for the same keychain"); + + ok_status(SecKeychainDelete(keychain), "SecKeychainDelete"); + + CFRelease(keychain); + CFRelease(keychain2); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-02-unlock-noui.c b/OSX/libsecurity_keychain/regressions/kc-02-unlock-noui.c new file mode 100644 index 00000000..c7b310bb --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-02-unlock-noui.c @@ -0,0 +1,36 @@ +#include +#include + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +int kc_02_unlock_noui(int argc, char *const *argv) +{ + plan_tests(12); + + initializeKeychainTests(__FUNCTION__); + + ok_status(SecKeychainSetUserInteractionAllowed(FALSE), "SecKeychainSetUserInteractionAllowed(FALSE)"); + + SecKeychainRef keychain = createNewKeychain("test", "test"); + ok_status(SecKeychainLock(keychain), "SecKeychainLock"); + + is_status(SecKeychainUnlock(keychain, 0, NULL, FALSE), errSecAuthFailed, "SecKeychainUnlock"); + + checkPrompts(0, "Unexpected keychain access prompt unlocking after SecKeychainCreate"); + + ok_status(SecKeychainLock(keychain), "SecKeychainLock"); + CFRelease(keychain); + + ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen locked kc"); + + is_status(SecKeychainUnlock(keychain, 0, NULL, FALSE), errSecAuthFailed, "SecKeychainUnlock"); + + checkPrompts(0, "Unexpected keychain access prompt unlocking after SecKeychainCreate"); + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFRelease(keychain); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-03-keychain-list.c b/OSX/libsecurity_keychain/regressions/kc-03-keychain-list.c new file mode 100644 index 00000000..a2b41130 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-03-keychain-list.c @@ -0,0 +1,124 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +static void dumpSearchList(char * label, CFArrayRef searchList) { + printf("%s:\n", label); + + for(int i = 0; i < CFArrayGetCount(searchList); i++) { + char pathName[300]; + UInt32 len = sizeof(pathName); + + SecKeychainGetPath((SecKeychainRef) CFArrayGetValueAtIndex(searchList, i), &len, pathName); + printf(" %s\n", pathName); + } + printf("\n"); +} + +static CFComparisonResult compare(const void* first, const void* second, void* context) { + SecKeychainRef k1 = (SecKeychainRef) first; + SecKeychainRef k2 = (SecKeychainRef) second; + + char path1[200]; + char path2[200]; + UInt32 l1 = 200, l2 = 200; + + SecKeychainGetPath(k1, &l1, path1); + SecKeychainGetPath(k2, &l2, path2); + + return strcmp(path1, path2); +} + +// Checks that these lists are equal modulo order +static bool keychainListsEqual(CFArrayRef list1, CFArrayRef list2) { + + CFIndex size1 = CFArrayGetCount(list1); + CFIndex size2 = CFArrayGetCount(list2); + + if(size1 != size2) { + return false; + } + + CFMutableArrayRef m1 = CFArrayCreateMutableCopy(NULL, 0, list1); + CFMutableArrayRef m2 = CFArrayCreateMutableCopy(NULL, 0, list2); + + CFArraySortValues(m1, CFRangeMake(0, size1), &compare, NULL); + CFArraySortValues(m2, CFRangeMake(0, size2), &compare, NULL); + + bool result = CFEqual(m1, m2); + + CFRelease(m1); + CFRelease(m2); + + return result; +} + +static void tests() +{ + SecKeychainRef kc = getPopulatedTestKeychain(); + + CFArrayRef searchList = NULL; + ok_status(SecKeychainCopySearchList(&searchList), "%s: SecKeychainCopySearchList", testName); + dumpSearchList("initial", searchList); + + CFMutableArrayRef mutableSearchList = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(searchList) + 1, searchList); + CFArrayAppendValue(mutableSearchList, kc); + ok_status(SecKeychainSetSearchList(mutableSearchList), "%s: SecKeychainSetSearchList", testName); + dumpSearchList("to set", mutableSearchList); + + CFArrayRef midSearchList = NULL; + ok_status(SecKeychainCopySearchList(&midSearchList), "%s: SecKeychainCopySearchList (mid)", testName); + dumpSearchList("after set", midSearchList); + + ok(keychainListsEqual(mutableSearchList, midSearchList), "%s: retrieved search list equal to set search list", testName); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + CFArrayRef finalSearchList = NULL; + ok_status(SecKeychainCopySearchList(&finalSearchList), "%s: SecKeychainCopySearchList (final)", testName); + dumpSearchList("final", finalSearchList); + + ok(keychainListsEqual(finalSearchList, searchList), "%s: final search list equal to initial search list", testName); + + CFRelease(searchList); + CFRelease(mutableSearchList); + CFRelease(midSearchList); + CFRelease(finalSearchList); +} + +int kc_03_keychain_list(int argc, char *const *argv) +{ + plan_tests(9); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-12-status.c b/OSX/libsecurity_keychain/regressions/kc-03-status.c old mode 100755 new mode 100644 similarity index 81% rename from SecurityTests/regressions/kc/kc-12-status.c rename to OSX/libsecurity_keychain/regressions/kc-03-status.c index 68fb14af..696b0c9d --- a/SecurityTests/regressions/kc/kc-12-status.c +++ b/OSX/libsecurity_keychain/regressions/kc-03-status.c @@ -3,9 +3,8 @@ #include #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" static void tests(void) { @@ -16,10 +15,9 @@ static void tests(void) if (!home || strlen(home) > 200) plan_skip_all("home too big"); - sprintf(kcname1, "%s/kc1/kc1", home); + sprintf(kcname1, "%s/kctests/kc1/kc1", home); SecKeychainRef kc1 = NULL, kc2 = NULL; - ok_status(SecKeychainCreate(kcname1, 4, "test", FALSE, NULL, &kc1), - "SecKeychainCreate kc1"); + kc1 = createNewKeychainAt(kcname1, "test"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, @@ -36,7 +34,7 @@ static void tests(void) /* Make keychain non writable. */ char kcdir1[256]; - sprintf(kcdir1, "%s/kc1", home); + sprintf(kcdir1, "%s/kctests/kc1", home); ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); @@ -64,12 +62,8 @@ static void tests(void) "status unlocked readable"); } - sprintf(kcname2, "%s/kc2/kc2", home); - ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); - is_status(SecKeychainGetStatus(kc2, &status2), errSecNoSuchKeychain, - "get kc2 status"); - ok_status(SecKeychainCreate(kcname2, 4, "test", FALSE, NULL, &kc2), - "SecKeychainCreate kc2"); + sprintf(kcname2, "%s/kctests/kc2/kc2", home); + kc2 = createNewKeychainAt(kcname2, "test"); ok_unix(chmod(kcname2, 0444), "chmod kc2 0444"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, @@ -85,13 +79,13 @@ static void tests(void) /* Restore dir to writable so cleanup code will work ok. */ ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755"); + ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName); CFRelease(kc1); + ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName); CFRelease(kc2); bool testWithFreshlyCreatedKeychain = true; - SecKeychainRef keychain; - ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), - "SecKeychainCreate"); + SecKeychainRef keychain = createNewKeychain("test", "test"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); do { @@ -106,33 +100,32 @@ static void tests(void) is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); - CFRelease(keychain); - + if (testWithFreshlyCreatedKeychain) { + CFRelease(keychain); testWithFreshlyCreatedKeychain = false; ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); } - else + else { testWithFreshlyCreatedKeychain = true; + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFReleaseNull(keychain); + } } while(!testWithFreshlyCreatedKeychain); - tests_end(1); } -int main(int argc, char *const *argv) +int kc_03_status(int argc, char *const *argv) { plan_tests(43); - if (!tests_begin(argc, argv)) - BAIL_OUT("tests_begin failed"); tests(); - ok_leaks("leaks"); - return 0; } diff --git a/SecurityTests/regressions/kc/kc-26-is-valid.c b/OSX/libsecurity_keychain/regressions/kc-04-is-valid.c old mode 100755 new mode 100644 similarity index 68% rename from SecurityTests/regressions/kc/kc-26-is-valid.c rename to OSX/libsecurity_keychain/regressions/kc-04-is-valid.c index d17b05a2..eab88ad6 --- a/SecurityTests/regressions/kc/kc-26-is-valid.c +++ b/OSX/libsecurity_keychain/regressions/kc-04-is-valid.c @@ -6,9 +6,8 @@ #include #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" static void tests(void) { @@ -18,17 +17,18 @@ static void tests(void) if (!home || strlen(home) > 200) plan_skip_all("home too big"); - sprintf(kcname1, "%s/kc1", home); + sprintf(kcname1, "%s/kctests/kc1-16-is-valid", home); SecKeychainRef kc1 = NULL, kc2 = NULL; Boolean kc1valid, kc2valid; - ok_status(SecKeychainCreate(kcname1, 4, "test", FALSE, NULL, &kc1), - "SecKeychainCreate kc1"); + kc1 = createNewKeychainAt(kcname1, "test"); ok_status(SecKeychainIsValid(kc1, &kc1valid), "SecKeychainIsValid kc1"); is(kc1valid, TRUE, "is kc1 valid"); + + ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName); CFRelease(kc1); int fd; - sprintf(kcname2, "%s/kc2", home); + sprintf(kcname2, "%s/kctests/kc2-16-is-valid", home); ok_unix(fd = open(kcname2, O_CREAT|O_WRONLY|O_TRUNC, 0600), "create invalid kc2 file"); ok_unix(close(fd), "close the kc2 file"); @@ -40,20 +40,17 @@ static void tests(void) "TRUE"); is(kc2valid, FALSE, "is kc2 not valid"); } - CFRelease(kc2); - tests_end(1); + ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName); + CFRelease(kc2); } -int main(int argc, char *const *argv) +int kc_04_is_valid(int argc, char *const *argv) { - plan_tests(9); - if (!tests_begin(argc, argv)) - BAIL_OUT("tests_begin failed"); + plan_tests(11); tests(); - ok_leaks("leaks"); - + deleteTestFiles(); return 0; } diff --git a/OSX/libsecurity_keychain/regressions/kc-05-find-existing-items-locked.c b/OSX/libsecurity_keychain/regressions/kc-05-find-existing-items-locked.c new file mode 100644 index 00000000..3813e5a3 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-05-find-existing-items-locked.c @@ -0,0 +1,126 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" +#include "kc-key-helpers.h" + +static void tests() +{ + SecKeychainRef kc = getPopulatedTestKeychain(); + + CFMutableDictionaryRef query = NULL; + SecKeychainItemRef item = NULL; + + // Perform keychain upgrade so future calls will check integrity, then lock keychain + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + + ok_status(SecKeychainLock(kc), "%s: SecKeychainLock", testName); + + // Find passwords + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // keychain is locked; AuthFailed is what securityd throws if UI access is not allowed + CFReleaseNull(item); + checkPrompts(0, "after reading a password in locked keychain without UI"); // this should be 1, but is 0 due to how denying UI access works in Credentials + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service_restrictive_acl"), CFSTR("test_service_restrictive_acl")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); + CFReleaseNull(item); + checkPrompts(0, "trying to read password in locked keychain without UI"); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassGenericPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // keychain is locked + CFReleaseNull(item); + checkPrompts(0, "after reading a password in locked keychain without UI"); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassGenericPassword, CFSTR("test_service_restrictive_acl"), CFSTR("test_service_restrictive_acl")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + CFReleaseNull(item); + checkPrompts(0, "trying to read password in locked keychain without UI"); + + // Find symmetric keys + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric); + item = checkN(testName, query, 2); + CFReleaseNull(item); + + // Find asymmetric keys + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic); + item = checkN(testName, query, 2); + CFReleaseNull(item); + + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate); + item = checkN(testName, query, 2); + CFReleaseNull(item); + + // Find certificates + query = makeBaseQueryDictionary(kc, kSecClassCertificate); + item = checkN(testName, query, 3); + CFReleaseNull(item); + + // ensure we can pull data from a certificate + query = makeBaseQueryDictionary(kc, kSecClassCertificate); + CFDictionarySetValue(query, kSecMatchSubjectWholeString, CFSTR("test_codesigning")); + item = checkN(testName, query, 1); + const unsigned char expectedSHA1[] = { 0x94, 0xdf, 0x22, 0x4a, 0x4d, 0x49, 0x33, 0x27, 0x9e, 0xc5, 0x7e, 0x91, 0x95, 0xcc, 0xbd, 0x51, 0x3d, 0x59, 0xae, 0x34 }; + CFDataRef expectedSHAData = CFDataCreateWithBytesNoCopy(NULL, expectedSHA1, sizeof(expectedSHA1), kCFAllocatorNull); + eq_cf(SecCertificateGetSHA1Digest((SecCertificateRef) item), expectedSHAData, "%s: expected SHA1 of certificate does not match", testName); + CFReleaseNull(item); + CFReleaseNull(expectedSHAData); + + checkPrompts(0, "searching keys and certificates"); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); +} +#define nTests (getPopulatedTestKeychainTests + checkNTests + 1 + \ +checkNTests + readPasswordContentsWithResultTests + checkPromptsTests + \ +checkNTests + readPasswordContentsWithResultTests + checkPromptsTests + \ +checkNTests + readPasswordContentsWithResultTests + checkPromptsTests + \ +checkNTests + readPasswordContentsWithResultTests + checkPromptsTests + \ +checkNTests + \ +checkNTests + \ +checkNTests + \ +checkNTests + \ +checkNTests + 1 + \ +checkPromptsTests + 1) + +int kc_05_find_existing_items_locked(int argc, char *const *argv) +{ + plan_tests(nTests); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-05-find-existing-items.c b/OSX/libsecurity_keychain/regressions/kc-05-find-existing-items.c new file mode 100644 index 00000000..bd37c96e --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-05-find-existing-items.c @@ -0,0 +1,120 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" +#include "kc-key-helpers.h" + +static void tests() +{ + SecKeychainRef kc = getPopulatedTestKeychain(); + + CFMutableDictionaryRef query = NULL; + SecKeychainItemRef item = NULL; + + // Find passwords + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + readPasswordContents(item, CFSTR("test_password")); + CFReleaseNull(item); + checkPrompts(0, "after reading a password"); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service_restrictive_acl"), CFSTR("test_service_restrictive_acl")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + CFReleaseNull(item); + checkPrompts(1, "trying to read password without access"); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassGenericPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + readPasswordContents(item, CFSTR("test_password")); + CFReleaseNull(item); + checkPrompts(0, "after reading a password"); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassGenericPassword, CFSTR("test_service_restrictive_acl"), CFSTR("test_service_restrictive_acl")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + CFReleaseNull(item); + checkPrompts(1, "trying to read password without access"); + + // Find symmetric keys + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric); + item = checkN(testName, query, 2); + CFReleaseNull(item); + + // Find asymmetric keys + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic); + item = checkN(testName, query, 2); + CFReleaseNull(item); + + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate); + item = checkN(testName, query, 2); + CFReleaseNull(item); + + // Find certificates + query = makeBaseQueryDictionary(kc, kSecClassCertificate); + item = checkN(testName, query, 3); + CFReleaseNull(item); + + // ensure we can pull data from a certificate + query = makeBaseQueryDictionary(kc, kSecClassCertificate); + CFDictionarySetValue(query, kSecMatchSubjectWholeString, CFSTR("test_codesigning")); + item = checkN(testName, query, 1); + const unsigned char expectedSHA1[] = { 0x94, 0xdf, 0x22, 0x4a, 0x4d, 0x49, 0x33, 0x27, 0x9e, 0xc5, 0x7e, 0x91, 0x95, 0xcc, 0xbd, 0x51, 0x3d, 0x59, 0xae, 0x34 }; + CFDataRef expectedSHAData = CFDataCreateWithBytesNoCopy(NULL, expectedSHA1, sizeof(expectedSHA1), kCFAllocatorNull); + eq_cf(SecCertificateGetSHA1Digest((SecCertificateRef) item), expectedSHAData, "%s: expected SHA1 of certificate does not match", testName); + CFReleaseNull(item); + CFReleaseNull(expectedSHAData); + + checkPrompts(0, "searching keys and certificates"); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); +} +#define nTests (getPopulatedTestKeychainTests + \ + checkNTests + readPasswordContentsTests + checkPromptsTests + \ + checkNTests + readPasswordContentsTests + checkPromptsTests + \ + checkNTests + readPasswordContentsTests + checkPromptsTests + \ + checkNTests + readPasswordContentsTests + checkPromptsTests + \ + checkNTests + \ + checkNTests + \ + checkNTests + \ + checkNTests + \ + checkNTests + 1 + \ + checkPromptsTests + 1) + +int kc_05_find_existing_items(int argc, char *const *argv) +{ + plan_tests(nTests); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-06-cert-search-email.m b/OSX/libsecurity_keychain/regressions/kc-06-cert-search-email.m new file mode 100644 index 00000000..3f04c49f --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-06-cert-search-email.m @@ -0,0 +1,207 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" +#include "kc-key-helpers.h" + +#import + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static NSString* printDataAsHex( + const CSSM_DATA *d) +{ + if (!d || !d->Data) return NULL; + + unsigned int i; + CSSM_SIZE len = d->Length; + uint8 *cp = d->Data; + NSString *str = [NSString string]; + + for(i=0; i #include -#include "testmore.h" -#include "testenv.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" /* Cert File Name: keybank_v3.101.cer */ static const uint8 keybank_der_bytes[] = @@ -193,23 +193,18 @@ certTests(SecKeychainRef keychain) } int -main(int argc, char * const *argv) +kc_10_item_add_certificate(int argc, char * const *argv) { plan_tests(33); - if (!tests_begin(argc, argv)) - return 255; /* Test with autocommit on. */ - SecKeychainRef keychain = NULL; - ok_status(SecKeychainCreate("test.keychain", 4, "test", FALSE, NULL, - &keychain), "SecKeychainCreate"); + SecKeychainRef keychain = createNewKeychain("test.keychain", "test"); ok(keychain, "keychain non NULL"); certTests(keychain); /* Test with autocommit off. */ keychain = NULL; - ok_status(SecKeychainCreate("test2.keychain", 4, "test", FALSE, NULL, - &keychain), "SecKeychainCreate"); + keychain = createNewKeychain("test2.keychain", "test"); ok(keychain, "keychain non NULL"); CSSM_DL_DB_HANDLE cspdl_dldb = {}; ok_status(SecKeychainGetDLDBHandle(keychain, &cspdl_dldb), @@ -223,5 +218,6 @@ main(int argc, char * const *argv) (const void *)FALSE, NULL), "autocommit off"); certTests(keychain); - return !tests_end(1); + deleteTestFiles(); + return 0; } diff --git a/SecurityTests/regressions/kc/kc-15-item-add-generic.c b/OSX/libsecurity_keychain/regressions/kc-10-item-add-generic.c old mode 100755 new mode 100644 similarity index 73% rename from SecurityTests/regressions/kc/kc-15-item-add-generic.c rename to OSX/libsecurity_keychain/regressions/kc-10-item-add-generic.c index c9f778cc..f22e12f8 --- a/SecurityTests/regressions/kc/kc-15-item-add-generic.c +++ b/OSX/libsecurity_keychain/regressions/kc-10-item-add-generic.c @@ -3,15 +3,12 @@ #include #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" -void tests(void) +static void tests(void) { - SecKeychainRef keychain; - ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), - "create keychain"); + SecKeychainRef keychain = getPopulatedTestKeychain(); SecKeychainItemRef item = NULL; ok_status(SecKeychainAddGenericPassword(keychain, 7, "service", 7, "account", 4, "test", &item), "add generic password"); @@ -32,7 +29,8 @@ void tests(void) UInt32 length = 0; void *data = NULL; ok_status(SecKeychainItemCopyContent(item, &itemClass, &attrList, &length, &data), "SecKeychainItemCopyContent"); - ok_status(SecKeychainItemFreeContent(&attrList, data), "SecKeychainItemCopyContent"); + eq_string(data, "test", "Item data is wrong"); + ok_status(SecKeychainItemFreeContent(&attrList, data), "SecKeychainItemCopyContent"); is(CFGetRetainCount(item), 1, "item retaincount is 1"); is(CFGetRetainCount(keychain), 2, "keychain retaincount is 2"); @@ -42,16 +40,13 @@ void tests(void) CFRelease(keychain); } -int main(int argc, char *const *argv) +int kc_10_item_add_generic(int argc, char *const *argv) { + initializeKeychainTests("kc-10-item-add-generic"); plan_tests(13); - if (!tests_begin(argc, argv)) - BAIL_OUT("tests_begin failed"); - tests(); - ok(tests_end(1), "cleanup"); - ok_leaks("no leaks"); + deleteTestFiles(); return 0; } diff --git a/SecurityTests/regressions/kc/kc-18-item-find-internet.c b/OSX/libsecurity_keychain/regressions/kc-10-item-add-internet.c old mode 100755 new mode 100644 similarity index 77% rename from SecurityTests/regressions/kc/kc-18-item-find-internet.c rename to OSX/libsecurity_keychain/regressions/kc-10-item-add-internet.c index 49899b66..1619e65a --- a/SecurityTests/regressions/kc/kc-18-item-find-internet.c +++ b/OSX/libsecurity_keychain/regressions/kc-10-item-add-internet.c @@ -3,15 +3,12 @@ #include #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" -void tests(int dont_skip) +static void tests() { - SecKeychainRef keychain; - ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), - "create keychain"); + SecKeychainRef keychain = createNewKeychain("test", "test"); SecKeychainItemRef item = NULL; ok_status(SecKeychainAddInternetPassword(keychain, 19, "members.spamcop.net", @@ -35,7 +32,7 @@ void tests(int dont_skip) CFRelease(item); item = NULL; - ok_status(SecKeychainFindInternetPassword(NULL, + ok_status(SecKeychainFindInternetPassword(keychain, 19, "members.spamcop.net", 0, NULL, 0, NULL, @@ -84,31 +81,25 @@ void tests(int dont_skip) }; SKIP: { skip(" 6L60 Malloc/free misuse in " - "SecKeychainItemCopyContent()", 1, dont_skip); + "SecKeychainItemCopyContent()", 1, 1); is_status(SecKeychainItemCopyContent(item, &itemClass, &attrList2, NULL, NULL), errSecNoSuchAttr, "SecKeychainItemCopyContent fails"); } is(CFGetRetainCount(item), 1, "item retaincount is 1"); - is(CFGetRetainCount(keychain), 2, "keychain retaincount is 2"); + cmp_ok(CFGetRetainCount(keychain), >=, 2, "keychain retaincount is at least 2"); CFRelease(item); - is(CFGetRetainCount(keychain), 1, "keychain retaincount is 1"); + cmp_ok(CFGetRetainCount(keychain), >=, 1, "keychain retaincount is at least 1"); ok_status(SecKeychainDelete(keychain), "delete keychain"); CFRelease(keychain); } -int main(int argc, char *const *argv) +int kc_10_item_add_internet(int argc, char *const *argv) { - int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); + plan_tests(19); - plan_tests(21); - - if (!tests_begin(argc, argv)) - BAIL_OUT("tests_begin failed"); - - tests(dont_skip); - ok(tests_end(1), "cleanup"); - ok_leaks("no leaks"); + tests(); + deleteTestFiles(); return 0; } diff --git a/SecurityTests/regressions/kc/kc-17-item-find-key.c b/OSX/libsecurity_keychain/regressions/kc-12-item-create-keypair.c old mode 100755 new mode 100644 similarity index 87% rename from SecurityTests/regressions/kc/kc-17-item-find-key.c rename to OSX/libsecurity_keychain/regressions/kc-12-item-create-keypair.c index eb4024d8..84744f8d --- a/SecurityTests/regressions/kc/kc-17-item-find-key.c +++ b/OSX/libsecurity_keychain/regressions/kc-12-item-create-keypair.c @@ -4,15 +4,12 @@ #include #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" -void tests(void) +static void tests(void) { - SecKeychainRef keychain; - ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), - "create keychain"); + SecKeychainRef keychain = createNewKeychain("test", "test"); SecKeyRef pub_crypt = NULL, prv_crypt = NULL; ok_status(SecKeyCreatePair(keychain, CSSM_ALGID_RSA, 256, 0 /* contextHandle */, @@ -82,20 +79,17 @@ void tests(void) CFRelease(prv_crypt); CFRelease(pub_sign); CFRelease(prv_sign); - CFRelease(keychain); - ok(tests_end(1), "cleanup"); + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFRelease(keychain); } -int main(int argc, char *const *argv) +int kc_17_item_find_key(int argc, char *const *argv) { - plan_tests(14); - - if (!tests_begin(argc, argv)) - BAIL_OUT("tests_begin failed"); + plan_tests(13); tests(); - ok_leaks("no leaks"); + deleteTestFiles(); return 0; } diff --git a/OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric-and-use.m b/OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric-and-use.m new file mode 100644 index 00000000..3cbfec92 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric-and-use.m @@ -0,0 +1,258 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#define nullptr NULL + +#import + +static NSString * const EncryptionKeyLabel = @"Test Encryption Key"; + +// +// This function allows finer-grained access control settings; +// the given application list is trusted only for one specific authorization +// (e.g. kSecACLAuthorizationDecrypt). Note that if trustedApplications +// is NULL, this means "allow any application", while an empty (zero-length) +// list means "no applications have access". +// Returns true if the ACL was modified successfully, otherwise false. +// +static bool setTrustedApplicationsForACLAuthorization(SecAccessRef access, + CFTypeRef authorizationTag, NSArray* trustedApplications) +{ + // get the access control list for this authorization tag) + CFArrayRef aclList = SecAccessCopyMatchingACLList(access, authorizationTag); + if (!aclList) + return false; + + // get the first entry in the access control list + SecACLRef aclRef=(SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + CFArrayRef appList=nil; + CFStringRef promptDescription=nil; + SecKeychainPromptSelector promptSelector; + OSStatus err = SecACLCopyContents(aclRef, &appList, &promptDescription, &promptSelector); + ok_status(err, "%s: SecACLCopyContents", testName); + + if (!trustedApplications) // "allow all applications to access this item" + { + // change the ACL to not require the passphrase, and have a nil application list. + promptSelector &= ~kSecKeychainPromptRequirePassphase; + err = SecACLSetContents(aclRef, NULL, promptDescription, promptSelector); + ok_status(err, "%s: SecACLSetContents (allow all)", testName); + } + else // "allow access by these applications" + { + // modify the application list + err = SecACLSetContents(aclRef, (CFArrayRef)trustedApplications, promptDescription, promptSelector); + ok_status(err, "%s: SecACLSetContents", testName); + } + + if (appList) CFRelease(appList); + if (promptDescription) CFRelease(promptDescription); + + CFRelease(aclList); + return (!err); +} + +// +// This function returns a SecAccessRef, which the caller owns and must release. +// Note that if the provided item is not NULL, its existing access reference is returned, +// otherwise a new access reference is created. +// +static SecAccessRef createAccess(SecKeychainItemRef item, NSString *accessLabel, BOOL allowAny) +{ + OSStatus err; + SecAccessRef access=nil; + NSArray *trustedApplications=nil; + + if (!allowAny) // use default access ("confirm access") + { + // make an exception list of applications you want to trust, + // which are allowed to access the item without requiring user confirmation + SecTrustedApplicationRef myself, someOther; + err = SecTrustedApplicationCreateFromPath(NULL, &myself); + ok_status(err, "%s: SecTrustedApplicationCreateFromPath (1)", testName); + err = SecTrustedApplicationCreateFromPath("/Applications/Safari.app", &someOther); + ok_status(err, "%s: SecTrustedApplicationCreateFromPath (2)", testName); + trustedApplications = [NSArray arrayWithObjects:(id)myself, (id)someOther, nil]; + } + + // If the keychain item already exists, use its access reference; otherwise, create a new one + if (item) { + err = SecKeychainItemCopyAccess(item, &access); + ok_status(err, "%s: SecKeychainItemCopyAccess", testName); + } else { + err = SecAccessCreate((CFStringRef)accessLabel, (CFArrayRef)trustedApplications, &access); + ok_status(err, "%s: SecAccessCreate", testName); + } + + if (err) return nil; + + // At this point we have a SecAccessRef which permits "decrypt" access to the item + // only by apps in our trustedApplications list. We could return at this point. + // + // To set up other types of access, we need to do more work. + // In this example, we'll explicitly set the access control for decrypt and encrypt operations. + // + setTrustedApplicationsForACLAuthorization(access, kSecACLAuthorizationEncrypt, (allowAny) ? NULL : trustedApplications); + setTrustedApplicationsForACLAuthorization(access, kSecACLAuthorizationDecrypt, (allowAny) ? NULL : trustedApplications); + + return access; +} + +static SecKeyRef findExistingEncryptionKey(SecKeychainRef kc) +{ + SecKeyRef key; + NSArray* searchList = @[(__bridge id) kc]; + NSDictionary *query = @{ (__bridge id)kSecMatchSearchList: searchList, + (__bridge id)kSecClass: (__bridge id)kSecClassKey, + (__bridge id)kSecAttrApplicationLabel: EncryptionKeyLabel, + (__bridge id)kSecReturnRef: @YES }; + if (!SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&key)) + return key; + + return nullptr; +} + +static SecKeyRef generateEncryptionKey(SecKeychainRef kc) +{ + SecAccessRef access = createAccess(nil, EncryptionKeyLabel, false); + if (!access) { + NSLog(@"Creating an access object failed."); + return nullptr; + } + + CFErrorRef error = NULL; + NSDictionary *keyParameters = @{ (__bridge id)kSecUseKeychain: (__bridge id)kc, + (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeAES, + (__bridge id)kSecAttrKeySizeInBits: @(256), + (__bridge id)kSecAttrCanEncrypt: @YES, + (__bridge id)kSecAttrCanDecrypt: @YES, + (__bridge id)kSecAttrIsPermanent: @YES, + (__bridge id)kSecAttrAccess: (__bridge id)access, + (__bridge id)kSecAttrLabel: EncryptionKeyLabel, + (__bridge id)kSecAttrApplicationLabel: EncryptionKeyLabel }; + SecKeyRef key = SecKeyGenerateSymmetric((__bridge CFDictionaryRef)keyParameters, &error); + + is(error, NULL, "%s: SecKeyGenerateSymmetric", testName); + ok(key, "%s: SecKeyGenerateSymmetric returned a key", testName); + + if (!key) + NSLog(@"Creating encryption key failed: %@", error); + + CFRelease(access); + return key; +} + +static SecKeyRef findOrGenerateEncryptionKey(SecKeychainRef kc) +{ + SecKeyRef key = findExistingEncryptionKey(kc); + if (key) + return key; + + return generateEncryptionKey(kc); +} + +static SecKeyRef encryptionKey(SecKeychainRef kc) +{ + static SecKeyRef key = NULL; + if (!key) { + key = findOrGenerateEncryptionKey(kc); + } + return key; +} + +static NSData *encryptData(SecKeychainRef kc, NSData *plainTextData) +{ + SecTransformRef transform = SecEncryptTransformCreate(encryptionKey(kc), nullptr); + SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, nullptr); + SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, nullptr); + SecTransformSetAttribute(transform, kSecTransformInputAttributeName, (__bridge CFDataRef)plainTextData, nullptr); + + CFErrorRef error = 0; + NSData *result = CFBridgingRelease(SecTransformExecute(transform, &error)); + CFRelease(transform); + is(error, NULL, "%s: SecTransformExecute (encrypt)", testName); + + if (!result) { + NSLog(@"Encrypting data failed: %@", error); + CFRelease(error); + return nil; + } + + return result; +} + +static NSData *decryptData(SecKeychainRef kc, NSData *cipherTextData) +{ + SecTransformRef transform = SecDecryptTransformCreate(encryptionKey(kc), nullptr); + SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, nullptr); + SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, nullptr); + SecTransformSetAttribute(transform, kSecTransformInputAttributeName, (__bridge CFDataRef)cipherTextData, nullptr); + + CFErrorRef error = 0; + NSData *result = CFBridgingRelease(SecTransformExecute(transform, &error)); + is(error, NULL, "%s: SecTransformExecute (decrypt)", testName); + + CFRelease(transform); + if (!result) { + NSLog(@"Decrypting data failed: %@", error); + CFRelease(error); + return nil; + } + + return result; +} + +int kc_12_key_create_symmetric_and_use(int argc, char *const *argv) +{ + plan_tests(17); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + @autoreleasepool { + NSData *data = [@"Hello, world!" dataUsingEncoding:NSUTF8StringEncoding]; + NSLog(@" Original: %@", data); + NSData *encryptedData = encryptData(kc, data); + NSLog(@"Encrypted: %@", encryptedData); + if (encryptedData) { + NSData *roundtrippedData = decryptData(kc, encryptedData); + + eq_cf(roundtrippedData, data, "%s: Round-tripped data does not match original data", testName); + NSLog(@"Decrypted: %@", roundtrippedData); + } + } + + checkPrompts(0, "no prompts during test"); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + deleteTestFiles(); + return 0; +} + diff --git a/OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric.c b/OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric.c new file mode 100644 index 00000000..9c3b6eb4 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-12-key-create-symmetric.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +static void tests() +{ + SecKeychainRef keychain = createNewKeychain("test", "test"); + + /* Symmetric key tests. */ + + ok_status(SecKeyGenerate(keychain, CSSM_ALGID_AES, 128, + 0 /* contextHandle */, + CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, NULL), "SecKeyGenerate"); + + uint32 btrue = 1; + SecKeychainAttribute sym_attrs[] = + { + { kSecKeyEncrypt, sizeof(btrue), &btrue } + }; + SecKeychainAttributeList sym_attr_list = + { sizeof(sym_attrs) / sizeof(*sym_attrs), sym_attrs }; + SecKeychainSearchRef search = NULL; + ok_status(SecKeychainSearchCreateFromAttributes(keychain, + CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &sym_attr_list, &search), + "create symmetric encryption key search"); + SecKeychainItemRef item = NULL; + ok_status(SecKeychainSearchCopyNext(search, &item), "get first key"); + + if (item) CFRelease(item); + is_status(SecKeychainSearchCopyNext(search, &item), + errSecItemNotFound, "copy next returns no more keys"); + CFRelease(search); + + ok_status(SecKeychainSearchCreateFromAttributes(keychain, + CSSM_DL_DB_RECORD_ANY, NULL, &search), + "create any item search"); + item = NULL; + + ok_status(SecKeychainSearchCopyNext(search, &item), "get first key"); + + if (item) CFRelease(item); + + is_status(SecKeychainSearchCopyNext(search, &item), + errSecItemNotFound, "copy next returns no more keys"); + CFRelease(search); + + SecKeyRef aes_key2 = NULL; + ok_status(SecKeyGenerate(keychain, CSSM_ALGID_AES, 128, + 0 /* contextHandle */, + CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, &aes_key2), "SecKeyGenerate and get key"); + + is(CFGetRetainCount(aes_key2), 1, "retain count is 1"); + CFRelease(aes_key2); + + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFRelease(keychain); +} + +int kc_12_key_create_symmetric(int argc, char *const *argv) +{ + plan_tests(11); + + tests(); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-15-item-update-label-skimaad.m b/OSX/libsecurity_keychain/regressions/kc-15-item-update-label-skimaad.m new file mode 100644 index 00000000..81870078 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-15-item-update-label-skimaad.m @@ -0,0 +1,169 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" + +#import +#include +#include +#include + +//Call SecKeychainAddGenericPassword to add a new password to the keychain: +static OSStatus StorePasswordKeychain (SecKeychainRef keychain, void* password,UInt32 passwordLength) +{ + OSStatus status; + status = SecKeychainAddGenericPassword ( + keychain, + 10, // length of service name + "SurfWriter", // service name + 10, // length of account name + "MyUserAcct", // account name + passwordLength, // length of password + password, // pointer to password data + NULL // the item reference + ); + + ok_status(status, "%s: SecKeychainAddGenericPassword", testName); + return (status); +} + +//Call SecKeychainFindGenericPassword to get a password from the keychain: +static OSStatus GetPasswordKeychain (SecKeychainRef keychain, void *passwordData,UInt32 *passwordLength,SecKeychainItemRef *itemRef) +{ + OSStatus status; + + + status = SecKeychainFindGenericPassword ( + keychain, + 10, // length of service name + "SurfWriter", // service name + 10, // length of account name + "MyUserAcct", // account name + passwordLength, // length of password + passwordData, // pointer to password data + itemRef // the item reference + ); + ok_status(status, "%s: SecKeychainFindGenericPassword", testName); + return (status); +} + +//Call SecKeychainItemModifyAttributesAndData to change the password for an item already in the keychain: +static OSStatus ChangePasswordKeychain (SecKeychainItemRef itemRef) +{ + OSStatus status; + void * password = "myNewP4sSw0rD"; + UInt32 passwordLength = (UInt32) strlen(password); + void * label = "New Item Label"; + UInt32 labelLength = (UInt32) strlen(label); + + NSString *account = @"New Account"; + NSString *service = @"New Service"; + const char *serviceUTF8 = [service UTF8String]; + const char *accountUTF8 = [account UTF8String]; + +//%%% IMPORTANT: While SecKeychainItemCreateFromContent() will accept a kSecLabelItemAttr, it cannot +// be changed later via SecKeychainItemModifyAttributesAndData(). ##### THIS IS A BUG. ##### +// To work around the bug, pass 7 instead of kSecLabelItemAttr. This value is the index of the label +// attribute in the database schema (and in the SecItemAttr enumeration). +// +//#define LABEL_ITEM_ATTR_TAG 7 +#define LABEL_ITEM_ATTR_TAG kSecLabelItemAttr + + // set up attribute vector (each attribute consists of {tag, length, pointer}) + SecKeychainAttribute attrs[] = { + { LABEL_ITEM_ATTR_TAG, labelLength, (char *)label }, + { kSecAccountItemAttr, (UInt32) strlen(accountUTF8), (char *)accountUTF8 }, + { kSecServiceItemAttr, (UInt32) strlen(serviceUTF8), (char *)serviceUTF8 } }; + const SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs }; + + + status = SecKeychainItemModifyAttributesAndData ( + itemRef, // the item reference + &attributes, // attributes to change + passwordLength, // length of password + password // pointer to password data + ); + ok_status(status, "%s: SecKeychainItemModifyAttributesAndData", testName); + return (status); +} + +int kc_15_item_update_label_skimaad(int argc, char *const *argv) +{ + plan_tests(27); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef keychain = getPopulatedTestKeychain(); + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + OSStatus status; + OSStatus status1; + SInt32 status3; + CFStringRef theLabel = CFSTR("Notice"); + + CFStringRef theStatusStr = nil; + + void * myPassword = "myP4sSw0rD"; + UInt32 myPasswordLength = (UInt32) strlen(myPassword); + void *passwordData = nil; // will be allocated and filled in by SecKeychainFindGenericPassword + UInt32 passwordLength = 0; + SecKeychainItemRef itemRef = nil; + + StorePasswordKeychain(keychain, myPassword, myPasswordLength); + + itemRef = checkN(testName, makeQueryCustomItemDictionaryWithService(keychain, kSecClassGenericPassword, CFSTR("SurfWriter"), CFSTR("SurfWriter")), 1); + checkN(testName, makeQueryCustomItemDictionaryWithService(keychain, kSecClassGenericPassword, CFSTR("New Item Label"), CFSTR("New Service")), 0); + readPasswordContents(itemRef, CFSTR("myP4sSw0rD")); + CFReleaseNull(itemRef); + + GetPasswordKeychain (keychain, &passwordData,&passwordLength,&itemRef); //Call SecKeychainFindGenericPassword + + /* + free the data allocated by SecKeychainFindGenericPassword: + */ + status = SecKeychainItemFreeContent ( + NULL, //No attribute data to release + passwordData //Release data buffer allocated by SecKeychainFindGenericPassword + ); + ok_status(status, "%s: SecKeychainItemFreeContent", testName); + + ChangePasswordKeychain(itemRef); + + checkN(testName, makeQueryCustomItemDictionaryWithService(keychain, kSecClassGenericPassword, CFSTR("SurfWriter"), CFSTR("SurfWriter")), 0); + itemRef = checkN(testName, makeQueryCustomItemDictionaryWithService(keychain, kSecClassGenericPassword, CFSTR("New Item Label"), CFSTR("New Service")), 1); + readPasswordContents(itemRef, CFSTR("myNewP4sSw0rD")); + CFReleaseNull(itemRef); + + [pool release]; + + checkPrompts(0, "no prompts during test"); + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFReleaseNull(keychain); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-15-key-update-valueref.c b/OSX/libsecurity_keychain/regressions/kc-15-key-update-valueref.c new file mode 100644 index 00000000..5d8f4682 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-15-key-update-valueref.c @@ -0,0 +1,301 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// Tests the SecItemUpdate function. +// Currently this is a simple test to determine whether the correct item +// is updated when specified by a kSecValueRef (see ). +// + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" +#include "kc-key-helpers.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static int quiet = 0; +static int debug = 1; +static int verbose = 1; + +#define MAXNAMELEN MAXPATHLEN +#define MAXITEMS INT32_MAX + +#pragma mark -- Utility Functions -- + + +static void PrintTestResult(char *testStr, OSStatus status, OSStatus expected) +{ + if (verbose) { + fprintf(stdout, "%s: %s (result=%d, expected=%d)\n", testStr, + (status==expected) ? "OK" : "FAILED", + (int)status, (int)expected); + } + if (debug) { + fprintf(stdout, "\n"); + } + fflush(stdout); +} + +static void PrintCFStringWithFormat(const char *formatStr, CFStringRef inStr) +{ + char *buf = (char*)malloc(MAXNAMELEN); + if (buf) { + if (CFStringGetCString(inStr, buf, (CFIndex)MAXNAMELEN, kCFStringEncodingUTF8)) { + fprintf(stdout, formatStr, buf); + fflush(stdout); + } + free(buf); + } +} + +const CFStringRef gPrefix = CFSTR("Test Key"); +const CFStringRef gLabel = CFSTR("Test AES Encryption Key"); +const CFStringRef gUUID = CFSTR("550e8400-e29b-41d4-a716-446655441234"); + +// CreateSymmetricKey will create a new AES-128 symmetric encryption key +// with the provided label, application label, and application tag. +// Each of those attributes is optional, but only the latter two +// (application label and application tag) are considered part of the +// key's "unique" attribute set. Previously, if you attempted to create a +// key which differs only in the label attribute (but not in the other two) +// then the attempt would fail and leave a "turd" key with no label in your +// keychain: , fixed in 11A268a. + +static int CreateSymmetricKey( + SecKeychainRef inKeychain, + CFStringRef keyLabel, + CFStringRef keyAppLabel, + CFStringRef keyAppTag, + OSStatus expected) +{ + OSStatus status; + int keySizeValue = 128; + CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); + + // get a SecKeychainRef for the keychain in which we want the key to be created + // (this step is optional, but if omitted, the key is NOT saved in any keychain!) + SecKeychainRef keychain = NULL; + if (inKeychain == NULL) + status = SecKeychainCopyDefault(&keychain); + else + keychain = (SecKeychainRef) CFRetain(inKeychain); + + // create a SecAccessRef to set up the initial access control settings for this key + // (this step is optional; if omitted, the creating application has access to the key) + // note: the access descriptor should be the same string as will be used for the item's label, + // since it's the string that is displayed by the access confirmation dialog to describe the item. + SecAccessRef access = NULL; + status = SecAccessCreate(gLabel, NULL, &access); + + // create a dictionary of parameters describing the key we want to create + CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFDictionaryAddValue( params, kSecClass, kSecClassKey ); + CFDictionaryAddValue( params, kSecUseKeychain, keychain ); + CFDictionaryAddValue( params, kSecAttrAccess, access ); + CFDictionaryAddValue( params, kSecAttrKeyClass, kSecAttrKeyClassSymmetric ); + CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeAES ); + CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); + CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue ); + CFDictionaryAddValue( params, kSecAttrCanEncrypt, kCFBooleanTrue ); + CFDictionaryAddValue( params, kSecAttrCanDecrypt, kCFBooleanTrue ); + CFDictionaryAddValue( params, kSecAttrCanWrap, kCFBooleanFalse ); + CFDictionaryAddValue( params, kSecAttrCanUnwrap, kCFBooleanFalse ); + if (keyLabel) + CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); + if (keyAppLabel) + CFDictionaryAddValue( params, kSecAttrApplicationLabel, keyAppLabel ); + if (keyAppTag) + CFDictionaryAddValue( params, kSecAttrApplicationTag, keyAppTag ); + + // generate the key + CFErrorRef error = NULL; + SecKeyRef key = SecKeyGenerateSymmetric(params, &error); + + // print result and clean up + if (debug) { + if (key == NULL) { + CFStringRef desc = (error) ? CFErrorCopyDescription(error) : CFRetain(CFSTR("(no result!")); + PrintCFStringWithFormat("SecKeyGenerateSymmetric failed: %s\n", desc); + CFRelease(desc); + } + else { + CFStringRef desc = CFCopyDescription(key); + PrintCFStringWithFormat("SecKeyGenerateSymmetric succeeded: %s\n", desc); + CFRelease(desc); + } + } + status = (error) ? (OSStatus) CFErrorGetCode(error) : noErr; +// if (status == errSecDuplicateItem) +// status = noErr; // it's OK if the key already exists + + if (key) CFRelease(key); + if (error) CFRelease(error); + if (params) CFRelease(params); + if (keychain) CFRelease(keychain); + if (access) CFRelease(access); + + PrintTestResult("CreateSymmetricKey", status, expected); + + return status; +} + +static int TestUpdateItems(SecKeychainRef keychain) +{ + int result = 0; + OSStatus status = errSecSuccess; + + // first, create a symmetric key + CFGregorianDate curGDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), NULL); + CFStringRef curDateLabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%4d-%02d-%02d)"), + gPrefix, (int) (curGDate.year), (int) (curGDate.month), (int) (curGDate.day)); + CFStringRef curAppTag = CFSTR("SecItemUpdate"); + + status = CreateSymmetricKey(keychain, curDateLabel, gUUID, curAppTag, noErr); + if (status && status != errSecDuplicateItem) + ++result; + + CFStringRef keyLabel = CFSTR("iMessage test key"); + CFStringRef newLabel = CFSTR("iMessage test PRIVATE key"); + + // create a new 1024-bit RSA key pair + SecKeyRef publicKey = NULL; + SecKeyRef privateKey = NULL; + CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + int keySizeValue = 1024; + CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); + + CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA ); + CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); + CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); +// CFDictionaryAddValue( params, kSecAttrAccess, access ); +// %%% note that SecKeyGeneratePair will create the key pair in the default keychain +// if a keychain is not given via the kSecUseKeychain parameter. + CFDictionaryAddValue( params, kSecUseKeychain, keychain ); + + status = SecKeyGeneratePair(params, &publicKey, &privateKey); + ok_status(status, "%s: SecKeyGeneratePair", testName); + if (status != noErr) { + ++result; + } + PrintTestResult("TestUpdateItems: generating key pair", status, noErr); + + // Make sure we have the key of interest + checkN(testName, makeQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, keyLabel), 1); + checkN(testName, makeQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, newLabel), 0); + + // create a query which will match just the private key item (based on its known reference) + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); +// CFArrayRef itemList = CFArrayCreate(NULL, (const void**) &privateKey, 1, &kCFTypeArrayCallBacks); +// %%% note that kSecClass seems to be a required query parameter even though +// kSecMatchItemList is provided; that looks like it could be a bug... + CFDictionaryAddValue( query, kSecClass, kSecClassKey ); +// CFDictionaryAddValue( query, kSecAttrKeyClass, kSecAttrKeyClassPrivate ); + +// %%% pass the private key ref, instead of the item list, to test +// CFDictionaryAddValue( query, kSecMatchItemList, itemList ); + CFDictionaryAddValue( query, kSecValueRef, privateKey ); + + // create dictionary of changed attributes for the private key + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + SecAccessRef access = NULL; + + status = SecAccessCreate(newLabel, NULL, &access); + ok_status(status, "%s: SecAccessCreate", testName); + if (status != noErr) { + ++result; + } + PrintTestResult("TestUpdateItems: creating access", status, noErr); + +//%%% note that changing the access for this key causes a dialog, +// so leave this out for the moment (uncomment to test that access change works). +// Normally the desired access should be passed into the SecKeyGeneratePair function. +// so there is no need for a dialog later. +// CFDictionaryAddValue( attrs, kSecAttrAccess, access ); + CFDictionaryAddValue( attrs, kSecAttrLabel, newLabel ); + + // update the private key with the new attributes + status = SecItemUpdate( query, attrs ); + ok_status(status, "%s: SecItemUpdate", testName); + + if (status != noErr) { + ++result; + } + PrintTestResult("TestUpdateItems: updating item", status, noErr); + + // Make sure label changed + checkN(testName, makeQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, keyLabel), 0); + checkN(testName, makeQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, newLabel), 1); + + if (publicKey) + CFRelease(publicKey); + if (privateKey) + CFRelease(privateKey); + if (access) + CFRelease(access); + + if (params) + CFRelease(params); + if (query) + CFRelease(query); + if (attrs) + CFRelease(attrs); + + return result; +} + +int kc_15_key_update_valueref(int argc, char *const *argv) +{ + plan_tests(20); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef keychain = getPopulatedTestKeychain(); + + TestUpdateItems(keychain); + + checkPrompts(0, "no prompts during test"); + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFRelease(keychain); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-16-item-update-password.c b/OSX/libsecurity_keychain/regressions/kc-16-item-update-password.c new file mode 100644 index 00000000..50ad886b --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-16-item-update-password.c @@ -0,0 +1,94 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" + +static void tests() +{ + SecKeychainRef kc = getPopulatedTestKeychain(); + + CFMutableDictionaryRef query = NULL; + SecKeychainItemRef item = NULL; + + // Find passwords + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + readPasswordContents(item, CFSTR("test_password")); checkPrompts(0, "after reading a password"); + changePasswordContents(item, CFSTR("new_password")); checkPrompts(0, "changing a internet password"); + readPasswordContents(item, CFSTR("new_password")); checkPrompts(0, "reading a changed internet password"); + CFReleaseNull(item); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service_restrictive_acl"), CFSTR("test_service_restrictive_acl")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + checkPrompts(1, "trying to read internet password without access"); + + changePasswordContents(item, CFSTR("new_password")); + checkPrompts(0, "after changing a internet password without access"); // NOTE: we expect this write to succeed, even though we're not on the ACL. Therefore, we should see 0 prompts for this step. + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + checkPrompts(1, "after changing a internet password without access"); + CFReleaseNull(item); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassGenericPassword, CFSTR("test_service"), CFSTR("test_service")); + item = checkN(testName, query, 1); + readPasswordContents(item, CFSTR("test_password")); checkPrompts(0, "after reading a generic password"); + changePasswordContents(item, CFSTR("new_password")); checkPrompts(0, "changing a generic password"); + readPasswordContents(item, CFSTR("new_password")); checkPrompts(0, "after changing a generic password"); + CFReleaseNull(item); + + query = makeQueryCustomItemDictionaryWithService(kc, kSecClassGenericPassword, CFSTR("test_service_restrictive_acl"), CFSTR("test_service_restrictive_acl")); + item = checkN(testName, query, 1); + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + checkPrompts(1, "trying to read generic password without access"); + + changePasswordContents(item, CFSTR("new_password")); + checkPrompts(0, "changing a generic password without access"); // NOTE: we expect this write to succeed, even though we're not on the ACL. Therefore, we should see 0 prompts for this step. + readPasswordContentsWithResult(item, errSecAuthFailed, NULL); // we don't expect to be able to read this + checkPrompts(1, "after changing a generic password without access"); + CFReleaseNull(item); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); +} +#define numTests (getPopulatedTestKeychainTests + \ +checkNTests + readPasswordContentsTests + checkPromptsTests + changePasswordContentsTests + checkPromptsTests + readPasswordContentsTests + checkPromptsTests + \ +checkNTests + readPasswordContentsTests + checkPromptsTests + changePasswordContentsTests + checkPromptsTests + readPasswordContentsTests + checkPromptsTests + \ +checkNTests + readPasswordContentsTests + checkPromptsTests + changePasswordContentsTests + checkPromptsTests + readPasswordContentsTests + checkPromptsTests + \ +checkNTests + readPasswordContentsTests + checkPromptsTests + changePasswordContentsTests + checkPromptsTests + readPasswordContentsTests + checkPromptsTests + \ ++ 1) + +int kc_16_item_update_password(int argc, char *const *argv) +{ + plan_tests(numTests); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-51-testSecItemFind.c b/OSX/libsecurity_keychain/regressions/kc-18-find-combined.c similarity index 59% rename from SecurityTests/regressions/kc/kc-51-testSecItemFind.c rename to OSX/libsecurity_keychain/regressions/kc-18-find-combined.c index 26e40ec3..c19ac9d2 100644 --- a/SecurityTests/regressions/kc/kc-51-testSecItemFind.c +++ b/OSX/libsecurity_keychain/regressions/kc-18-find-combined.c @@ -1,5 +1,26 @@ -// -// testSecItemFind.c +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + // // Tests the ability of SecItemCopyMatching to replace the following // deprecated keychain search functions: @@ -17,25 +38,11 @@ // - SecItemDelete // - SecKeyGenerateSymmetric // -// -// To build and run this tool (from Terminal): -// cc -framework Security -framework CoreFoundation -o testSecItemFind testSecItemFind.c -// ./testSecItemFind -// -// IMPORTANT: when building this code yourself, make sure that the AUTO_TEST -// symbol is undefined (or defined to 0) below. If the AUTO_TEST symbol is -// defined and non-zero, it is assumed that this tool is being built as part of -// an automated regression test suite by internal Security test harness code. -// -// -// Last modified: Tue Nov 16 2010 (kcm) - - -#define AUTO_TEST 1 #include #include #include +#include #include #include @@ -43,17 +50,11 @@ #include #include #include +#include "test/testenv.h" +#include "utilities/SecCFRelease.h" -#if AUTO_TEST -#import "testmore.h" -#import "testenv.h" -#import "testleaks.h" -#else -#define tests_begin(ARGC, ARGV) /* no-op */ -#define tests_end(RESULT) /* no-op */ -#define plan_tests(COUNT) /* no-op */ -#define ok(RESULT, REASON) /* no-op */ -#endif +#include "keychain_regressions.h" +#include "kc-helpers.h" /* Following is a 3-element certificate chain * (ROOT_CERT, INTERMEDIATE_CERT, LEAF_CERT) @@ -261,502 +262,410 @@ unsigned char LEAF_CERT[1037]={ /* Test certificate for Code Signing policy */ -unsigned char Test_codesign[1017]={ - 0x30,0x82,0x03,0xF5,0x30,0x82,0x02,0xDD,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x77, - 0xCE,0xF5,0x3D,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, - 0x30,0x81,0xA5,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x0C,0x19,0x54,0x65, - 0x73,0x74,0x2D,0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x49,0x4E,0x54,0x45,0x52, - 0x4D,0x45,0x44,0x49,0x41,0x54,0x45,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A, - 0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B, - 0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,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,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, - 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75, - 0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61, - 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x31,0x30,0x30,0x35, - 0x32,0x30,0x30,0x31,0x32,0x35,0x33,0x32,0x5A,0x17,0x0D,0x31,0x31,0x30,0x35,0x32, - 0x30,0x30,0x31,0x32,0x35,0x33,0x32,0x5A,0x30,0x81,0xA8,0x31,0x24,0x30,0x22,0x06, - 0x03,0x55,0x04,0x03,0x0C,0x1B,0x54,0x65,0x73,0x74,0x2D,0x37,0x38,0x37,0x35,0x38, - 0x30,0x31,0x20,0x28,0x43,0x6F,0x64,0x65,0x20,0x53,0x69,0x67,0x6E,0x69,0x6E,0x67, - 0x29,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, - 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x10,0x30,0x0E,0x06,0x03,0x55,0x04,0x0B,0x0C, - 0x07,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,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,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70, - 0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x2D, - 0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,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,0xC0,0x5E,0x52,0x53,0xB0,0x05,0x8D,0x9E,0xF2,0xBF,0x2E,0xA1, - 0x95,0xD5,0x10,0x97,0xFC,0x8E,0x77,0x6E,0x63,0x7A,0x7D,0xD2,0x56,0x05,0xE9,0xEE, - 0x3D,0xEE,0xCA,0xA4,0xBB,0x99,0x42,0xA2,0x55,0x67,0x97,0x15,0xFB,0x94,0x6D,0x22, - 0x39,0x7F,0xE9,0xC0,0x72,0x41,0x8F,0xF5,0x76,0x55,0x65,0x3B,0x39,0x5F,0x31,0x15, - 0x72,0x2A,0xB4,0x2F,0xED,0xB7,0x6A,0x3E,0xE9,0x3A,0x1C,0x50,0xD4,0x31,0x6D,0x7A, - 0x71,0x28,0x98,0x8D,0x8A,0xBF,0x90,0x01,0x8A,0xFF,0x42,0x62,0xEB,0xE5,0xC8,0x5A, - 0xB2,0x5A,0xB8,0x46,0x27,0xDA,0xD5,0x70,0xAF,0xD4,0xF6,0xF2,0xEC,0xD6,0x43,0x7E, - 0x25,0x31,0xED,0xA2,0x1E,0xFA,0x77,0xF4,0x59,0xBF,0x3F,0x11,0xAE,0xF1,0x0E,0xC9, - 0xFD,0x56,0xCA,0xA0,0x3E,0x8B,0xA5,0xE9,0xF6,0x91,0x82,0xE0,0xC6,0x5E,0x35,0x92, - 0x3F,0x0E,0x77,0x23,0x88,0x6F,0x33,0x91,0xAC,0x98,0xC5,0xF5,0x52,0x12,0xB2,0x3A, - 0x08,0x66,0xEB,0xC8,0x14,0x8E,0xED,0x0F,0xE5,0x76,0xCE,0x36,0xE8,0xED,0xB6,0x41, - 0xD6,0xF3,0x1C,0x24,0xBA,0xCC,0xEE,0x28,0xF8,0xC8,0xAE,0x87,0x15,0x1D,0x33,0x47, - 0xEA,0x5B,0x7D,0xE2,0x80,0xA9,0x6B,0xE3,0x8B,0x36,0xD0,0x25,0x2C,0x32,0xDA,0xFF, - 0x7C,0x85,0x28,0x48,0xDB,0x35,0x2A,0x1A,0xBE,0x7F,0xCD,0xE1,0xA6,0x79,0x35,0xB3, - 0x79,0xA3,0xB9,0x15,0xC6,0x31,0xA1,0xB4,0x63,0xD8,0x05,0x1D,0xDD,0x11,0x74,0xCD, - 0xCF,0xBD,0x27,0x02,0xB7,0xD8,0xA9,0xA1,0x1D,0xFB,0xA1,0xEC,0x44,0x8D,0x21,0x64, - 0x84,0x2E,0x6B,0x3B,0x02,0x03,0x01,0x00,0x01,0xA3,0x2A,0x30,0x28,0x30,0x0E,0x06, - 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x16,0x06, - 0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01, - 0x05,0x05,0x07,0x03,0x03,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, - 0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x80,0xC4,0xB6,0x9D,0xBE,0x72,0x30, - 0x72,0xFD,0x49,0x43,0x8F,0x3B,0xFE,0xC6,0xF1,0x4D,0xAA,0xB3,0xD1,0xD6,0x0C,0x54, - 0x9D,0x24,0xDF,0x86,0x9B,0x0A,0x68,0x55,0x4B,0x5A,0x20,0x53,0xC0,0xBF,0x82,0xAF, - 0xC7,0x19,0x19,0x43,0xA1,0xA4,0x53,0xF4,0xE5,0x33,0xE6,0xF7,0xAD,0x8E,0x6D,0xD8, - 0x94,0x23,0xEB,0x3E,0x6A,0xCF,0xDA,0x4B,0x09,0x6E,0x26,0x2B,0x62,0x70,0x98,0x0A, - 0xCE,0x58,0x70,0xA6,0xAD,0x08,0x45,0xAB,0x9E,0x89,0xBB,0xF8,0x84,0x6F,0x0D,0x9B, - 0x77,0xBA,0x60,0x9E,0xB8,0xA6,0xB6,0x7D,0x20,0xE9,0x83,0x72,0xE1,0xE9,0xB0,0x0E, - 0x0D,0x27,0xFB,0xD0,0x4C,0x81,0x88,0xAF,0x82,0x8F,0xB9,0x82,0xAD,0x1D,0x1B,0x54, - 0x11,0x84,0x16,0xFC,0x0B,0x53,0xB8,0xED,0x71,0xA2,0x6A,0xD9,0xC7,0x88,0xEE,0xD6, - 0x0C,0x5E,0xAD,0x2E,0x50,0xBA,0x56,0x12,0x95,0x5C,0x7F,0xF1,0x3B,0x48,0xB5,0x17, - 0x53,0xA9,0xC5,0x4C,0xD6,0x8C,0x39,0xCB,0x1A,0x5B,0xB6,0x4B,0x73,0x67,0x1E,0xB5, - 0x7D,0x13,0xAE,0x6B,0xD5,0xF4,0x59,0xE3,0xA1,0x4C,0x6A,0xEC,0xA5,0x27,0x07,0x9D, - 0x93,0x8F,0xF5,0xBB,0x50,0x28,0x00,0x05,0x25,0xCD,0xED,0xF7,0xA9,0x11,0x22,0x7E, - 0x92,0x4D,0xF5,0x7C,0x55,0xF4,0x1C,0x7A,0xA3,0xBC,0x24,0xC7,0xFB,0xED,0x6A,0x0A, - 0x1E,0xD5,0x9D,0x63,0xE0,0x2B,0x91,0x59,0x48,0xF2,0xF6,0xEB,0xF9,0xEB,0x9E,0x4D, - 0x3E,0xAE,0x44,0x9D,0xF9,0x93,0xB5,0x44,0xA1,0x36,0x3E,0x4E,0xC7,0xD9,0x47,0x83, - 0xCE,0xDD,0xA0,0x7C,0xA1,0xB4,0x75,0x1F,0xC8, +unsigned char Test_codesign[]={ + 0x30, 0x82, 0x03, 0xe3, 0x30, 0x82, 0x02, 0xcb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0xc8, 0x60, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x9d, 0x31, 0x24, 0x30, 0x22, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1b, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x37, 0x38, 0x37, 0x35, 0x38, 0x30, 0x31, 0x20, + 0x28, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x29, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x10, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 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, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, + 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, + 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, + 0x34, 0x30, 0x34, 0x32, 0x32, 0x35, 0x35, 0x33, 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x34, 0x30, 0x32, 0x32, 0x32, + 0x35, 0x35, 0x33, 0x32, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1b, 0x54, + 0x65, 0x73, 0x74, 0x2d, 0x37, 0x38, 0x37, 0x35, 0x38, 0x30, 0x31, 0x20, 0x28, 0x43, 0x6f, 0x64, 0x65, 0x20, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x29, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, + 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 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, 0xb0, 0x78, + 0x41, 0xd5, 0xc0, 0x71, 0x1d, 0x02, 0xc8, 0x57, 0x46, 0xf8, 0xc4, 0x3c, 0x7c, 0xa2, 0x13, 0x45, 0x8a, 0x1b, 0xef, 0x16, + 0xa6, 0x6f, 0xfe, 0x97, 0xe4, 0x8b, 0x6a, 0x7b, 0x89, 0xd2, 0x50, 0xcb, 0x6b, 0xcc, 0x47, 0x32, 0x9a, 0xd3, 0xf4, 0x19, + 0x62, 0x70, 0xe6, 0x27, 0xc4, 0x13, 0x5a, 0x60, 0x20, 0x8c, 0xb1, 0xc4, 0xf1, 0x76, 0xcd, 0x06, 0xb3, 0x60, 0x78, 0x4d, + 0xb2, 0x30, 0xb1, 0x1c, 0x53, 0x36, 0x98, 0x44, 0x84, 0x35, 0x57, 0xe9, 0xbc, 0xb7, 0x2d, 0x17, 0xd7, 0x0c, 0xbc, 0x52, + 0x9e, 0xfd, 0xe5, 0x32, 0x2a, 0xad, 0x28, 0x36, 0x24, 0x81, 0x87, 0x56, 0xd2, 0x39, 0x66, 0x13, 0x9e, 0x26, 0x44, 0x32, + 0xa3, 0xa7, 0x8b, 0xe7, 0x33, 0x25, 0xa3, 0x8e, 0x25, 0x14, 0x91, 0xf4, 0x32, 0x1a, 0x97, 0x82, 0xd3, 0x5a, 0xb5, 0x68, + 0x24, 0x0c, 0x46, 0x89, 0x00, 0x6f, 0xfa, 0x27, 0x03, 0xc6, 0x0b, 0xa2, 0xf0, 0xad, 0xd2, 0xec, 0x35, 0xca, 0x1a, 0xc5, + 0x76, 0xd4, 0xb2, 0x48, 0x72, 0xf0, 0x34, 0x48, 0xd6, 0x8e, 0xae, 0x37, 0x35, 0x87, 0x60, 0x25, 0x16, 0x71, 0xda, 0x0c, + 0x71, 0xaa, 0x95, 0xc2, 0xe4, 0x09, 0x91, 0xd9, 0x38, 0x62, 0xee, 0x0c, 0x26, 0x34, 0x7b, 0x6b, 0xbb, 0xf8, 0x33, 0xa1, + 0x08, 0x71, 0xc1, 0x4a, 0x5f, 0x7d, 0x17, 0x31, 0x25, 0xb7, 0xbe, 0x66, 0xab, 0x28, 0x6e, 0x58, 0x3c, 0xd1, 0x5f, 0xbf, + 0x8f, 0x48, 0x6e, 0x42, 0x8f, 0x85, 0x1a, 0x9e, 0x6b, 0x79, 0xbf, 0x43, 0xd9, 0xeb, 0x20, 0xa8, 0x1e, 0xf6, 0xe4, 0xaa, + 0xdb, 0x62, 0x87, 0x02, 0x43, 0xd0, 0x75, 0xa4, 0x14, 0x1d, 0x33, 0x3e, 0x81, 0x5d, 0x7a, 0x7c, 0x4a, 0xdf, 0x3e, 0x79, + 0x70, 0xca, 0xf5, 0xb6, 0xd8, 0x6d, 0x8e, 0xc7, 0x7f, 0xc7, 0xa0, 0x72, 0x6e, 0x95, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, + 0x2a, 0x30, 0x28, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x01, 0x00, 0x98, 0x03, 0xa7, 0x17, 0x66, 0x1a, 0xf3, 0x19, 0xd5, 0x7f, 0xac, 0x74, 0x8e, 0xa7, 0x43, 0x6a, 0x14, + 0xca, 0x5d, 0xa8, 0xf9, 0x8d, 0x22, 0x38, 0x48, 0x1c, 0x10, 0xd8, 0xe6, 0xfe, 0x0e, 0x8e, 0xd4, 0xb5, 0x8e, 0x89, 0xd9, + 0x95, 0x01, 0xba, 0x11, 0x4c, 0x7b, 0x7c, 0x64, 0x98, 0xd8, 0x4a, 0x11, 0x43, 0x0d, 0x71, 0xbd, 0x9f, 0xd9, 0x33, 0x84, + 0xa0, 0x3e, 0x9d, 0x6d, 0xa7, 0x72, 0xf0, 0x8d, 0x62, 0x9e, 0x45, 0xc2, 0x91, 0xfe, 0xbb, 0xbf, 0x08, 0x8b, 0x37, 0xd7, + 0x38, 0x71, 0x8f, 0x17, 0x2d, 0x98, 0x81, 0x16, 0x2d, 0xf6, 0x90, 0x6d, 0x57, 0x64, 0x6b, 0xa0, 0xbc, 0x02, 0xd8, 0xeb, + 0x63, 0x65, 0x1d, 0x1b, 0x20, 0xe7, 0x73, 0x8f, 0xe0, 0x82, 0x8d, 0x8f, 0xf6, 0x36, 0x08, 0x9d, 0xf3, 0xfd, 0x33, 0x4f, + 0xd2, 0xb0, 0x6d, 0xb8, 0x50, 0x02, 0x43, 0x2f, 0x90, 0x16, 0xe9, 0xb0, 0x1f, 0x9b, 0x2e, 0x70, 0x10, 0x89, 0xaa, 0xdc, + 0x18, 0xd7, 0xda, 0x3a, 0xce, 0xb8, 0x8f, 0xa4, 0x42, 0x4e, 0x50, 0x50, 0xa9, 0x19, 0x42, 0x0b, 0x07, 0x7c, 0x33, 0xe5, + 0x47, 0x40, 0x6a, 0x14, 0x02, 0x1f, 0x1e, 0xcf, 0x66, 0xb2, 0x76, 0x88, 0x0d, 0x49, 0x3a, 0xa5, 0xde, 0xfb, 0x99, 0xfa, + 0x70, 0xd4, 0x5e, 0xa1, 0x3e, 0x6d, 0x7f, 0x6b, 0x8c, 0x71, 0x79, 0x94, 0xb3, 0x1f, 0xcf, 0xdd, 0x9a, 0x31, 0xfd, 0x26, + 0x82, 0xa9, 0x94, 0x55, 0x87, 0x17, 0x33, 0xd0, 0x35, 0x3e, 0x80, 0x53, 0x8e, 0xb7, 0x18, 0x86, 0x5b, 0x8b, 0xee, 0x29, + 0xcf, 0xdf, 0x0e, 0x3f, 0x31, 0x9e, 0x29, 0x44, 0xa8, 0x99, 0xf7, 0xbe, 0x51, 0x3b, 0x53, 0xcd, 0x55, 0xfc, 0xb7, 0x6e, + 0x50, 0x21, 0xf2, 0xcc, 0x9c, 0x09, 0xe2, 0x6f, 0x4d, 0x15, 0x2f, 0x98, 0xa1, 0x04, 0xc0, 0xeb, 0x4c, 0x98, 0x93 }; +unsigned int Test_7875801__Code_Signing__cer_len = 999; -/* Test certificate for S/MIME policy (encrypt only, no sign) +/* Test certificate for S/MIME policy (encrypt only, no sign), expires April 2026 */ -unsigned char Test_smime_encryptonly[1060]={ - 0x30,0x82,0x04,0x20,0x30,0x82,0x03,0x08,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x77, - 0xCF,0x46,0x7D,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, - 0x30,0x81,0xA5,0x31,0x22,0x30,0x20,0x06,0x03,0x55,0x04,0x03,0x0C,0x19,0x54,0x65, - 0x73,0x74,0x2D,0x35,0x36,0x38,0x35,0x33,0x31,0x36,0x2D,0x49,0x4E,0x54,0x45,0x52, - 0x4D,0x45,0x44,0x49,0x41,0x54,0x45,0x31,0x0E,0x30,0x0C,0x06,0x03,0x55,0x04,0x0A, - 0x0C,0x05,0x41,0x70,0x70,0x6C,0x65,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B, - 0x0C,0x0B,0x43,0x6F,0x72,0x65,0x20,0x43,0x72,0x79,0x70,0x74,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,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, - 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29,0x06, - 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63,0x75, - 0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,0x2E,0x61, - 0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x30,0x1E,0x17,0x0D,0x31,0x30,0x30,0x37, - 0x32,0x37,0x32,0x30,0x35,0x39,0x35,0x38,0x5A,0x17,0x0D,0x31,0x32,0x30,0x37,0x32, - 0x37,0x32,0x30,0x35,0x39,0x35,0x38,0x5A,0x30,0x81,0xB2,0x31,0x21,0x30,0x1F,0x06, - 0x03,0x55,0x04,0x03,0x0C,0x18,0x54,0x65,0x73,0x74,0x2D,0x45,0x6E,0x63,0x72,0x79, - 0x70,0x74,0x69,0x6F,0x6E,0x20,0x28,0x53,0x2F,0x4D,0x49,0x4D,0x45,0x29,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, - 0x6E,0x63,0x2E,0x31,0x25,0x30,0x23,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1C,0x43,0x6F, - 0x72,0x65,0x20,0x4F,0x53,0x20,0x49,0x6E,0x66,0x6F,0x72,0x6D,0x61,0x74,0x69,0x6F, - 0x6E,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,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,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43, - 0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x23,0x30,0x21,0x06,0x09,0x2A,0x86, - 0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x14,0x73,0x6D,0x69,0x6D,0x65,0x2D,0x74, - 0x65,0x73,0x74,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,0xBB,0x8F, - 0xC3,0x01,0xD7,0x8A,0x62,0xE2,0xDD,0x26,0xE3,0x13,0x3E,0x61,0xC7,0x90,0xDE,0x98, - 0xCB,0x4A,0xC6,0x80,0xB3,0x36,0x99,0x8A,0xDE,0x6D,0xCF,0x60,0x7B,0x38,0x2E,0x86, - 0x0F,0x9E,0x9F,0xB0,0xCB,0x23,0xB1,0x52,0x0E,0x6E,0x70,0xD5,0x8D,0x56,0x32,0x36, - 0x35,0x7D,0x59,0x32,0xE6,0x3F,0x67,0x2F,0xC0,0x0F,0x2B,0x85,0x47,0x20,0x70,0x22, - 0xE5,0xB0,0x3C,0xF7,0xE3,0x4A,0x40,0xA5,0xB2,0x28,0xE5,0xB1,0x85,0x47,0x54,0x03, - 0xD1,0xB6,0x96,0x3E,0xDB,0x8D,0xD0,0x0E,0x5E,0x7A,0x65,0x2A,0x8A,0xBE,0xF7,0xB0, - 0x28,0x70,0x42,0x55,0x5A,0xAE,0xE6,0x58,0x91,0x20,0x5D,0x5B,0xFF,0x9B,0xF0,0x0C, - 0x49,0x94,0x55,0x68,0x46,0x34,0x2A,0xE4,0xA1,0x69,0x89,0xC8,0xB1,0xE7,0x07,0xB7, - 0xEC,0x2C,0x8A,0x65,0xF0,0xC6,0x51,0x3F,0x7C,0xC9,0x6F,0x42,0x71,0x15,0x30,0x9F, - 0xB5,0xA7,0xA5,0xD1,0xFE,0x2B,0x46,0x4F,0x3D,0xFD,0xCD,0xA8,0x1B,0x82,0x7B,0xA0, - 0x7B,0x9F,0x34,0x00,0xB7,0xC5,0x9F,0xCC,0x74,0xB4,0x35,0xC6,0x31,0x38,0x8D,0x91, - 0x79,0xE8,0xAF,0xCB,0xE4,0x17,0x78,0x11,0x7A,0x41,0xB1,0xF8,0x4D,0x2C,0xEE,0x7E, - 0x8D,0xEB,0x09,0x89,0xDC,0x74,0x2B,0xC1,0x25,0x57,0x3E,0x55,0x79,0x98,0x8B,0x5C, - 0xCF,0x05,0x38,0x69,0xF9,0x99,0x07,0x42,0x6D,0x99,0x1B,0x5E,0x89,0xBD,0xB6,0x4B, - 0x52,0x0F,0xDD,0xF9,0x67,0x53,0xDF,0xE2,0x25,0xBC,0x6C,0x72,0x19,0x6A,0x28,0xCE, - 0x6A,0xB4,0x22,0x93,0x20,0xDE,0xB6,0xF5,0x83,0x6A,0xC6,0x82,0x36,0x2B,0x02,0x03, - 0x01,0x00,0x01,0xA3,0x4B,0x30,0x49,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, - 0xFF,0x04,0x04,0x03,0x02,0x05,0x20,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01, - 0xFF,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x04,0x30, - 0x1F,0x06,0x03,0x55,0x1D,0x11,0x04,0x18,0x30,0x16,0x81,0x14,0x73,0x6D,0x69,0x6D, - 0x65,0x2D,0x74,0x65,0x73,0x74,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,0x7D,0xB4,0x4B,0x4B,0xE1,0xB3,0x29,0x22,0x72,0x7E,0x66,0xEA, - 0x78,0x51,0xBB,0x38,0xA0,0x44,0x6E,0xAE,0xB7,0xFE,0x43,0x24,0x78,0xAE,0x93,0x3B, - 0xF0,0x2B,0xAB,0x31,0x61,0x9F,0x6E,0x1F,0x89,0x0F,0x2C,0xD0,0xC4,0x29,0xE0,0x1C, - 0x4C,0x7B,0x96,0x82,0x0D,0x29,0x08,0x1F,0xDE,0x35,0xA2,0x12,0x0D,0xB4,0xA0,0x5D, - 0xE4,0xE8,0x38,0xC3,0x5C,0x99,0xFD,0x2E,0xE9,0x3B,0xC7,0xFC,0x67,0x3D,0xBD,0x1E, - 0x46,0x3A,0xDD,0xFB,0x24,0xF0,0x83,0x77,0x4F,0xA0,0x63,0x40,0x58,0x28,0x3C,0x32, - 0x3B,0xEB,0x8B,0x20,0x29,0xFD,0x22,0x4A,0xEC,0x3C,0x78,0xE2,0xD5,0xD3,0x54,0x35, - 0x8F,0x4D,0x48,0x61,0x2E,0xB6,0xC1,0xE5,0x3A,0x95,0xCD,0xBF,0x73,0xA2,0x1A,0x15, - 0xC3,0x24,0x0F,0xDB,0x86,0x08,0x55,0x01,0xBC,0x8C,0x4F,0x83,0x4E,0x90,0x55,0x84, - 0xF8,0x82,0xB1,0x1E,0x9F,0x70,0xD3,0xE8,0xE8,0xD3,0xDB,0x97,0xE0,0x66,0xAA,0x54, - 0x58,0x32,0x16,0x56,0xA3,0xF3,0x9B,0xCE,0xC4,0xA3,0x65,0x66,0x71,0xFD,0x20,0x87, - 0x3A,0x34,0x74,0xAB,0x6B,0x26,0xB8,0x18,0x8A,0x77,0xFF,0x77,0x21,0x6A,0xF0,0x38, - 0x12,0x74,0x45,0x1F,0x67,0x3D,0xBD,0xDF,0xBF,0x32,0x82,0x8E,0x4D,0xC5,0x3D,0x59, - 0x07,0xCD,0x1A,0x05,0xB6,0x96,0xD7,0x95,0xDB,0x44,0x81,0x59,0xD7,0x2A,0x88,0x0D, - 0x3C,0xD8,0xD5,0x2B,0x92,0xA8,0xC1,0x8D,0xDE,0x60,0x6F,0x98,0xE4,0x3C,0xB8,0xEC, - 0x52,0x2A,0x56,0x6E,0xF1,0x76,0x56,0x64,0x3D,0xD9,0x09,0xB9,0x4B,0x73,0xEF,0x11, - 0x78,0xFB,0xA6,0x9A, +unsigned char Test_smime_encryptonly[]={ + 0x30, 0x82, 0x04, 0x07, 0x30, 0x82, 0x02, 0xef, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x02, 0xb8, 0x95, 0x23, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x9e, 0x31, 0x21, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x53, 0x2f, 0x4d, 0x49, 0x4d, 0x45, 0x29, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x20, 0x4f, 0x53, 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, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x23, + 0x30, 0x21, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x14, 0x73, 0x6d, 0x69, 0x6d, 0x65, + 0x2d, 0x74, 0x65, 0x73, 0x74, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x36, 0x30, 0x34, 0x30, 0x34, 0x32, 0x32, 0x32, 0x32, 0x33, 0x36, 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x34, 0x30, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x33, 0x36, 0x5a, 0x30, 0x81, 0x9e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x18, 0x54, 0x65, 0x73, 0x74, 0x2d, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x53, 0x2f, + 0x4d, 0x49, 0x4d, 0x45, 0x29, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x07, 0x43, 0x6f, + 0x72, 0x65, 0x20, 0x4f, 0x53, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x23, 0x30, 0x21, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x14, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x2d, 0x74, 0x65, 0x73, 0x74, 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, 0xc6, 0x5a, 0xe9, 0x94, 0x4a, 0x9e, 0x4d, 0x47, 0xa3, 0x9d, 0x06, 0xb3, 0xd5, 0x05, 0xad, 0x05, 0x71, 0xaf, 0x93, + 0x42, 0x9d, 0x02, 0x58, 0x33, 0x30, 0xee, 0xcb, 0xe4, 0x96, 0x24, 0x4b, 0x35, 0x0b, 0x6a, 0x58, 0xd0, 0xe7, 0x13, 0x5b, + 0xd5, 0xd3, 0xa1, 0x99, 0x55, 0xff, 0xe9, 0x3b, 0xe7, 0x20, 0x4e, 0x9e, 0x6b, 0xcd, 0x86, 0x47, 0xd7, 0xf6, 0x67, 0xc2, + 0xde, 0x51, 0xbc, 0x58, 0xd8, 0xc8, 0xe1, 0xb6, 0x42, 0xc5, 0xe9, 0x9e, 0x65, 0x3a, 0x04, 0xab, 0x47, 0x1b, 0xc8, 0xfe, + 0xb6, 0xb2, 0x47, 0x03, 0xc4, 0xa4, 0xb8, 0xaf, 0x31, 0xe7, 0x10, 0x7b, 0x4a, 0x4b, 0x29, 0x09, 0x91, 0xc2, 0xd2, 0x1f, + 0x42, 0x9a, 0x77, 0xc2, 0x08, 0x98, 0x53, 0x32, 0x8f, 0x8c, 0xa7, 0x06, 0xa5, 0x05, 0x9e, 0xeb, 0xc9, 0x5b, 0x7a, 0x5c, + 0xb3, 0xd7, 0x91, 0x6f, 0xea, 0xa1, 0x4f, 0x93, 0x9b, 0xa6, 0xf5, 0xdb, 0x32, 0x3b, 0x71, 0xfd, 0x07, 0xa4, 0x30, 0x30, + 0x35, 0xfa, 0x6c, 0x77, 0x76, 0x98, 0x99, 0x3a, 0x19, 0xcd, 0x7c, 0x5d, 0xc5, 0x70, 0x86, 0xaf, 0xf9, 0x9e, 0xa1, 0x45, + 0x5e, 0x6d, 0x03, 0x63, 0x3b, 0x4a, 0xcc, 0x14, 0xda, 0x75, 0xc2, 0xf1, 0x8f, 0x51, 0xd3, 0x80, 0x5f, 0xf7, 0x52, 0xd0, + 0x04, 0x1b, 0x37, 0x6e, 0x3a, 0xfe, 0xcc, 0x5d, 0xba, 0xbe, 0x0f, 0x1a, 0xd8, 0x31, 0xd4, 0x7b, 0xf2, 0x20, 0x22, 0x56, + 0xd1, 0x84, 0x8f, 0x12, 0x4a, 0x81, 0xa5, 0xeb, 0x7f, 0x8b, 0x4b, 0x21, 0x02, 0xeb, 0xb4, 0x6e, 0xb6, 0x3c, 0x3c, 0x15, + 0x09, 0xa4, 0x79, 0x7c, 0x3e, 0x45, 0xf3, 0xe7, 0x84, 0x10, 0xc9, 0x45, 0x86, 0xd5, 0xda, 0x9e, 0xdf, 0x7d, 0x05, 0xcc, + 0xdf, 0x1a, 0x30, 0x8f, 0xea, 0x57, 0x9a, 0x72, 0xb0, 0x58, 0x95, 0x6b, 0x9e, 0xe8, 0x94, 0xf2, 0x8d, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x4b, 0x30, 0x49, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, + 0x07, 0x80, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x04, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x18, 0x30, 0x16, 0x81, 0x14, 0x73, + 0x6d, 0x69, 0x6d, 0x65, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x40, 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, 0x79, + 0xc0, 0x92, 0xf8, 0xfd, 0xac, 0x3f, 0x21, 0x3a, 0x1b, 0x7c, 0x2b, 0xc9, 0x0a, 0x62, 0xb6, 0xe2, 0x1d, 0x3b, 0x67, 0x4b, + 0x4b, 0xf8, 0xe8, 0xbe, 0xd8, 0x8e, 0x71, 0x07, 0x4a, 0x6e, 0xbd, 0x07, 0xc8, 0xd0, 0x86, 0x9c, 0xdb, 0xd5, 0x43, 0x23, + 0xc3, 0x56, 0x03, 0x45, 0xa6, 0xab, 0xf8, 0xba, 0xc2, 0xba, 0xd8, 0x78, 0x33, 0x49, 0xaa, 0x82, 0xb4, 0x0c, 0x6c, 0x9b, + 0x4c, 0x5b, 0x9d, 0x4f, 0xb5, 0xd8, 0xd9, 0x0f, 0x33, 0x21, 0x27, 0x8c, 0x99, 0xa0, 0xb6, 0xe0, 0xfb, 0x40, 0x4e, 0x88, + 0x36, 0x91, 0x42, 0x3f, 0xcc, 0x52, 0x3f, 0x39, 0x82, 0x3d, 0xbd, 0x43, 0x45, 0xf4, 0x1c, 0x17, 0x4c, 0x29, 0x63, 0x5d, + 0x12, 0xdd, 0x16, 0x8a, 0xa3, 0x6a, 0x81, 0x21, 0xbc, 0x55, 0x10, 0xfa, 0x88, 0x95, 0x80, 0x5d, 0x6a, 0xeb, 0x96, 0x54, + 0x37, 0x94, 0x07, 0x28, 0x06, 0x0f, 0x62, 0x7e, 0x6f, 0x3d, 0x9e, 0xe7, 0x1d, 0x0e, 0x35, 0xb5, 0x89, 0x07, 0x04, 0xd6, + 0x70, 0x69, 0x43, 0x8b, 0x44, 0xdb, 0xb5, 0x0b, 0xc8, 0x80, 0xc5, 0xe9, 0x8f, 0xe4, 0xa7, 0x75, 0x32, 0xa6, 0x47, 0xdc, + 0xc9, 0x68, 0x26, 0x85, 0x96, 0x8c, 0x15, 0x47, 0xe0, 0x4f, 0x13, 0x81, 0x97, 0xae, 0x7c, 0xc5, 0x1c, 0xda, 0x22, 0xef, + 0x39, 0xef, 0xe8, 0x8f, 0xbb, 0x33, 0xd3, 0x40, 0x12, 0x45, 0xcd, 0x05, 0x81, 0x39, 0xdc, 0x88, 0x9f, 0xd2, 0x3e, 0x20, + 0xe5, 0xec, 0xf9, 0x39, 0xc5, 0x55, 0xeb, 0x97, 0x7f, 0x67, 0x36, 0x80, 0xfa, 0x2a, 0xe1, 0xf4, 0x36, 0x03, 0xe5, 0xe2, + 0xa8, 0x75, 0x0e, 0x58, 0x21, 0xdf, 0x86, 0x38, 0x49, 0x19, 0x6f, 0x00, 0x3b, 0x8c, 0x57, 0x8c, 0xa7, 0x60, 0xf8, 0xda, + 0x01, 0xbc, 0xbc, 0xe5, 0x77, 0x81, 0xeb, 0xda, 0xd6, 0xd6, 0x6e, 0xa4, 0x1a, 0x09, 0x3c }; +unsigned int Test_Encryption__S_MIME__cer_len = 1035; /* Test identity for S/MIME policy (sign only, no encrypt) */ -unsigned char Test_smime_signonly_p12[2761] = { - 0x30,0x82,0x0a,0xc5,0x02,0x01,0x03,0x30,0x82,0x0a,0x8c,0x06,0x09,0x2a,0x86,0x48, - 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0x7d,0x04,0x82,0x0a,0x79,0x30,0x82, - 0x0a,0x75,0x30,0x82,0x04,0xef,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, - 0x06,0xa0,0x82,0x04,0xe0,0x30,0x82,0x04,0xdc,0x02,0x01,0x00,0x30,0x82,0x04,0xd5, - 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x30,0x1c,0x06,0x0a,0x2a, - 0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x06,0x30,0x0e,0x04,0x08,0x03,0x00,0x56, - 0xda,0x33,0x28,0xb6,0xbc,0x02,0x02,0x08,0x00,0x80,0x82,0x04,0xa8,0x36,0xa9,0x2d, - 0xab,0xcc,0x17,0x76,0x6e,0x1c,0xf2,0x82,0xb1,0xc1,0xac,0x19,0xbe,0xb3,0x71,0x4f, - 0x1a,0xe6,0x0f,0x2d,0x7e,0xd4,0x66,0x0a,0x70,0x85,0x41,0xa5,0x92,0x06,0x02,0x71, - 0x0f,0x7a,0xed,0xef,0x52,0x96,0xd2,0x67,0xf4,0xa8,0x5b,0xde,0x6e,0xc6,0xdc,0xc6, - 0xe8,0x6e,0x86,0x11,0x94,0x60,0x0d,0xa1,0x24,0x57,0x1f,0x51,0xd8,0x7d,0x28,0xf9, - 0x10,0xcb,0x68,0x1b,0x32,0xe4,0xa3,0x60,0x7c,0xb2,0x2b,0x33,0x4e,0x23,0xec,0x60, - 0x4c,0xe0,0x1a,0x39,0x03,0x60,0xb7,0x09,0x4d,0xb7,0x8c,0x94,0x91,0x44,0xa7,0xc7, - 0x3b,0xd7,0xc5,0xc5,0x0f,0x4a,0x54,0xe5,0xee,0x41,0xd5,0x32,0xf2,0xfc,0x7a,0x4d, - 0x68,0x5d,0xfc,0xe9,0xab,0xa0,0x74,0xb9,0x6f,0x68,0xc4,0x68,0xa1,0x91,0x5d,0x74, - 0x2b,0x06,0xfc,0xa7,0x93,0x2c,0xc3,0x8e,0xaf,0x12,0x84,0x09,0x1f,0xa8,0xd7,0xb3, - 0xf2,0x13,0x33,0xdf,0xd2,0xa5,0x34,0xa5,0x08,0x73,0xea,0x8f,0xc3,0x88,0xd4,0xa1, - 0xce,0xa9,0x56,0xc4,0x4f,0xc9,0x48,0xfb,0x84,0x26,0x16,0xc8,0x1a,0x15,0x6d,0x10, - 0x8e,0x4e,0x85,0xfc,0x8b,0xb7,0xfc,0x69,0x6a,0x79,0xc0,0xff,0xed,0xfd,0x7b,0x0b, - 0x7f,0x5b,0x8d,0x89,0x4e,0xb6,0x25,0x0e,0x04,0x42,0xdb,0x15,0x7b,0xbc,0x7b,0x75, - 0x91,0x12,0x7c,0x0f,0x22,0xfd,0xd4,0x4d,0x3c,0x9c,0x6c,0x10,0x40,0x9e,0x3e,0x0b, - 0xfd,0x2e,0x2d,0x23,0x27,0x96,0x86,0x85,0x44,0xdd,0xc4,0x44,0xbf,0x74,0x09,0x2f, - 0x90,0x48,0x3d,0x8a,0x05,0xbe,0x44,0xe5,0x75,0x1f,0x4e,0xbc,0x91,0xfd,0xf5,0x1a, - 0xde,0xd4,0x99,0xf4,0xbe,0x2f,0x28,0xbf,0x47,0x49,0x90,0xb5,0xea,0xd6,0x48,0xcb, - 0x7b,0xde,0xea,0x3d,0x07,0x8d,0xf4,0x7c,0xd7,0x4d,0xcb,0xc1,0xcb,0xa3,0x30,0x2f, - 0x7c,0x59,0x09,0xad,0xb3,0x27,0x66,0x2a,0x87,0x51,0xd7,0x7b,0xbb,0xb1,0x6d,0x4e, - 0x0e,0x1a,0x6a,0x7a,0xf8,0x31,0x99,0xa8,0x1c,0x06,0x1a,0x4e,0x83,0xa8,0xac,0xaf, - 0x72,0xdb,0x89,0x1b,0xe1,0x9d,0x52,0x22,0x94,0xaf,0x6a,0xe0,0x5c,0x60,0xd5,0xf2, - 0x6a,0xde,0x1f,0x51,0xb0,0x19,0x13,0xff,0xb9,0xfe,0x15,0xeb,0x4a,0x5c,0x44,0xe6, - 0xbd,0x3d,0xbd,0xdc,0xb2,0xa8,0x96,0xa2,0x05,0x7e,0xdc,0x39,0x15,0x7a,0xc9,0xdc, - 0xb3,0x2b,0xa2,0x1c,0xe1,0x78,0xfb,0x5b,0x12,0x35,0xc2,0x05,0xed,0x59,0xa2,0xf1, - 0x8d,0x5b,0xe2,0xf8,0x95,0xc7,0xdd,0x20,0xf9,0xcc,0xfd,0x43,0xbe,0x03,0x0f,0xdb, - 0xa1,0x21,0x7b,0x86,0x0e,0x0b,0x26,0xbd,0x38,0x10,0x62,0xbc,0x5c,0x43,0x48,0x6f, - 0xbc,0x6c,0x68,0x83,0xd4,0x54,0x5b,0x80,0x25,0x13,0x69,0x18,0xce,0x8e,0xe9,0x3f, - 0xfb,0x81,0x51,0x92,0x19,0x3f,0x4b,0x41,0x53,0x39,0x3e,0xa2,0xef,0x90,0x59,0x5c, - 0x30,0x22,0x36,0xed,0x78,0x78,0xc5,0x70,0x9c,0x8b,0x96,0x8d,0xe8,0x7a,0x9b,0x27, - 0xdc,0x9b,0x4f,0x2b,0x30,0x86,0x27,0x95,0x70,0x8f,0xc0,0xd5,0xd4,0x79,0x9f,0x0f, - 0x38,0x49,0x1d,0xe9,0x76,0xcf,0x6c,0x34,0x06,0xc0,0xfa,0xa0,0xab,0x41,0x1c,0x26, - 0x04,0x18,0x0f,0xa8,0x45,0xf5,0xdc,0x82,0x5d,0x8a,0xe6,0x2b,0x84,0xe9,0xaa,0xa2, - 0xbd,0xf4,0xc6,0x94,0xa6,0xbb,0x6f,0x35,0x3c,0x5f,0x9a,0x45,0xd3,0x3e,0x6b,0x75, - 0x54,0x10,0x5a,0x6f,0x0c,0x26,0xe7,0xb1,0x92,0x6c,0x93,0xf1,0xce,0x02,0x97,0xbe, - 0xf8,0x76,0xbc,0x9b,0xff,0x09,0xe2,0x8a,0x62,0xdc,0x19,0xfa,0x33,0x94,0x07,0x4b, - 0x7d,0x62,0xe3,0xca,0xc6,0x1e,0xc4,0x18,0xd7,0xa8,0xbb,0x79,0xd1,0x4e,0x2e,0x37, - 0xa4,0x02,0x06,0x80,0xa4,0xed,0xbf,0x3e,0x8b,0xc7,0xcd,0xf2,0xa5,0x8f,0x68,0x1e, - 0xb2,0x72,0xc2,0xa2,0xa7,0x8d,0x03,0x51,0x0f,0xe2,0x7a,0x04,0x03,0x83,0x2f,0x71, - 0x16,0x85,0x7e,0xf3,0x29,0xc7,0x31,0x27,0x24,0xae,0x8b,0x08,0xe7,0x6b,0x7d,0x5f, - 0x27,0xdd,0xdb,0x28,0x63,0x65,0xbb,0x2a,0x6e,0x63,0xc4,0xa4,0x90,0x36,0x8e,0xc4, - 0x8b,0x55,0x6f,0x99,0x4f,0xf3,0x63,0xef,0xc7,0x3a,0xd5,0x55,0xf3,0x98,0xaa,0x9c, - 0x20,0x9d,0x9b,0x07,0x44,0x92,0x27,0x2c,0xc5,0x22,0x78,0x85,0x66,0x71,0xd5,0x0f, - 0xea,0xa7,0xdc,0x0c,0xad,0x07,0x2a,0xa5,0x34,0xca,0xbc,0x8e,0xff,0xfd,0x0b,0xb0, - 0x9d,0x21,0x16,0x9d,0xfa,0x21,0xaf,0xec,0x25,0x6a,0xd7,0x7d,0xff,0xe6,0x73,0xe3, - 0x6c,0x4e,0x9c,0xe0,0xeb,0x0c,0x56,0x32,0xa9,0xbb,0x48,0xe5,0xa7,0x4b,0x59,0x1d, - 0x70,0x31,0xf2,0x79,0x88,0x50,0xc4,0x59,0x01,0x3c,0xc2,0x61,0xbe,0xe7,0xbc,0xc0, - 0x6f,0xb4,0x27,0x90,0xcd,0x4f,0x44,0x60,0x9f,0x02,0x5a,0x68,0x81,0xb6,0x6f,0x78, - 0x10,0xd3,0x3e,0xb3,0xb4,0xc5,0x6f,0xa6,0x3e,0x77,0x30,0x29,0xd7,0xa7,0xda,0x5f, - 0xb4,0x3e,0x3f,0xf9,0xb3,0x04,0xd8,0xe5,0x75,0xc5,0x1e,0xcf,0xa6,0x85,0x4c,0x57, - 0xf6,0xbb,0x8f,0xda,0x80,0x02,0x4b,0x79,0x0f,0x94,0xed,0x98,0xdb,0x64,0x8d,0x8f, - 0x8e,0x90,0x5b,0x31,0x80,0x1b,0x50,0x8b,0x99,0x7b,0x23,0x94,0xf2,0x1e,0x8e,0xe6, - 0xce,0x7f,0x2f,0x16,0x64,0x7f,0xdb,0x16,0x08,0x97,0x78,0x5c,0x4d,0xef,0x9c,0x63, - 0x0f,0x37,0x14,0x58,0x68,0x57,0x29,0x42,0xd3,0x4d,0x97,0x62,0xe8,0x08,0xe4,0x60, - 0x87,0x07,0x73,0x11,0x21,0x5e,0x8c,0x97,0x78,0xdb,0x2f,0x81,0xb3,0xa0,0xfd,0x17, - 0x0b,0xf0,0x29,0x88,0x1a,0x39,0xec,0x0c,0xfb,0x30,0x0d,0x0a,0x9a,0x60,0xe2,0xaf, - 0xf9,0xb3,0x9c,0xdd,0xa6,0x2e,0x7c,0x90,0xf7,0x31,0x3c,0x35,0xe8,0x2f,0xdd,0x54, - 0xdf,0x45,0x54,0xcf,0xdd,0xfc,0xf6,0x36,0x3f,0x36,0x8a,0x23,0x60,0xd0,0x4b,0xe2, - 0x0b,0xb5,0x90,0xc4,0xbe,0xaf,0xa1,0xd6,0xc2,0x69,0x0a,0x5b,0x74,0xae,0xa5,0xb3, - 0x12,0xaf,0x06,0x98,0xfe,0xc3,0x52,0xbb,0xf0,0xde,0x67,0xd4,0x8d,0x2a,0xf4,0x35, - 0x71,0xaf,0x5e,0x24,0xc4,0x2a,0x48,0xa6,0x42,0x32,0x10,0xb0,0x09,0x74,0x83,0x9e, - 0x3c,0x50,0x15,0x74,0xeb,0x2e,0x29,0x64,0x3e,0xe5,0x6e,0x13,0xc0,0x5b,0x9b,0x5b, - 0x1f,0x8f,0xe5,0x49,0x25,0x36,0x57,0x90,0x81,0xce,0x27,0xf4,0x8d,0x42,0x5d,0x04, - 0x2c,0x44,0x7a,0xeb,0xe0,0x10,0x4e,0xba,0x21,0xf3,0x1d,0xdf,0xb0,0xe4,0x56,0xf9, - 0x5a,0xbe,0xfe,0x1a,0x6d,0xeb,0x2d,0xe2,0x93,0x5f,0xa1,0x74,0x86,0x0c,0x64,0x68, - 0xf4,0x67,0xf3,0xe0,0xfa,0xe6,0x9d,0x6a,0xfe,0xb6,0x5f,0x58,0x2d,0xa7,0x77,0x07, - 0x58,0xc8,0x79,0x51,0xa5,0x8e,0xbd,0x4c,0x61,0x80,0x9d,0x91,0xda,0x32,0xee,0x09, - 0x02,0xca,0x14,0xf8,0xfa,0x08,0xf3,0x4a,0xf5,0x6a,0x50,0xcd,0x98,0x21,0xbd,0xb4, - 0x5e,0x4c,0x20,0x8f,0x0a,0x94,0xd0,0x6c,0x96,0xf1,0xa2,0xff,0xf6,0x1f,0x15,0xd5, - 0x1d,0x64,0x92,0x82,0xaf,0x01,0xca,0xa0,0x38,0xe9,0x80,0xea,0xe9,0xb3,0xdf,0xed, - 0xa8,0x03,0x31,0x5e,0x05,0x12,0xcd,0x29,0x33,0x59,0xf9,0xf2,0xbc,0x7f,0x05,0x86, - 0x9e,0x96,0xc4,0x52,0x2d,0x1f,0x1e,0x29,0x05,0x68,0xde,0xf1,0x3c,0x2d,0x65,0x97, - 0x7c,0xde,0x28,0x88,0xab,0xd3,0x12,0x5e,0x3d,0x15,0x45,0xc3,0x05,0x47,0x13,0x03, - 0x65,0xad,0x49,0x5f,0x8a,0x15,0xf5,0x27,0xc1,0x13,0xa5,0x16,0x85,0x13,0x11,0xf6, - 0x71,0x03,0x2c,0xaf,0xce,0xc4,0x36,0x17,0x0b,0xfd,0x4a,0x4c,0xce,0x9e,0x0d,0xcc, - 0xa5,0xa3,0x30,0xce,0x61,0x30,0x82,0x05,0x7e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, - 0x0d,0x01,0x07,0x01,0xa0,0x82,0x05,0x6f,0x04,0x82,0x05,0x6b,0x30,0x82,0x05,0x67, - 0x30,0x82,0x05,0x63,0x06,0x0b,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x0a,0x01, - 0x02,0xa0,0x82,0x04,0xee,0x30,0x82,0x04,0xea,0x30,0x1c,0x06,0x0a,0x2a,0x86,0x48, - 0x86,0xf7,0x0d,0x01,0x0c,0x01,0x03,0x30,0x0e,0x04,0x08,0xb1,0xca,0xab,0x81,0x75, - 0x32,0xf4,0x2c,0x02,0x02,0x08,0x00,0x04,0x82,0x04,0xc8,0xc8,0xe4,0x07,0x32,0x15, - 0x32,0xb1,0xce,0xca,0xa4,0x03,0x84,0x91,0xbc,0x74,0x45,0x63,0x46,0xa8,0x20,0xcf, - 0xa2,0x2d,0x0e,0xfb,0xf7,0xfa,0x3d,0xad,0x72,0xa4,0x97,0xc9,0x14,0xb9,0x55,0x00, - 0x5e,0xb6,0x17,0xf9,0xba,0xe4,0xf4,0x4b,0x36,0x31,0xbb,0xfc,0x4a,0xb3,0xfe,0xd7, - 0xf5,0xd0,0xe8,0x63,0x43,0x6b,0x7e,0xfe,0xcc,0xa8,0x2f,0x8a,0x8a,0xf3,0xfb,0x23, - 0x0c,0xed,0x03,0x20,0x66,0xe2,0x90,0x9b,0x68,0x71,0xfb,0x44,0x68,0xe5,0x87,0x97, - 0x0a,0x97,0x63,0x53,0x3c,0x07,0x86,0x63,0xb2,0x0f,0x8e,0xe8,0xb5,0x0a,0x0c,0xe2, - 0x12,0x6d,0x33,0xa1,0xa5,0xc5,0xc4,0xab,0xf7,0x23,0x35,0x53,0x69,0xc1,0x37,0x28, - 0x86,0x42,0xa1,0x9c,0xe4,0xf5,0x2e,0x8c,0x92,0x1a,0xeb,0x67,0x10,0xcb,0x24,0xb5, - 0xd6,0x75,0x33,0x7a,0x5f,0x20,0x8f,0x1e,0x13,0x4c,0x4c,0xa1,0x53,0x87,0x8c,0xad, - 0x04,0x28,0xe0,0x21,0x65,0xf0,0x1b,0x62,0x15,0x95,0x36,0xd1,0x21,0xe1,0x50,0x0d, - 0xe4,0xed,0x07,0x8d,0x37,0xd3,0x06,0x2d,0x88,0x46,0x0f,0x54,0x16,0x19,0xac,0xc7, - 0x0b,0xcf,0x83,0xe9,0x49,0xbc,0x9e,0x7f,0x38,0xed,0xe4,0xf1,0x84,0x6a,0x0e,0xd1, - 0x92,0x39,0x61,0x36,0xa3,0x12,0xfc,0x31,0x4c,0xde,0x9d,0xcf,0xa0,0x90,0xd0,0x17, - 0x29,0x51,0x93,0x04,0xb1,0xe9,0xab,0x5e,0x5d,0x9e,0x2f,0x99,0xe9,0x53,0x95,0x27, - 0x39,0x5a,0x48,0x64,0x56,0x7b,0x97,0x9e,0x5d,0xf0,0xc9,0xd5,0x6b,0x57,0x0e,0xdc, - 0x69,0x7f,0x2d,0x6e,0xd7,0x3a,0xd8,0x31,0xcb,0x14,0xf4,0x3b,0x33,0xaf,0x62,0x95, - 0xbe,0x6b,0xe9,0xd7,0x2a,0x17,0x6c,0x9d,0x65,0x6c,0x2a,0xf5,0x38,0x39,0x95,0x8c, - 0xc6,0x97,0xc9,0xa1,0xe8,0x07,0x09,0x62,0x71,0x92,0xc2,0x4f,0xb1,0x25,0x83,0x90, - 0x44,0x54,0xcd,0x5c,0x3d,0x7b,0x0f,0xf1,0xdf,0x00,0xe2,0x4a,0x0e,0xd4,0xfe,0xa8, - 0x3e,0x81,0x4e,0x6c,0x92,0x49,0xa0,0x49,0xc4,0x3a,0x80,0x78,0x1d,0xb2,0x43,0xbd, - 0x21,0x5a,0xe0,0xbd,0x99,0xe0,0x77,0xd1,0xe6,0x2d,0x73,0xd4,0x4b,0xa9,0x07,0xcc, - 0xbd,0x12,0xa2,0x06,0x08,0x60,0xbd,0x99,0xfd,0x9f,0xcc,0x23,0x6f,0xd2,0xd0,0xdf, - 0xbe,0x63,0xef,0xe9,0x15,0x24,0x54,0x55,0x73,0x85,0x9e,0x26,0x62,0xd8,0xc1,0x14, - 0xce,0xcc,0x3b,0xf6,0x87,0x68,0xfa,0x3d,0x6e,0xb1,0x1c,0x5e,0x4e,0x05,0xe4,0xbc, - 0x95,0x1b,0xb4,0xd5,0xa1,0xfb,0xe2,0x25,0x48,0xe9,0x63,0x36,0xdf,0x33,0x8e,0xed, - 0x1d,0xdf,0x63,0x1a,0xfd,0xb6,0xc9,0x09,0x3a,0xc2,0x9f,0x1d,0xd4,0x45,0x00,0x2a, - 0x86,0x09,0x9c,0x30,0x4e,0xc0,0x81,0x9c,0x30,0x14,0x6b,0x4c,0x52,0xfd,0xca,0x36, - 0xef,0x99,0x2e,0xd1,0x86,0xc0,0xdf,0x9d,0x6a,0xb5,0xfa,0xa3,0x12,0xe0,0x5f,0x73, - 0xb4,0xfd,0xd7,0x59,0x23,0x6d,0xa8,0x77,0x8f,0x65,0x4a,0x65,0x46,0x5e,0x56,0xe0, - 0x23,0xbb,0xc5,0x38,0xff,0xf0,0x4a,0x2e,0xab,0x20,0x75,0x02,0xc5,0x85,0x7e,0x6b, - 0x3f,0xa4,0x00,0xf5,0x39,0x88,0xd1,0x9c,0xc9,0xe9,0x77,0xeb,0x8d,0xce,0x2e,0x74, - 0x5c,0xb9,0x6c,0xb0,0x6d,0x9e,0x5f,0x7b,0x93,0x7b,0x22,0x0e,0xb3,0x55,0x65,0xca, - 0x64,0xec,0xc0,0xa5,0xff,0x19,0x0a,0x2d,0x1c,0xc9,0xd3,0xe3,0xb6,0x18,0xe3,0x8c, - 0x83,0xd8,0x43,0x01,0xf8,0x6e,0x64,0x07,0xb9,0xac,0x20,0x29,0xeb,0x36,0xf5,0x04, - 0xd8,0x41,0xeb,0x8d,0x23,0x39,0x21,0x83,0xb6,0x82,0xbd,0x18,0xac,0xc6,0xb7,0x5b, - 0xf7,0x4d,0x80,0x7a,0xf6,0xdc,0x40,0x04,0x9c,0xec,0xb2,0xea,0xd6,0xf1,0x5d,0xa4, - 0x62,0x43,0x05,0x0b,0xba,0x29,0x36,0xeb,0xbd,0x23,0xb6,0x02,0xf6,0x62,0x4e,0xf3, - 0xff,0xee,0x3d,0x92,0xbe,0x65,0xc0,0x4a,0xb1,0x60,0x60,0x46,0x23,0x85,0x67,0x71, - 0xe4,0x25,0x6b,0x58,0xdc,0x91,0x4c,0x05,0x54,0xfa,0x4b,0xa5,0x60,0x82,0x3e,0xa2, - 0x4f,0x3e,0xc7,0xe5,0xf0,0x2b,0xa6,0x9d,0x55,0xdc,0x98,0x46,0xd7,0xec,0x3e,0x47, - 0x5b,0x4c,0x02,0x46,0x9c,0x2d,0x25,0x6d,0x55,0x25,0xfc,0x67,0xc2,0xe9,0xbf,0xa1, - 0xb0,0x5b,0x97,0xf8,0x4f,0xae,0xdf,0xab,0x50,0xa0,0x0b,0x5b,0xc8,0x78,0xcc,0xcd, - 0x50,0x55,0xc6,0x46,0x21,0x01,0x7e,0xac,0x38,0xe2,0x10,0x34,0x0b,0x22,0x64,0xa7, - 0xa5,0xe4,0x7f,0x60,0x51,0x75,0xdf,0x32,0x87,0xd4,0xa6,0x06,0x4f,0x8c,0x60,0x15, - 0xd0,0x1f,0xc1,0xbb,0xa4,0xca,0x4a,0xac,0x80,0xf1,0x7f,0x3a,0xfc,0x4a,0xe7,0x4e, - 0xb8,0xc2,0xdb,0x84,0xd8,0x5c,0xeb,0x44,0x23,0xec,0x9e,0x92,0x72,0xb7,0x45,0x02, - 0xee,0x52,0x08,0x47,0xb6,0x09,0x5d,0xdc,0xe5,0x26,0xae,0x61,0x42,0x77,0x13,0x85, - 0xa2,0x4f,0xf0,0xb0,0x46,0x88,0x2a,0x3c,0x09,0x98,0x89,0xe3,0xf1,0x69,0x89,0x0a, - 0x76,0xd9,0x8e,0x7e,0x0c,0xd7,0xcc,0x16,0xda,0xfd,0xfb,0x96,0x2b,0xd7,0xe2,0x8d, - 0x54,0x3f,0x75,0x2f,0x66,0x6b,0x72,0x8f,0xbd,0x5c,0x3c,0x05,0xa7,0xe4,0x11,0x06, - 0xcf,0x4a,0xd6,0x32,0x95,0x42,0x71,0xc6,0x2b,0xf9,0x8b,0xe6,0xda,0x0c,0x37,0xa8, - 0xed,0x7b,0x71,0x9a,0xea,0x8e,0xa1,0xbd,0x27,0x8f,0x45,0x00,0x48,0x40,0xba,0xf4, - 0x41,0x0e,0xb6,0x98,0x88,0xed,0xc7,0x3d,0xbd,0x59,0x52,0xc4,0xeb,0xbc,0xb8,0x0b, - 0x22,0x5e,0x68,0x79,0xc9,0x71,0x3d,0xd7,0x31,0x4c,0x55,0x40,0xcd,0x1f,0x41,0x0c, - 0xd7,0xb0,0x02,0x47,0xb0,0x9f,0xfa,0xb2,0x60,0xd4,0x3c,0x64,0xe8,0xc5,0xae,0xe8, - 0x12,0xad,0x84,0xc3,0xe1,0xfd,0x1e,0x20,0x6f,0x20,0x2e,0xbe,0xa9,0xd4,0x30,0xb6, - 0x6c,0xa5,0xf0,0x03,0x75,0xae,0x1b,0xb1,0x15,0x36,0x8d,0xba,0x0f,0x1e,0xb7,0x74, - 0x8b,0xa4,0x41,0xfd,0x13,0x7a,0xa9,0x16,0x22,0x54,0xe4,0x60,0x38,0x52,0xb6,0x60, - 0x8b,0x7f,0x7a,0xb9,0x2a,0xb0,0x28,0x63,0x71,0xeb,0x29,0x52,0xab,0x66,0x70,0x66, - 0x72,0x12,0xe9,0x4d,0xf4,0x01,0xba,0x88,0xb6,0x15,0xe1,0xb9,0x67,0x10,0x0a,0x59, - 0xc8,0x12,0x1b,0x81,0x6a,0x4c,0x79,0x0f,0x94,0xd7,0xa7,0xa8,0x4c,0x25,0xf2,0xd3, - 0x4d,0x23,0x6c,0x9d,0x65,0x81,0x75,0x72,0xd9,0xca,0xa5,0x32,0xa5,0x9a,0xcc,0xef, - 0xfe,0xb2,0x30,0x2f,0x6c,0x17,0x53,0xac,0x9d,0xc6,0xd5,0x6a,0x85,0x35,0xfa,0x17, - 0xe4,0xfa,0xb8,0x93,0x18,0xc6,0x82,0x42,0xa4,0xaf,0x72,0x7d,0xd4,0xbd,0xf2,0xe3, - 0x7b,0x6e,0x56,0x2d,0x25,0xeb,0xeb,0x53,0x4e,0x34,0xaa,0x86,0x5d,0xcb,0xe1,0xd6, - 0x22,0x4d,0x74,0xee,0x37,0xbd,0x8d,0x43,0xf8,0x3b,0xdb,0xf6,0x9a,0xef,0xe9,0x7f, - 0x3d,0x7f,0x74,0xe6,0x25,0xbb,0xf9,0x4a,0xf8,0x20,0x07,0x94,0x30,0x43,0x48,0xab, - 0x0e,0x1d,0x97,0xd6,0x01,0xa1,0x5b,0x9e,0x92,0xa2,0xeb,0xbe,0x22,0xe8,0x2f,0xb0, - 0x31,0x24,0xb4,0xb5,0x2b,0x73,0xf2,0xdd,0x29,0x5b,0xfd,0x1b,0x18,0x3e,0x3a,0xe6, - 0xa3,0x4b,0x0b,0x19,0xe3,0x4c,0x83,0x8b,0xe3,0x5f,0x94,0xd7,0x5a,0x33,0xb3,0x3d, - 0x3c,0x3f,0xf2,0x16,0x39,0x84,0x48,0x6b,0xc4,0x21,0x87,0x68,0xa7,0xe7,0x94,0xb4, - 0x4f,0x36,0x97,0x28,0x9a,0xbd,0xd4,0x5c,0xf5,0x89,0x5a,0x46,0xf4,0x4b,0x1f,0xe9, - 0x5c,0x48,0xae,0x51,0xe5,0x6f,0xb3,0xea,0xe2,0x6e,0x4e,0x72,0x2d,0x87,0x8c,0x5d, - 0x07,0x3e,0xfb,0x1c,0x95,0x88,0x9e,0xde,0xec,0xc2,0xd1,0x7c,0xef,0x6d,0x4e,0x19, - 0x0c,0xbc,0x6f,0x9f,0xd1,0xa0,0x8e,0x71,0xc8,0x13,0xe6,0xc9,0x21,0xcb,0x31,0x77, - 0x13,0x38,0x14,0xe9,0x25,0xea,0x5c,0x35,0x48,0x06,0x2c,0x4d,0xbe,0x53,0x76,0x51, - 0x1d,0x7a,0x88,0x31,0x62,0x30,0x3b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, - 0x09,0x14,0x31,0x2e,0x1e,0x2c,0x00,0x54,0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x2d, - 0x00,0x53,0x00,0x69,0x00,0x67,0x00,0x6e,0x00,0x4f,0x00,0x6e,0x00,0x6c,0x00,0x79, - 0x00,0x20,0x00,0x28,0x00,0x53,0x00,0x2f,0x00,0x4d,0x00,0x49,0x00,0x4d,0x00,0x45, - 0x00,0x29,0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x15,0x31, - 0x16,0x04,0x14,0x6f,0x7c,0x20,0x36,0xbe,0x29,0x2b,0xca,0x1a,0xbf,0x51,0xb7,0x15, - 0x8a,0xf9,0x7c,0x2b,0x4e,0x04,0xe8,0x30,0x30,0x30,0x21,0x30,0x09,0x06,0x05,0x2b, - 0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0x0e,0xb5,0xcf,0xf5,0x4e,0x2b,0x2c,0x5d, - 0x2e,0x43,0xc9,0x60,0xf2,0x16,0x0f,0xd2,0xe6,0x50,0x93,0x0b,0x04,0x08,0xf0,0x18, - 0xb1,0xdb,0x61,0x97,0x53,0xcb,0x02,0x01,0x01 -}; - -/* Test identity (PKCS12 data) +unsigned char Test_smime_signonly_p12[] = { + 0x30, 0x82, 0x0a, 0xdd, 0x02, 0x01, 0x03, 0x30, 0x82, 0x0a, 0xa4, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x82, 0x0a, 0x95, 0x04, 0x82, 0x0a, 0x91, 0x30, 0x82, 0x0a, 0x8d, 0x30, 0x82, 0x05, 0x07, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x04, 0xf8, 0x30, 0x82, 0x04, 0xf4, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x04, 0xed, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0xa7, 0xf8, 0xe5, 0x65, 0x62, 0x31, 0xe0, + 0xa6, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x04, 0xc0, 0x2b, 0xf6, 0xdc, 0x0d, 0x1c, 0xce, 0x0d, 0x2a, 0xa8, 0x50, 0x94, + 0xc5, 0x52, 0x04, 0xa0, 0x07, 0x8b, 0xf2, 0x31, 0x4e, 0x5e, 0xfe, 0xe7, 0x8f, 0x53, 0xac, 0x98, 0x1a, 0x04, 0x08, 0xdc, + 0xd9, 0xc6, 0xd5, 0xee, 0xbd, 0x43, 0x15, 0x55, 0xf8, 0x03, 0xa7, 0x05, 0x31, 0x7f, 0xee, 0x36, 0xa8, 0x43, 0xdb, 0x09, + 0x25, 0x61, 0x8e, 0x1c, 0xd2, 0x84, 0x22, 0xc2, 0xf5, 0x2f, 0x29, 0x4b, 0x97, 0xfd, 0x38, 0xb8, 0x4d, 0xde, 0x76, 0x28, + 0xe9, 0xd9, 0xf7, 0xf1, 0x77, 0xdd, 0x7d, 0x6f, 0x35, 0xf7, 0x73, 0x94, 0xeb, 0x39, 0x5d, 0xaf, 0x92, 0xca, 0x07, 0x39, + 0xa2, 0x8a, 0xd2, 0xcd, 0xe0, 0x69, 0x5b, 0x2f, 0xc3, 0x29, 0x1c, 0xbb, 0x27, 0x01, 0x83, 0x49, 0xfe, 0x55, 0x75, 0x1f, + 0x56, 0xf4, 0xf8, 0xed, 0x60, 0xe3, 0xee, 0x10, 0x40, 0x4d, 0x67, 0xdb, 0x1b, 0x4e, 0x0b, 0x03, 0x65, 0xfc, 0x10, 0x9f, + 0x40, 0x19, 0xcd, 0xe7, 0x5b, 0x6f, 0x8d, 0xf4, 0x21, 0x80, 0x1e, 0x81, 0xae, 0x34, 0xac, 0x70, 0xf5, 0xdd, 0x59, 0xb7, + 0xd8, 0x31, 0x9f, 0xd9, 0xec, 0x54, 0x8c, 0x93, 0x73, 0x78, 0xbf, 0x5c, 0xf9, 0x29, 0x8b, 0x32, 0xdd, 0x3d, 0xb5, 0xe8, + 0xdf, 0xe6, 0x78, 0xd2, 0xbe, 0x9d, 0x55, 0x2d, 0xde, 0x23, 0xe4, 0x14, 0xc2, 0x7b, 0x38, 0xce, 0x27, 0x22, 0x0b, 0x6a, + 0x05, 0x22, 0x27, 0x39, 0x04, 0x99, 0x6f, 0x02, 0x74, 0xc0, 0xc8, 0xcd, 0x8d, 0xa7, 0x76, 0x9f, 0x41, 0x76, 0x6b, 0x97, + 0x5f, 0x40, 0xc4, 0xa4, 0x77, 0x85, 0x2b, 0x18, 0x94, 0x79, 0xa3, 0x2a, 0x8d, 0x72, 0x5c, 0x8a, 0x15, 0xad, 0x57, 0x87, + 0xc3, 0x72, 0x83, 0x89, 0x4a, 0xec, 0x92, 0xb6, 0xad, 0xb0, 0x5a, 0xb6, 0x1a, 0x53, 0x61, 0x28, 0x66, 0xfc, 0x9c, 0x4a, + 0x4f, 0xfd, 0x38, 0x2a, 0x00, 0x55, 0x56, 0x03, 0xff, 0x09, 0xb0, 0xff, 0xbc, 0xa6, 0x78, 0x43, 0x0c, 0x90, 0xc7, 0x6d, + 0x25, 0x45, 0x73, 0x61, 0x55, 0x24, 0x5d, 0x93, 0x2c, 0x38, 0x4f, 0x8d, 0x68, 0x41, 0xfe, 0xeb, 0xbc, 0xae, 0xee, 0x92, + 0xa5, 0xbd, 0x6c, 0x1f, 0x4c, 0xe2, 0xb2, 0xc8, 0x42, 0x50, 0x5c, 0xa9, 0xa3, 0x53, 0x46, 0x6b, 0xa1, 0x4e, 0x69, 0x6f, + 0xe0, 0x12, 0xc4, 0x03, 0x1e, 0xe5, 0xc1, 0xad, 0x8d, 0x57, 0x95, 0xfd, 0x24, 0x85, 0xd7, 0x2b, 0x5d, 0xbb, 0x72, 0x5b, + 0x62, 0x72, 0x97, 0xdd, 0xb8, 0xb1, 0x7a, 0xf7, 0x42, 0x2c, 0x9f, 0xe2, 0x6e, 0x57, 0x7d, 0xee, 0x72, 0x67, 0xec, 0x98, + 0x3a, 0x63, 0x44, 0x28, 0x75, 0xce, 0x9b, 0x5e, 0x95, 0xe6, 0x34, 0x7c, 0x1e, 0x56, 0x33, 0x3d, 0x31, 0x69, 0xd6, 0xf7, + 0x62, 0xa9, 0x7c, 0x0e, 0xf7, 0x9d, 0xf8, 0x7d, 0xfe, 0x86, 0x12, 0x62, 0x18, 0xf1, 0xdd, 0xbf, 0x37, 0x73, 0xb2, 0x0b, + 0x81, 0xb4, 0x38, 0xcb, 0x93, 0x8c, 0x3a, 0xe6, 0xd6, 0x72, 0x39, 0x09, 0x84, 0x09, 0xd7, 0x14, 0xc1, 0x67, 0x78, 0xc4, + 0x5a, 0xa3, 0xa6, 0x0b, 0x0c, 0xd8, 0xd4, 0xda, 0xd7, 0xb8, 0x3a, 0x86, 0xcc, 0x44, 0x7d, 0xf6, 0x30, 0x4f, 0x07, 0x9f, + 0x8a, 0x28, 0x22, 0x89, 0x34, 0xd3, 0x7b, 0xe6, 0x1b, 0xac, 0x9a, 0x11, 0xdd, 0x06, 0x72, 0x6e, 0x3f, 0x39, 0x3f, 0x18, + 0x92, 0xc8, 0x93, 0xbb, 0x7c, 0x4a, 0x65, 0xad, 0xba, 0xfb, 0x6b, 0x29, 0xe3, 0xd5, 0x0d, 0xfc, 0xf1, 0x05, 0x91, 0x9d, + 0x3f, 0x86, 0x86, 0xd3, 0xf3, 0x48, 0x8b, 0xba, 0x97, 0x59, 0xaf, 0xfb, 0x06, 0x34, 0x6e, 0x09, 0x5b, 0x4f, 0x4a, 0xdf, + 0x3c, 0x94, 0xc7, 0x18, 0xb0, 0xf0, 0x23, 0xaf, 0x2f, 0x4e, 0x29, 0xd2, 0x99, 0xc3, 0x5f, 0x43, 0x52, 0xd2, 0x93, 0x1b, + 0x8c, 0x13, 0x08, 0x5c, 0xa3, 0x5a, 0x68, 0x14, 0x7d, 0xda, 0xad, 0x92, 0xb5, 0xd0, 0x13, 0xe6, 0x21, 0xbc, 0x5b, 0xd5, + 0xfa, 0x4e, 0xd7, 0x01, 0x8b, 0xa0, 0x9a, 0xfd, 0x02, 0x02, 0xc3, 0x9e, 0x7f, 0xfc, 0xc0, 0x90, 0x2a, 0xdd, 0xac, 0xa0, + 0x01, 0x92, 0x39, 0x23, 0xb4, 0x3b, 0x2a, 0x13, 0x56, 0xcb, 0x78, 0xf5, 0xe1, 0xac, 0x15, 0x7f, 0x22, 0x38, 0x77, 0x0c, + 0xa8, 0xfc, 0x46, 0x14, 0x02, 0xbe, 0x28, 0xf2, 0xa4, 0x59, 0x68, 0x01, 0x73, 0x4a, 0x52, 0xea, 0xfe, 0xb8, 0x8e, 0x59, + 0xf2, 0x41, 0xaa, 0x04, 0x77, 0x20, 0xc6, 0x57, 0x62, 0x60, 0xb3, 0xc0, 0x6b, 0x2b, 0x5b, 0x4d, 0x64, 0x0c, 0xfe, 0x09, + 0x92, 0x35, 0x9f, 0xde, 0xfe, 0xad, 0x8e, 0xd6, 0xf3, 0x8f, 0xb9, 0xf4, 0x77, 0x0f, 0xed, 0x47, 0x0d, 0x77, 0x59, 0x9c, + 0xda, 0x7f, 0x40, 0xa1, 0xee, 0x6c, 0xaf, 0x66, 0x69, 0x12, 0x3a, 0x42, 0x98, 0x55, 0x91, 0x34, 0xf8, 0x02, 0x57, 0xf9, + 0xf1, 0x9c, 0x5e, 0x7f, 0xec, 0x44, 0x14, 0x21, 0x8b, 0x21, 0x98, 0xe8, 0x62, 0x00, 0x0b, 0x9b, 0xe2, 0xc8, 0xff, 0xfe, + 0xf5, 0xa0, 0xc5, 0x6a, 0x61, 0x75, 0x6f, 0xbf, 0x1f, 0x8d, 0x72, 0xbe, 0x48, 0x1f, 0xdf, 0x58, 0xba, 0x13, 0x33, 0x60, + 0x8f, 0xc4, 0x5b, 0xf3, 0x70, 0x94, 0xee, 0x25, 0x98, 0x5e, 0x30, 0x40, 0x7f, 0x1c, 0xf6, 0x34, 0xb5, 0x6d, 0x5c, 0xc2, + 0x45, 0xad, 0x1b, 0x88, 0x9e, 0x10, 0x59, 0x86, 0xcf, 0x49, 0xaa, 0xa4, 0x72, 0xee, 0x1c, 0xeb, 0x21, 0x85, 0x78, 0x5c, + 0x1a, 0x08, 0x33, 0x6d, 0x52, 0xf3, 0xde, 0x86, 0x64, 0x2a, 0x34, 0x9e, 0x17, 0x16, 0xc5, 0xaf, 0xc9, 0x5a, 0xb0, 0x69, + 0xcb, 0xdf, 0x6f, 0x23, 0x67, 0xe7, 0x02, 0x93, 0xf8, 0x79, 0x3d, 0xc1, 0x7f, 0x7e, 0xe7, 0x9a, 0xb2, 0xa8, 0x5b, 0x11, + 0x64, 0x8c, 0x4b, 0x71, 0x29, 0xc4, 0x8c, 0xa5, 0x3b, 0xcf, 0x42, 0x48, 0x41, 0x2b, 0x29, 0x31, 0xc4, 0xfc, 0x21, 0x69, + 0x10, 0x1e, 0x8c, 0xde, 0x02, 0x45, 0x43, 0x30, 0x4a, 0x9f, 0x4b, 0x8f, 0x4f, 0xf5, 0x63, 0x4f, 0x6d, 0xed, 0x7c, 0x37, + 0x3f, 0x88, 0x43, 0x01, 0x95, 0xba, 0x49, 0x03, 0xa1, 0xe0, 0xe6, 0xf9, 0x58, 0x3a, 0x50, 0xf3, 0x3f, 0xcf, 0x15, 0xc7, + 0x30, 0x4b, 0x56, 0xad, 0x74, 0x9e, 0x1d, 0xe1, 0x1f, 0x33, 0x33, 0x10, 0x9f, 0x55, 0xf6, 0xad, 0xf2, 0x07, 0x32, 0x39, + 0xd4, 0x6e, 0x32, 0xd2, 0xc5, 0xbb, 0x67, 0x7d, 0x77, 0xd3, 0x21, 0xb5, 0xce, 0x5f, 0x07, 0xc4, 0x61, 0x6b, 0x67, 0x1d, + 0x58, 0x56, 0xf7, 0xa3, 0x99, 0x4f, 0x7a, 0x9d, 0xd3, 0x78, 0x07, 0x7f, 0x4e, 0x24, 0x94, 0x2e, 0x75, 0x46, 0xd0, 0x1e, + 0x76, 0x77, 0xf1, 0x18, 0x1c, 0xbf, 0x3e, 0xe5, 0x42, 0x45, 0x9c, 0x30, 0x78, 0x64, 0x5e, 0x55, 0x43, 0x42, 0x4e, 0x60, + 0x1f, 0x57, 0xc3, 0xd3, 0xe3, 0xf4, 0x8b, 0x4c, 0xaf, 0x18, 0xc0, 0xa9, 0xf8, 0xe5, 0xd3, 0x96, 0xe0, 0xd2, 0x0a, 0x05, + 0xc5, 0x2a, 0x42, 0x16, 0xc9, 0x1d, 0x90, 0xfb, 0x4b, 0x2d, 0x3b, 0xbf, 0x14, 0xfc, 0x7b, 0x47, 0x11, 0xf7, 0x46, 0x7b, + 0x31, 0xb4, 0x2f, 0x25, 0x89, 0xed, 0x5d, 0x95, 0x7c, 0x0b, 0xe9, 0x89, 0x7a, 0x0a, 0x83, 0xc2, 0x08, 0xcc, 0x61, 0x8d, + 0x7a, 0xf3, 0x3a, 0x7e, 0x7e, 0xa4, 0x16, 0x36, 0x0e, 0x9e, 0xac, 0xd3, 0x01, 0x0d, 0x60, 0x0c, 0x5e, 0xca, 0x2d, 0xcc, + 0x59, 0xd8, 0x9d, 0x67, 0xb6, 0xc0, 0x81, 0xa7, 0xcb, 0x64, 0x8f, 0x03, 0x18, 0xc8, 0xba, 0x2b, 0x3d, 0x83, 0x37, 0x7e, + 0xe2, 0x24, 0x9e, 0xff, 0xef, 0x78, 0x0c, 0x24, 0xaf, 0x90, 0x83, 0x45, 0x29, 0xfd, 0x1c, 0x1e, 0xc3, 0xf9, 0x49, 0x88, + 0x48, 0xf3, 0xae, 0x22, 0x26, 0x07, 0xa6, 0xc6, 0x50, 0xed, 0xda, 0xb7, 0xb8, 0x4e, 0x1f, 0x6c, 0x7f, 0x9c, 0x54, 0x77, + 0x0c, 0x66, 0x0b, 0x65, 0x4b, 0xdd, 0x9a, 0x9f, 0x69, 0xdc, 0x9a, 0x3a, 0xfc, 0xa8, 0x1c, 0xb5, 0xcf, 0xfd, 0x9a, 0x9d, + 0x49, 0x5e, 0xcb, 0xd5, 0xa8, 0xcd, 0x89, 0xa6, 0xd3, 0x26, 0xfd, 0xa3, 0x8f, 0x46, 0xb8, 0x98, 0x63, 0x0d, 0x0a, 0xd8, + 0x21, 0xed, 0xa5, 0x5f, 0x0a, 0x6e, 0x8b, 0xd1, 0xd7, 0x93, 0xca, 0xa8, 0xc2, 0x54, 0x6d, 0x8e, 0x4a, 0x3a, 0x87, 0x50, + 0x23, 0x6c, 0x98, 0x4d, 0x61, 0xc9, 0x21, 0xca, 0xfa, 0xe9, 0x14, 0xaf, 0x85, 0x07, 0x66, 0x40, 0xe4, 0x3c, 0x78, 0xcf, + 0x8f, 0x0d, 0x06, 0xe2, 0xce, 0x5b, 0x38, 0xdd, 0x6c, 0x99, 0x95, 0x7a, 0x3a, 0xaf, 0xfb, 0x82, 0xdb, 0x94, 0x51, 0x6d, + 0x99, 0xd6, 0x47, 0x41, 0x16, 0x8c, 0x7e, 0x30, 0xb4, 0x86, 0x42, 0xe7, 0xad, 0x38, 0x16, 0x12, 0x3e, 0x6b, 0xcf, 0xb8, + 0x8f, 0x08, 0x8c, 0xce, 0xc9, 0xf5, 0x5a, 0x6d, 0x6d, 0x1c, 0xef, 0xa3, 0xee, 0x44, 0x1e, 0x48, 0xe4, 0x41, 0xc6, 0xfa, + 0x38, 0x63, 0xf6, 0x7d, 0x50, 0x59, 0x36, 0x9b, 0x8a, 0xbc, 0x66, 0x9d, 0x3d, 0xac, 0xe0, 0x4a, 0x2b, 0x27, 0xd4, 0x0a, + 0x5e, 0x8c, 0xd2, 0x03, 0xde, 0x30, 0x82, 0x05, 0x7e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0xa0, 0x82, 0x05, 0x6f, 0x04, 0x82, 0x05, 0x6b, 0x30, 0x82, 0x05, 0x67, 0x30, 0x82, 0x05, 0x63, 0x06, 0x0b, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, + 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xe8, 0xe9, 0xa0, 0xff, 0x46, + 0xbd, 0xb7, 0xbe, 0x02, 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0xb7, 0xe8, 0x82, 0xae, 0xfd, 0x43, 0x15, 0xbb, 0xf4, + 0x94, 0x2d, 0x8d, 0x28, 0x5c, 0x66, 0xc4, 0x78, 0x5b, 0x0f, 0x41, 0xf9, 0x8e, 0x65, 0x3f, 0xf3, 0x06, 0x99, 0x36, 0x70, + 0xeb, 0x99, 0x38, 0x29, 0x49, 0xea, 0x28, 0xc4, 0x84, 0x11, 0x8c, 0x4f, 0x5e, 0x61, 0x7c, 0x3f, 0xc3, 0x61, 0x16, 0x1b, + 0xce, 0x50, 0xc9, 0xd6, 0x3e, 0x0e, 0x96, 0x93, 0xd1, 0xf7, 0x1a, 0x79, 0x86, 0x86, 0x22, 0x7e, 0x39, 0xc0, 0x15, 0x49, + 0x69, 0xc5, 0x56, 0xf9, 0xb6, 0xeb, 0xe0, 0x36, 0x53, 0x01, 0xc1, 0xb9, 0x2d, 0x31, 0xdb, 0xdc, 0x12, 0xe0, 0x1b, 0x85, + 0x4b, 0x11, 0xfa, 0x74, 0xd5, 0x5b, 0x4a, 0x84, 0xbc, 0x7e, 0x1f, 0xf4, 0x1e, 0x04, 0x75, 0x5e, 0x75, 0x6b, 0xb0, 0x6f, + 0xc0, 0xb6, 0x5c, 0x0b, 0x93, 0xe7, 0x96, 0x94, 0x4c, 0x17, 0x97, 0xce, 0x4e, 0x2c, 0xe8, 0x48, 0xff, 0x89, 0xd5, 0x8c, + 0x41, 0xe1, 0x0d, 0xed, 0xb2, 0x82, 0x7a, 0x75, 0x49, 0xbf, 0x0e, 0xf2, 0xec, 0x06, 0x8b, 0xa7, 0x86, 0xd8, 0x95, 0x4a, + 0x3e, 0x5a, 0x78, 0xea, 0xf3, 0xee, 0xff, 0x5b, 0xc9, 0x21, 0x58, 0x88, 0x2c, 0x84, 0xab, 0x1f, 0x79, 0x07, 0xae, 0x98, + 0x6a, 0xa0, 0xc9, 0x93, 0x3d, 0x74, 0x67, 0x43, 0x5b, 0x2d, 0xfb, 0x57, 0xc8, 0x24, 0x8e, 0xe6, 0x74, 0x0f, 0x11, 0x53, + 0x8d, 0x2b, 0xd9, 0xa6, 0x44, 0x11, 0x32, 0xab, 0xec, 0x08, 0xe4, 0x63, 0xb3, 0x19, 0x5d, 0xd2, 0xff, 0x7d, 0x29, 0xb2, + 0x4e, 0xc0, 0x44, 0x0b, 0xd2, 0x68, 0x4d, 0xc0, 0xbf, 0x24, 0xcd, 0x01, 0x26, 0x31, 0x52, 0xcf, 0x1c, 0x14, 0x8f, 0x70, + 0x31, 0x1f, 0x68, 0x19, 0xfd, 0x81, 0x09, 0xef, 0xbd, 0xc0, 0xa7, 0xcd, 0xd9, 0x6c, 0xff, 0xf7, 0xb1, 0x11, 0xbb, 0xfa, + 0x8b, 0x73, 0x22, 0xd9, 0x3a, 0x74, 0xa3, 0x49, 0x54, 0xd7, 0x52, 0x53, 0xd5, 0xaa, 0x1b, 0x72, 0xbd, 0xa6, 0x44, 0x7d, + 0xed, 0x97, 0xe9, 0xfd, 0xcf, 0x26, 0x2b, 0x3c, 0x3a, 0x00, 0xf7, 0x3f, 0xf7, 0xdc, 0x91, 0x3a, 0x65, 0x5b, 0xcb, 0xba, + 0x79, 0x5c, 0xb7, 0xfb, 0x79, 0x15, 0xe7, 0x7d, 0x1c, 0xd8, 0xf5, 0x89, 0x0f, 0xb1, 0x5e, 0x8d, 0x96, 0xa2, 0xef, 0x3f, + 0x8d, 0x27, 0x38, 0x36, 0xd5, 0xcf, 0xe5, 0x67, 0xd0, 0xa9, 0xa5, 0xde, 0x16, 0xe7, 0xe7, 0x62, 0x04, 0x55, 0x66, 0xfd, + 0x9f, 0xa4, 0x10, 0xcb, 0x30, 0x12, 0x10, 0x24, 0xb4, 0x7f, 0x63, 0x6a, 0x38, 0xd0, 0x9b, 0x77, 0x93, 0x27, 0xda, 0x72, + 0xeb, 0xdb, 0x79, 0x26, 0x92, 0x60, 0xc5, 0x41, 0xb9, 0xe6, 0xce, 0x08, 0xaf, 0x3e, 0x0f, 0xe6, 0x8d, 0x17, 0x7e, 0x3b, + 0xbc, 0x37, 0x57, 0x16, 0x54, 0xbe, 0x8c, 0x6a, 0xda, 0xb1, 0x7c, 0x46, 0xee, 0xc7, 0xed, 0x26, 0x76, 0x91, 0x01, 0xd5, + 0x9c, 0x7b, 0xc2, 0xb7, 0x6f, 0x8c, 0xa1, 0xd1, 0x93, 0x50, 0x0c, 0x27, 0x0c, 0x74, 0xa4, 0x80, 0x7c, 0x3d, 0x28, 0x93, + 0x21, 0xbe, 0xc9, 0x9f, 0xb5, 0x0a, 0xc8, 0x31, 0x12, 0x25, 0x90, 0x3f, 0x9a, 0x6d, 0x20, 0x02, 0xa0, 0xd6, 0x21, 0x53, + 0x10, 0x55, 0x19, 0x48, 0x57, 0xf8, 0x2a, 0x48, 0xc4, 0xb5, 0xa1, 0x79, 0xac, 0x53, 0xbd, 0x2b, 0xde, 0x4d, 0xa4, 0x77, + 0xe4, 0x1f, 0x87, 0x9f, 0x9f, 0xd1, 0x9c, 0x00, 0x8d, 0x7b, 0x83, 0x4a, 0xc4, 0x25, 0xf2, 0xb7, 0xfc, 0xb8, 0x0e, 0x97, + 0x26, 0x70, 0x26, 0x89, 0x86, 0xe6, 0x15, 0xaa, 0x8f, 0x5e, 0x76, 0xb3, 0x3f, 0x8b, 0x01, 0xda, 0xf5, 0x99, 0x01, 0x32, + 0xc3, 0x76, 0x19, 0x93, 0xca, 0xda, 0x27, 0xb1, 0x74, 0x0e, 0x84, 0x4b, 0x02, 0x4b, 0x50, 0x31, 0x64, 0x69, 0xd9, 0xa4, + 0x21, 0x85, 0xfd, 0xab, 0x69, 0xf3, 0x66, 0x40, 0x43, 0x13, 0x4f, 0x58, 0xf5, 0x03, 0x3b, 0xc1, 0xea, 0x40, 0xeb, 0xe4, + 0xca, 0x63, 0x29, 0xca, 0x41, 0x64, 0x7a, 0x0e, 0xb9, 0x46, 0xf2, 0xcb, 0xa0, 0xf3, 0x3e, 0x35, 0xaf, 0xe1, 0x81, 0xa9, + 0xd3, 0x0c, 0xef, 0xe9, 0x2d, 0xc4, 0x10, 0x46, 0x24, 0xd0, 0x6d, 0xab, 0xb1, 0xd3, 0xe0, 0x4a, 0x43, 0xcd, 0x3f, 0xa4, + 0xe4, 0xdc, 0x3e, 0x70, 0x07, 0x62, 0x93, 0x27, 0x32, 0x46, 0x57, 0x85, 0x45, 0x6a, 0xcf, 0x0d, 0xec, 0x08, 0xf0, 0x07, + 0x6c, 0xb8, 0x87, 0xd1, 0xc5, 0xa3, 0xf0, 0xd6, 0xaf, 0x37, 0x09, 0xff, 0xbc, 0x15, 0x56, 0x60, 0xfc, 0x2a, 0xec, 0xbf, + 0x8c, 0x22, 0x1c, 0xef, 0xaa, 0xfe, 0x6a, 0x42, 0xa0, 0x41, 0xdd, 0x8d, 0x7d, 0xa8, 0x74, 0xa8, 0xb4, 0xfc, 0x12, 0x2e, + 0xf2, 0xe6, 0xbe, 0xa6, 0xbc, 0x31, 0x01, 0x40, 0xa4, 0x27, 0xc2, 0x75, 0xbb, 0x12, 0x91, 0xc9, 0x84, 0xa0, 0xd5, 0xff, + 0xaa, 0x8d, 0x8f, 0x22, 0xd0, 0x05, 0x05, 0x63, 0xe1, 0xa3, 0xa0, 0xfc, 0x7d, 0xb4, 0xd9, 0x26, 0xcf, 0x77, 0x46, 0x36, + 0x9a, 0xdd, 0x97, 0x8f, 0xc6, 0x79, 0x99, 0x81, 0x47, 0x91, 0x00, 0xe3, 0x88, 0xe4, 0x09, 0xca, 0xb9, 0x2c, 0x66, 0x70, + 0xa2, 0x1c, 0xc7, 0xb9, 0xfe, 0xd3, 0x3e, 0x8f, 0x52, 0x5a, 0xfb, 0x63, 0x8d, 0x06, 0x36, 0xd9, 0x40, 0xf6, 0x4a, 0x99, + 0xcf, 0xf6, 0x60, 0x02, 0xb2, 0xff, 0x81, 0x51, 0x44, 0xf7, 0x69, 0x7a, 0xc6, 0xf9, 0x6a, 0xe3, 0x3a, 0xc5, 0x11, 0xc3, + 0x61, 0xe7, 0x09, 0xdd, 0x88, 0x04, 0x0c, 0x41, 0xbf, 0x41, 0x6e, 0x20, 0x5c, 0xf0, 0x6b, 0x3c, 0x57, 0x3b, 0x03, 0x16, + 0x25, 0xc7, 0x39, 0x42, 0x4d, 0x32, 0x30, 0xd3, 0x12, 0xbf, 0x85, 0x3b, 0x90, 0x9a, 0x38, 0xe1, 0x6c, 0x32, 0x5b, 0xe5, + 0xa0, 0x8e, 0xab, 0x7f, 0xcc, 0x36, 0x91, 0x7b, 0xd3, 0x45, 0x47, 0xa5, 0x14, 0x47, 0xb0, 0x0a, 0x0f, 0x29, 0xcd, 0xbc, + 0x72, 0x2c, 0xc9, 0x47, 0xf4, 0xd7, 0x3e, 0x5c, 0x25, 0x85, 0x9b, 0x7d, 0xa9, 0xf7, 0xdc, 0xec, 0xfe, 0x7b, 0x6b, 0xad, + 0x00, 0x24, 0xd2, 0x84, 0xd8, 0xd1, 0xc1, 0x2a, 0xde, 0x0d, 0x14, 0x46, 0x87, 0xa6, 0x83, 0x59, 0x6b, 0xde, 0x06, 0xf8, + 0x1c, 0x81, 0x04, 0x3e, 0x14, 0xac, 0x9a, 0xe4, 0xc4, 0xe1, 0x51, 0xbb, 0xcf, 0xe0, 0xf5, 0xc3, 0x40, 0xdd, 0x1e, 0xae, + 0x3e, 0x06, 0x45, 0x80, 0x7a, 0x6b, 0x07, 0x58, 0xc1, 0xcf, 0xb3, 0x22, 0xd4, 0xfe, 0xc0, 0x01, 0x86, 0x16, 0x48, 0x5a, + 0x04, 0xe9, 0x3c, 0xa0, 0xdb, 0x2d, 0x57, 0xec, 0x6f, 0x83, 0x4e, 0x14, 0xcc, 0xf8, 0x01, 0x3b, 0x46, 0x6a, 0xec, 0xd0, + 0xd3, 0x13, 0x29, 0xf5, 0x61, 0x38, 0x7a, 0x41, 0xd6, 0xca, 0x87, 0x4e, 0x91, 0x67, 0x3a, 0x7f, 0x4e, 0x1e, 0x40, 0x07, + 0xad, 0x0d, 0x80, 0xac, 0x83, 0xd2, 0x4d, 0xee, 0xc6, 0x81, 0xab, 0x86, 0x58, 0xd0, 0x86, 0x3e, 0x97, 0x95, 0xef, 0xec, + 0xbe, 0xd6, 0xe9, 0xc1, 0xce, 0x2e, 0xa5, 0xd1, 0x71, 0x1c, 0x7e, 0xb9, 0xa4, 0x5f, 0xcc, 0x12, 0x96, 0x13, 0x50, 0x6d, + 0x07, 0x8c, 0xa3, 0xa5, 0x40, 0x73, 0xb3, 0x90, 0x70, 0x92, 0x4b, 0x48, 0x95, 0xb7, 0x38, 0x72, 0xe3, 0x9c, 0x1d, 0x1d, + 0x6b, 0x4a, 0x29, 0xf3, 0xf5, 0x77, 0xfb, 0x5e, 0x44, 0x4e, 0x2b, 0xec, 0xc2, 0x65, 0xd2, 0x4c, 0x6c, 0xad, 0xac, 0xb7, + 0x64, 0x9a, 0xd2, 0xbf, 0x10, 0x53, 0xdd, 0x2d, 0x48, 0x55, 0x45, 0x9d, 0x64, 0x1d, 0x00, 0x15, 0xd2, 0x20, 0x15, 0x9f, + 0xcf, 0xc0, 0x72, 0x20, 0xec, 0xf3, 0x55, 0x86, 0x36, 0x8b, 0xac, 0x8f, 0x71, 0x04, 0xc5, 0x17, 0x3b, 0x98, 0x8d, 0x96, + 0xd9, 0x56, 0x1c, 0x48, 0x5f, 0xd4, 0x32, 0x3d, 0x41, 0x94, 0x54, 0x7b, 0xa8, 0x44, 0xfd, 0x99, 0x9e, 0xbb, 0x22, 0x6d, + 0x36, 0x57, 0x86, 0x19, 0xc5, 0x09, 0x73, 0x5e, 0x4a, 0xb7, 0x99, 0x2c, 0x51, 0x9d, 0xf3, 0x0e, 0x40, 0x82, 0x9a, 0xc3, + 0x5e, 0x00, 0x85, 0xf1, 0xa1, 0xe0, 0xe7, 0xf2, 0xcd, 0x7d, 0x6a, 0x3a, 0x10, 0x42, 0x1d, 0x95, 0xb1, 0xc5, 0x9e, 0x76, + 0x2a, 0x22, 0x00, 0x48, 0x52, 0x07, 0xc7, 0x49, 0xab, 0xa1, 0xd5, 0xa6, 0xe2, 0xc5, 0x51, 0x47, 0x31, 0x80, 0x37, 0xbd, + 0xb6, 0x91, 0xab, 0xa3, 0x9c, 0xee, 0x9c, 0x1e, 0x69, 0xc7, 0x15, 0x29, 0xf5, 0x8f, 0x12, 0x4f, 0xf4, 0x99, 0xaf, 0x58, + 0x68, 0x5b, 0x2e, 0x0d, 0x99, 0x25, 0x13, 0xc1, 0xe4, 0xe7, 0x7f, 0x58, 0x16, 0xaa, 0x02, 0xf1, 0xce, 0xde, 0x90, 0x33, + 0x80, 0x5b, 0xb3, 0xdb, 0xb6, 0x6b, 0xda, 0x77, 0x4b, 0x45, 0xff, 0x73, 0x27, 0x02, 0x79, 0xb3, 0x01, 0xe9, 0x11, 0x64, + 0x0b, 0x93, 0x17, 0xd5, 0x71, 0x23, 0xdb, 0x2d, 0xbd, 0x06, 0xb5, 0x8a, 0x1e, 0xfd, 0x13, 0xe4, 0x0c, 0xfb, 0x5f, 0xd5, + 0x68, 0x04, 0xd7, 0xd2, 0xeb, 0x63, 0xc2, 0x2f, 0x7d, 0xfe, 0x9b, 0x24, 0x92, 0xb7, 0x46, 0xab, 0x0e, 0x7c, 0x15, 0xfa, + 0x0d, 0x1a, 0xdc, 0x65, 0x99, 0xdb, 0xa1, 0x6f, 0x55, 0x90, 0x76, 0xb5, 0x20, 0x8b, 0x6f, 0x31, 0x62, 0x30, 0x3b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x2e, 0x1e, 0x2c, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, + 0x00, 0x74, 0x00, 0x2d, 0x00, 0x53, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6e, 0x00, 0x4f, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x79, + 0x00, 0x20, 0x00, 0x28, 0x00, 0x53, 0x00, 0x2f, 0x00, 0x4d, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x29, 0x30, 0x23, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x60, 0x94, 0x0b, 0x09, 0xd9, + 0x9c, 0x09, 0x22, 0xc2, 0x15, 0x0e, 0xf8, 0x47, 0x4c, 0x8f, 0xbe, 0xaa, 0x65, 0x51, 0x76, 0x30, 0x30, 0x30, 0x21, 0x30, + 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x76, 0xa4, 0x2d, 0xf1, 0x67, 0x61, 0x56, 0x63, + 0xd0, 0x39, 0x34, 0xe3, 0xb4, 0x1c, 0x96, 0xa3, 0xc0, 0x5a, 0xf7, 0xff, 0x04, 0x08, 0x06, 0xe1, 0x19, 0x07, 0xbf, 0xf2, + 0xb9, 0xbf, 0x02, 0x01, 0x01 +}; +unsigned int test_sign_only_smime_p12_len = 2785; + + +/* Test SSL User identity (PKCS12 data), expires in 2026 */ -unsigned char Test_p12[2721] = { - 0x30,0x82,0x0a,0x9d,0x02,0x01,0x03,0x30,0x82,0x0a,0x64,0x06,0x09,0x2a,0x86,0x48, - 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0x55,0x04,0x82,0x0a,0x51,0x30,0x82, - 0x0a,0x4d,0x30,0x82,0x04,0xd7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, - 0x06,0xa0,0x82,0x04,0xc8,0x30,0x82,0x04,0xc4,0x02,0x01,0x00,0x30,0x82,0x04,0xbd, - 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x30,0x1c,0x06,0x0a,0x2a, - 0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x06,0x30,0x0e,0x04,0x08,0xba,0x25,0x0b, - 0x36,0xab,0xc2,0xe7,0x34,0x02,0x02,0x08,0x00,0x80,0x82,0x04,0x90,0xe2,0x74,0x80, - 0xf1,0xf9,0xff,0xb5,0x9a,0xa4,0xe2,0x43,0x70,0x41,0xa1,0x90,0x19,0xb2,0xd5,0x8e, - 0x00,0x4b,0xfc,0x07,0xd6,0x72,0x99,0x9c,0x89,0xa8,0x0c,0x97,0x4a,0x9c,0x10,0x30, - 0x11,0x80,0xc1,0x42,0xda,0x56,0xdd,0x1b,0xfa,0x9e,0x5f,0x85,0x72,0x1d,0xde,0xdf, - 0x78,0x8f,0xd4,0x69,0xf0,0x39,0xfb,0xf1,0xf4,0x96,0xc1,0x2d,0x97,0x20,0x98,0xe2, - 0x38,0xd0,0xe1,0xda,0x01,0x59,0x64,0x71,0xd6,0xd9,0xa2,0x46,0x38,0x87,0x54,0x4c, - 0x4d,0x3f,0x8a,0x9b,0x75,0xf4,0x98,0xec,0xf1,0xe4,0x01,0x60,0x8d,0x04,0x54,0x28, - 0x4c,0xbb,0x90,0x08,0x98,0xb1,0x6b,0x61,0xe3,0x03,0xcd,0x00,0x19,0x87,0xa2,0xc2, - 0xb5,0x7b,0x57,0xd4,0x22,0x77,0xd1,0x68,0x9a,0xfe,0xe3,0x43,0xef,0x2b,0xb6,0x11, - 0x7c,0x63,0x9c,0x28,0xab,0x86,0xdf,0x1b,0x95,0x58,0x54,0xa5,0x3d,0x18,0xb0,0xad, - 0x20,0x76,0x92,0xf5,0xef,0x20,0x8a,0x0c,0x21,0xdb,0x83,0x15,0x1e,0xa5,0x6f,0xeb, - 0xd3,0xc8,0x40,0x14,0x7f,0x69,0x46,0x73,0x20,0x60,0x2b,0x3e,0x27,0xd7,0xb9,0x33, - 0x8c,0xe6,0x43,0xc8,0xf6,0xa5,0x53,0xa7,0x36,0x03,0x3d,0xa9,0xdd,0x85,0x59,0xde, - 0x70,0xc2,0x65,0x38,0x06,0x04,0x00,0x01,0xcc,0xed,0xdf,0x1f,0xab,0x83,0xed,0xeb, - 0xc0,0x3d,0x33,0x4e,0x99,0x22,0xcc,0x63,0xc7,0x14,0x9c,0x50,0x60,0x38,0xc3,0xa5, - 0xe2,0xfe,0x78,0x04,0x01,0x0f,0x1d,0xde,0xe0,0x3e,0x86,0x05,0x02,0xfc,0x3c,0x7f, - 0x38,0xf7,0xb0,0xd0,0xbb,0x0c,0xe1,0x1b,0xdc,0x6e,0xb0,0x12,0x7a,0xae,0x13,0x5d, - 0x80,0xd7,0x0e,0xb2,0xe8,0x5d,0x2a,0xbf,0x2e,0x67,0xc3,0xd8,0x8d,0xa1,0x9f,0x2c, - 0xbb,0xc4,0x33,0xca,0xf4,0x43,0x89,0xbd,0x4e,0x19,0xa5,0x71,0x1c,0x5f,0x6b,0x4d, - 0xd4,0xf7,0xdd,0xd3,0xfd,0x13,0xdc,0xde,0x76,0x2c,0x38,0x8e,0xef,0xb2,0x00,0x9c, - 0xfd,0xa5,0x52,0xa0,0xec,0xa3,0xfe,0xcc,0x80,0xee,0x8d,0xed,0x25,0xf9,0xa8,0x30, - 0x99,0x04,0x6f,0x61,0x4e,0x2f,0x08,0x6c,0xa5,0xe2,0x5b,0x15,0xae,0x58,0xbd,0xbd, - 0xa1,0x36,0xa9,0xa1,0xb5,0xed,0x1e,0x95,0xf5,0x90,0x35,0xa2,0x5c,0xc3,0x9b,0x1f, - 0x98,0x5d,0xdd,0xcf,0xd4,0x08,0xd4,0xb7,0x90,0x58,0xb8,0xc7,0x9d,0x60,0x25,0x57, - 0xa1,0x39,0xc3,0x2c,0x75,0x07,0xd9,0x4c,0xdd,0x2f,0xc8,0xf5,0x7a,0xee,0x06,0xcf, - 0xdc,0xc3,0x22,0x89,0x37,0xa0,0x9f,0x9f,0x45,0x46,0x2d,0x98,0xac,0xdb,0x33,0x80, - 0xb3,0x29,0x76,0x6f,0x1b,0x9e,0x71,0xc7,0x41,0x9f,0x12,0x00,0x4e,0x09,0x0c,0xab, - 0xc7,0xda,0x58,0x60,0x6c,0x0a,0x6e,0x09,0xbe,0x2e,0x2f,0x4f,0x0a,0x63,0x38,0x60, - 0xca,0xc9,0xe9,0x67,0x70,0xcb,0x4e,0xed,0xa9,0xd3,0xd4,0xbc,0xa2,0x69,0x32,0xcb, - 0x62,0x69,0xa0,0x32,0x36,0x09,0x96,0x1f,0xdc,0xea,0x73,0xe6,0x84,0x3d,0x84,0xbf, - 0x62,0x82,0x4d,0x23,0xb1,0xc5,0x64,0xa8,0x57,0x07,0x37,0x3c,0x54,0x63,0x61,0xe1, - 0x24,0xeb,0xd9,0xdd,0x2e,0xb8,0x8f,0xbd,0xa9,0x3e,0x55,0xd7,0xea,0xfb,0x5a,0xc9, - 0x68,0xd9,0x9d,0x0e,0x75,0xb1,0x86,0xf0,0xa4,0xb2,0x3f,0xd7,0x77,0x7d,0x5f,0x5f, - 0x87,0x00,0x07,0x24,0x16,0x20,0x0a,0x5b,0x4b,0x52,0xb6,0x1a,0x39,0xd6,0x32,0x43, - 0x7a,0xb4,0xf8,0x81,0x59,0xec,0xbd,0x97,0xb6,0xe7,0x41,0x2b,0x68,0x19,0xb4,0x06, - 0xec,0xbf,0x34,0x36,0xa2,0x9a,0x7f,0xa0,0xa9,0x16,0x9e,0x98,0x40,0x37,0x22,0x21, - 0x3e,0x43,0xe3,0xaf,0x30,0x6e,0x50,0xf5,0xba,0xe4,0x00,0x14,0x25,0x08,0xbf,0xa8, - 0xdf,0x71,0x4b,0x3d,0x27,0x8b,0x44,0xbb,0xed,0x2c,0xcb,0x75,0x6a,0x1d,0xb8,0x8b, - 0xe9,0xe2,0x99,0x0b,0xe5,0xcd,0x0e,0x24,0xa8,0x68,0x91,0xca,0xc9,0x48,0x5c,0xdb, - 0x60,0xa0,0x43,0x52,0x82,0x74,0x17,0xd7,0x47,0x91,0xd7,0x92,0x04,0xba,0x3f,0xe4, - 0x54,0xc9,0x41,0xb9,0xa4,0xcf,0x2f,0x0f,0x7e,0xce,0xa2,0x82,0xe7,0xed,0x3a,0x48, - 0x83,0xdb,0xdb,0x9f,0x1d,0xa2,0x44,0x56,0xf0,0x76,0x7a,0x20,0x6b,0xd7,0x8e,0xc1, - 0x34,0x67,0x28,0xc3,0x1e,0x8d,0x03,0xf0,0x91,0x87,0x83,0xeb,0x26,0xa3,0x38,0xe0, - 0xc6,0xd9,0x1d,0x3a,0xa6,0xe4,0xf0,0x31,0xe9,0x23,0xce,0x6c,0x0a,0xe4,0xab,0x3c, - 0x3c,0xf2,0x68,0x8a,0x41,0xda,0x19,0x5b,0x40,0x9c,0xde,0xc7,0x84,0x0b,0x2b,0xa7, - 0xfd,0x95,0x37,0xf7,0x42,0x17,0xac,0x90,0x6e,0x11,0x53,0xfb,0x75,0x4b,0x37,0x88, - 0xd2,0x1f,0xaa,0x73,0x98,0x0d,0x74,0xb3,0x69,0x54,0x2b,0x9e,0x5f,0xaf,0x93,0x21, - 0x07,0x05,0x60,0xc6,0x61,0x4e,0x5d,0xaf,0x36,0x79,0xca,0x85,0x4a,0x6c,0x58,0xeb, - 0xcf,0xaf,0x99,0xd9,0xb5,0x82,0x46,0xb4,0x73,0x95,0x1a,0xbc,0x78,0xdd,0xb7,0x47, - 0x10,0xeb,0x03,0x50,0x63,0x06,0x73,0xdc,0xc4,0xa1,0xa8,0xa3,0x44,0xc1,0x4d,0xc9, - 0x2c,0x73,0x75,0x0f,0xb0,0xe0,0xa5,0x43,0xd1,0x8a,0x29,0xa9,0x60,0x71,0x4d,0x82, - 0xae,0x5c,0xa5,0x87,0x93,0x4c,0xa2,0xfd,0xb5,0xb3,0xda,0xf4,0x90,0x61,0x87,0x6e, - 0xe8,0x8d,0xfc,0x52,0x17,0x06,0x87,0x32,0x37,0x6a,0xff,0xe7,0x58,0xa2,0x46,0x25, - 0xd0,0x3a,0xd8,0xf7,0xc4,0x1b,0xda,0x58,0x5d,0xb8,0xa2,0x5d,0x4d,0x8b,0x1a,0x90, - 0x20,0x12,0x00,0xf3,0x7f,0xb0,0x53,0x97,0x6d,0xfb,0xa0,0x5c,0x4a,0x6c,0xb5,0xb5, - 0xc3,0xb0,0x3a,0x32,0x71,0xbc,0x61,0xe5,0x37,0x60,0xea,0x4a,0xf5,0xd8,0x05,0xc2, - 0xd4,0x62,0xb2,0x94,0xb0,0x73,0xd6,0x82,0x08,0x60,0x71,0xee,0x7e,0xd5,0xf7,0x30, - 0x89,0xe8,0xb5,0x1a,0x08,0xb8,0xea,0x11,0x57,0x9d,0x99,0x2d,0xef,0xd0,0x5a,0xb7, - 0x24,0xc8,0x1d,0x87,0x81,0x70,0xbb,0xb9,0x88,0xed,0x04,0x32,0xab,0x55,0x7e,0xea, - 0x1a,0x77,0x80,0x7a,0x88,0x08,0xc7,0xa1,0x53,0x05,0xb1,0x85,0x43,0x5a,0x11,0x4f, - 0x2a,0x7e,0xda,0xfe,0x83,0x12,0x47,0xc4,0xd7,0x6b,0xfb,0x8a,0x0c,0x90,0x77,0x84, - 0xc0,0xb3,0xa6,0x60,0x96,0xd3,0x2f,0x5f,0x3f,0x62,0xe4,0xda,0x13,0xf4,0x35,0x50, - 0x20,0x5b,0x1a,0xd0,0xc7,0x39,0x06,0x08,0x6a,0x0d,0x5e,0xb7,0x8b,0x37,0x56,0x1c, - 0x52,0x7c,0x9b,0x6a,0xd6,0x7e,0x8e,0xb0,0x36,0xb7,0x44,0x36,0x30,0xb9,0x0f,0x39, - 0x51,0x48,0xc3,0xa3,0xa1,0x98,0x57,0x6b,0xba,0xf6,0x62,0xaf,0xf4,0x2b,0x6c,0x50, - 0xa1,0x55,0xf4,0x58,0x37,0xc4,0x4a,0xd2,0xcb,0xb6,0x59,0x19,0x82,0x3d,0x5e,0x3d, - 0x38,0xc3,0x74,0xab,0x0c,0xd0,0xb2,0xc5,0xb0,0x87,0x30,0xa2,0xef,0x0a,0x85,0xb0, - 0xe5,0x6c,0x39,0x13,0x8f,0x54,0xfe,0xf4,0x3c,0x16,0x4b,0xfd,0xfa,0x2a,0xef,0x66, - 0xa8,0x2a,0x8d,0xc0,0x7b,0x53,0x55,0x4b,0xba,0x19,0xa3,0xa3,0x5f,0x16,0xb4,0x06, - 0xb2,0x56,0xa7,0xca,0xfa,0x6a,0x1f,0xf2,0x0f,0xe5,0x58,0x8a,0x6d,0x45,0x43,0xb3, - 0xd5,0xd2,0x35,0x4f,0x52,0x75,0x47,0x74,0x6f,0x7c,0x25,0x98,0xb2,0xa9,0xef,0x37, - 0x8e,0xa9,0x89,0xff,0x18,0xb6,0x56,0x75,0x32,0x8e,0x98,0xed,0x35,0x8b,0xca,0xad, - 0x91,0xaf,0xdd,0xd4,0xdf,0xff,0x23,0x99,0x45,0x30,0xad,0x9d,0xec,0xce,0x94,0x4a, - 0x6d,0xaa,0xd7,0x6b,0x73,0xa3,0x33,0x0d,0x8b,0x1d,0xd0,0xde,0xc6,0x30,0x82,0x05, - 0x6e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x05,0x5f, - 0x04,0x82,0x05,0x5b,0x30,0x82,0x05,0x57,0x30,0x82,0x05,0x53,0x06,0x0b,0x2a,0x86, - 0x48,0x86,0xf7,0x0d,0x01,0x0c,0x0a,0x01,0x02,0xa0,0x82,0x04,0xee,0x30,0x82,0x04, - 0xea,0x30,0x1c,0x06,0x0a,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x0c,0x01,0x03,0x30, - 0x0e,0x04,0x08,0xe9,0x3c,0x06,0x49,0x97,0xcf,0x08,0xfe,0x02,0x02,0x08,0x00,0x04, - 0x82,0x04,0xc8,0x95,0xff,0x56,0xf1,0x44,0xdd,0xe9,0x3d,0x50,0x22,0xbd,0xda,0x8c, - 0x1d,0x0f,0x6f,0xde,0x2d,0x96,0x46,0x21,0x32,0xc9,0xde,0x6d,0x96,0x45,0xfd,0x05, - 0x67,0xde,0x46,0x22,0x87,0xc3,0xbe,0xb9,0xb1,0x30,0x9d,0x8b,0xb0,0x6b,0x35,0xd9, - 0xa0,0x09,0x49,0x43,0x77,0x93,0x3b,0x6f,0xdd,0xc9,0xba,0xdd,0xa4,0xf9,0x81,0xb0, - 0xc8,0x61,0x2e,0xd8,0xe9,0xd0,0xb4,0xa4,0xe8,0x49,0x5a,0x48,0xe7,0x88,0x21,0xdc, - 0x1d,0x84,0x12,0x08,0x08,0x74,0x52,0x36,0x4a,0x30,0x6b,0xb0,0x57,0x91,0x71,0x0c, - 0x56,0x64,0xc8,0x6d,0x4e,0xfa,0xc6,0xdf,0xec,0xc6,0xc6,0x97,0x76,0xe0,0x5d,0x14, - 0xb7,0x67,0xdc,0xec,0xc9,0x83,0xec,0x8e,0xae,0x3d,0x3d,0x85,0xd2,0x26,0xc9,0x8c, - 0x2a,0xb1,0xf1,0xd7,0xc6,0xe3,0x64,0xf8,0x31,0x59,0xf5,0x6d,0x29,0xd3,0xce,0x29, - 0x8c,0xaa,0x0e,0x3d,0x5d,0x8f,0x9e,0x00,0xb6,0xfd,0xfb,0x7a,0x3a,0x2f,0xaa,0x1e, - 0x01,0x0a,0xd6,0xb5,0xdf,0x34,0x60,0x60,0xe0,0x5a,0x94,0x68,0x6d,0x87,0x26,0x3e, - 0x85,0x83,0x1a,0xb9,0x82,0x71,0xc5,0xb1,0x28,0x67,0x9e,0x2c,0xbe,0x07,0x4a,0x8b, - 0xd2,0xa1,0x2e,0x5c,0xb1,0xff,0x26,0xae,0x2e,0xc9,0xc2,0x3a,0x78,0x12,0x50,0x0b, - 0xbd,0x01,0x48,0x41,0x89,0x1f,0xa1,0x74,0xe8,0xe0,0xc7,0x70,0x88,0xac,0xa2,0x04, - 0x21,0x82,0x4b,0x8f,0x2a,0x81,0x13,0x4a,0xbb,0x80,0x59,0x7c,0xef,0xc4,0x26,0xb8, - 0x9d,0x43,0x76,0xef,0x2e,0x53,0xc3,0x10,0xd8,0xd8,0x76,0x2b,0xf0,0x00,0xca,0xf3, - 0xf7,0xa5,0xff,0x2a,0x7d,0x2b,0x9e,0xec,0x2d,0xf4,0x0c,0x1c,0x0e,0xa5,0xef,0x92, - 0xd5,0x26,0x2d,0x22,0xf8,0x67,0xcf,0x9d,0xc3,0x06,0xd7,0xdf,0x9a,0x91,0x94,0xaa, - 0x73,0x70,0x6b,0xf9,0xa6,0x32,0x21,0xb2,0x8a,0x2a,0xe2,0x6c,0x9b,0x6e,0x8d,0xc7, - 0xa5,0x18,0xa3,0xf4,0x8f,0xaf,0x6e,0xe3,0x4c,0x76,0xe9,0xe6,0x81,0x7f,0xa1,0x3b, - 0x53,0x3f,0xb1,0x0f,0x94,0x5b,0x57,0x23,0xfe,0x19,0x51,0xf8,0xc5,0xd6,0x6d,0xa9, - 0x55,0x53,0xb6,0xf8,0x93,0x29,0xe8,0x4b,0xca,0x1f,0x9c,0xe5,0xdb,0x30,0xa2,0x13, - 0x26,0xed,0x90,0xea,0x5e,0xa5,0xc8,0xf6,0x04,0xf3,0xc0,0xd0,0x0d,0x7c,0x33,0x66, - 0x8d,0xfd,0x69,0x70,0x91,0x96,0xe4,0x9f,0x70,0xfa,0x4b,0xbc,0x07,0xbf,0xf7,0x0e, - 0x9f,0xcc,0x3a,0xef,0x5a,0xc8,0x5f,0xd7,0x17,0x5a,0xaa,0x35,0x68,0x09,0xb7,0x5a, - 0xc9,0xab,0x33,0x40,0x17,0xb7,0xd2,0x66,0xe6,0xea,0x74,0xca,0xd5,0x71,0x89,0x8b, - 0x95,0x07,0x2c,0xbd,0x43,0xc9,0x7a,0xa3,0xb5,0x8b,0x11,0x61,0x95,0x4e,0x39,0xeb, - 0x66,0xfb,0x06,0xfb,0xf2,0xd4,0x56,0xb5,0x2b,0xca,0x93,0xde,0x22,0xbe,0xc2,0x62, - 0xbd,0xbc,0x58,0x0d,0x49,0x4d,0x08,0x82,0x8a,0x63,0x74,0x7c,0x64,0x0d,0xf5,0x36, - 0x82,0xc2,0x14,0x6a,0xa1,0x34,0x34,0x94,0x55,0x74,0xc6,0x69,0xe6,0xd4,0x3c,0x6c, - 0x03,0x0f,0xa5,0xa5,0x23,0x58,0xbb,0x97,0x75,0x97,0x70,0x4e,0x6a,0x94,0x57,0xba, - 0x5a,0xbb,0xab,0x3f,0xfe,0x8f,0x1d,0x5a,0x1f,0x7a,0x6d,0x79,0xaa,0x67,0xd8,0xdc, - 0x03,0x88,0x2f,0x2c,0xa7,0x79,0xc0,0xd7,0x85,0x42,0xf9,0xc3,0x23,0x67,0x09,0x22, - 0x3a,0xb8,0x04,0x5c,0xa9,0x75,0x18,0x35,0x16,0x39,0x7a,0xf2,0x01,0xb7,0x5e,0xe6, - 0xa1,0xc8,0x2b,0x29,0x9c,0x38,0xb1,0x8b,0x50,0xd8,0xe9,0x8b,0x6a,0x38,0x5b,0xe0, - 0xfe,0x88,0x21,0xb6,0xc9,0xf6,0x6a,0x66,0x17,0xe7,0x37,0x42,0xe9,0x62,0x63,0x41, - 0xca,0xa1,0xc7,0x0c,0x5c,0xf6,0xdc,0xf5,0xf4,0x5f,0xc1,0x84,0xc5,0x8f,0xe8,0x87, - 0x5e,0xb2,0xf5,0x0a,0x9f,0x8f,0x8d,0x71,0x25,0x3b,0x54,0xb8,0xd2,0x15,0x3f,0x69, - 0x27,0x9b,0xea,0xf7,0x83,0xf5,0xf2,0x24,0xd9,0xd8,0xd6,0x62,0x13,0x43,0xe5,0x64, - 0xb3,0xf2,0x49,0x70,0x02,0xf4,0x76,0x42,0xae,0xed,0x00,0xbf,0x18,0x5b,0xe0,0x1c, - 0x41,0x37,0x0e,0xbd,0x13,0x2d,0xa1,0x31,0x0c,0x8c,0xd6,0xc4,0x27,0xe4,0x2a,0x74, - 0xa3,0x90,0x63,0x56,0x05,0x59,0x6a,0xdc,0x45,0x9e,0x04,0x14,0xd3,0x32,0x77,0xff, - 0xb2,0x50,0x73,0xba,0x2a,0xd3,0x70,0x69,0xbe,0xec,0xf6,0xee,0xed,0xf9,0x88,0x65, - 0x4e,0x61,0x32,0x09,0x73,0xdc,0x16,0x16,0x8a,0xec,0x09,0x44,0xcb,0x2c,0x03,0x44, - 0xaf,0xd7,0xcd,0x0d,0x91,0x52,0xf1,0xba,0xed,0x64,0x7b,0xd9,0xa1,0x1a,0x40,0xdb, - 0xf8,0x46,0x86,0x74,0x30,0x2d,0x72,0x62,0x2a,0x8c,0xd0,0xa2,0x6f,0xcd,0x21,0x02, - 0xc9,0xc4,0xd0,0x81,0x23,0x1c,0x81,0xd9,0x71,0xc1,0xee,0x70,0x37,0x8e,0x23,0x9d, - 0x2c,0xd6,0x4b,0x2b,0x08,0x92,0x95,0xbb,0xf4,0xae,0x78,0x14,0xa6,0x16,0xdc,0xf7, - 0xba,0xc1,0x18,0x96,0x13,0x5a,0xa4,0x12,0xcd,0x96,0x2b,0xb3,0x21,0x0a,0xd6,0x7e, - 0x25,0xd8,0xe9,0x59,0xd5,0x18,0x91,0x85,0xc1,0xe3,0xee,0xf8,0x9b,0x4f,0x42,0x04, - 0x03,0x7d,0xe8,0xcc,0x2a,0xa3,0x8e,0x95,0x9b,0x47,0xb0,0x89,0x7f,0xd5,0x53,0xbd, - 0x54,0x7b,0x73,0xa2,0x0a,0x62,0x51,0x34,0x3b,0xc5,0x41,0x5d,0xa5,0x5c,0x94,0x69, - 0xd5,0xfd,0x5e,0x71,0xc1,0x6e,0x18,0x80,0x1f,0xab,0x94,0xcd,0x0d,0x44,0x47,0xd4, - 0xa9,0xf3,0x3a,0xfd,0xf8,0x47,0xe4,0x9c,0xd7,0x5d,0x54,0x6f,0x4b,0xea,0xf1,0x8f, - 0x9f,0xca,0x3c,0x24,0xe6,0x8b,0xa5,0x29,0x5b,0x07,0x05,0x60,0x41,0xce,0x77,0x2b, - 0xfe,0xe0,0x4e,0x47,0x92,0x2d,0xca,0x5b,0x6e,0x08,0xcc,0x25,0x8e,0xc8,0x93,0x96, - 0x49,0x6d,0x3f,0x25,0xbf,0x8e,0x37,0xe3,0xdf,0xb9,0xea,0xf0,0x2b,0x56,0xc8,0x30, - 0x7d,0xff,0x32,0xfa,0x9c,0xf1,0x35,0x6b,0x68,0xf2,0xfd,0x1e,0x23,0xf2,0x95,0x81, - 0x68,0xd8,0xec,0x95,0x5b,0x85,0xa8,0x42,0xa6,0xcc,0xf5,0x03,0x95,0xf1,0x3f,0xd2, - 0x86,0x3a,0x1f,0x11,0xd2,0xcf,0x4b,0x32,0xf2,0xb9,0x46,0x3e,0xf5,0xbb,0x0d,0xa0, - 0x5b,0x85,0xea,0xe0,0xbd,0x7c,0x3b,0x75,0x80,0x1c,0x8a,0x6d,0x92,0x39,0x27,0xbf, - 0xc5,0x8e,0xb4,0x5a,0xaf,0xd5,0x8b,0x34,0x53,0x85,0x76,0x60,0xe6,0xd4,0xb8,0xe2, - 0x2f,0x9e,0x66,0x24,0x28,0x66,0x06,0x25,0x62,0x77,0x35,0xce,0x36,0x68,0x2a,0xdc, - 0x82,0x94,0xd8,0x21,0x96,0x7b,0x05,0x10,0x3b,0xcc,0xfb,0x43,0x11,0xd0,0x25,0xfc, - 0x1c,0x5a,0x1c,0xee,0x3d,0x1c,0x75,0xf8,0x41,0xa7,0x10,0x48,0xd7,0xee,0x9e,0xa4, - 0x62,0xb0,0x64,0xaa,0x55,0xd9,0xd7,0xb6,0x4b,0xe9,0x84,0xa8,0x64,0xcc,0xb3,0x3a, - 0xe7,0x83,0xf0,0x8a,0xd3,0xe3,0x86,0xda,0xb5,0xc7,0x8e,0x9c,0x84,0xde,0x06,0x5d, - 0x8f,0x4d,0x68,0x35,0x69,0x88,0xc2,0xd1,0xea,0xab,0x1b,0xa7,0xf0,0x8e,0x05,0x3d, - 0xdb,0x8b,0x27,0x20,0xd2,0xb1,0x20,0xab,0x9a,0xda,0x4d,0x03,0xbd,0xa4,0x17,0xf6, - 0x01,0xb5,0x25,0x62,0x02,0xe5,0x17,0xdd,0x71,0x8a,0xe8,0x2b,0x01,0x56,0x35,0x31, - 0x79,0x6f,0x7f,0x98,0x3f,0x5c,0x3d,0x0d,0x11,0x43,0x44,0x31,0xe0,0x94,0xa0,0x6a, - 0xaa,0x8e,0x24,0x0d,0x8f,0xe2,0x81,0x75,0x0d,0x9f,0x54,0xf8,0x0e,0x23,0x19,0xb9, - 0xa9,0x6e,0x11,0xfc,0x08,0xb4,0x73,0x77,0xda,0x3b,0x00,0x63,0xc4,0xb8,0x79,0xb4, - 0xf9,0xb2,0x41,0x55,0xd5,0xb6,0xd3,0x91,0x4d,0x77,0xeb,0xc9,0xb9,0x42,0xba,0xef, - 0x05,0xae,0x2f,0xc3,0x1a,0x7d,0x9b,0x01,0xef,0xee,0x8f,0x0b,0x2c,0x68,0xab,0xc6, - 0x43,0xb3,0x87,0x1f,0xca,0xba,0xe7,0x30,0xe9,0x7a,0xda,0x55,0xec,0x77,0xd1,0xb6, - 0x44,0xcb,0x91,0x43,0xa9,0x2b,0xc1,0x26,0xed,0x14,0x85,0x31,0x52,0x30,0x2b,0x06, - 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x14,0x31,0x1e,0x1e,0x1c,0x00,0x54, - 0x00,0x65,0x00,0x73,0x00,0x74,0x00,0x20,0x00,0x53,0x00,0x53,0x00,0x4c,0x00,0x20, - 0x00,0x55,0x00,0x73,0x00,0x65,0x00,0x72,0x00,0x00,0x30,0x23,0x06,0x09,0x2a,0x86, - 0x48,0x86,0xf7,0x0d,0x01,0x09,0x15,0x31,0x16,0x04,0x14,0xf1,0x1b,0x6e,0xf2,0x3a, - 0xc4,0x3a,0xe1,0xd6,0x4b,0x7d,0x31,0xf3,0x2c,0xd4,0x63,0x06,0x66,0x37,0xe0,0x30, - 0x30,0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14, - 0x85,0xed,0x34,0x3d,0xde,0xa1,0x8a,0x94,0xcd,0x12,0x95,0xf7,0x2d,0xb2,0x60,0xfd, - 0xbd,0x67,0xe9,0x2d,0x04,0x08,0x71,0xfc,0x54,0xf2,0x12,0x3c,0x22,0xf1,0x02,0x01, - 0x01 +unsigned char Test_ssl_user_p12[] = { + 0x30, 0x82, 0x0a, 0x83, 0x02, 0x01, 0x03, 0x30, 0x82, 0x0a, 0x4a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x82, 0x0a, 0x3b, 0x04, 0x82, 0x0a, 0x37, 0x30, 0x82, 0x0a, 0x33, 0x30, 0x82, 0x04, 0xbf, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x04, 0xb0, 0x30, 0x82, 0x04, 0xac, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x04, 0xa5, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0xe2, 0xcf, 0xcc, 0x9d, 0x17, 0xcd, 0x62, + 0xa4, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x04, 0x78, 0xe0, 0x0c, 0xd8, 0xf5, 0x7c, 0xf7, 0x2f, 0x1e, 0xbf, 0x95, 0x6b, + 0xc1, 0x43, 0x35, 0x3e, 0x8d, 0xdf, 0x65, 0x9b, 0xd8, 0xa0, 0xb2, 0x86, 0xec, 0x38, 0x39, 0x04, 0x72, 0x39, 0x3b, 0xf1, + 0x5c, 0x1d, 0x1c, 0xac, 0xe6, 0x67, 0xea, 0xce, 0xb2, 0x15, 0xe5, 0xd4, 0xee, 0xe8, 0xf1, 0xad, 0x45, 0x75, 0x6a, 0x07, + 0xbd, 0xe5, 0x2b, 0x55, 0x89, 0x24, 0xed, 0x65, 0xc7, 0x8e, 0x50, 0xf8, 0x38, 0xef, 0x9c, 0x79, 0x1b, 0xb7, 0xb5, 0x34, + 0x32, 0x36, 0xa9, 0x1a, 0x65, 0x0f, 0xc4, 0x22, 0x9c, 0x9f, 0xd8, 0x70, 0xe9, 0x8e, 0x59, 0x88, 0x95, 0x86, 0xb0, 0x2c, + 0xb2, 0xc5, 0x4d, 0x5a, 0x3d, 0x6a, 0xbf, 0x1a, 0x3a, 0x60, 0xbe, 0xde, 0x33, 0xb4, 0x21, 0x86, 0x8b, 0x02, 0x38, 0xf4, + 0x77, 0x7e, 0x40, 0x9f, 0x0c, 0x55, 0xed, 0x76, 0xfd, 0x60, 0x70, 0x94, 0x3e, 0xf9, 0x01, 0x42, 0xa7, 0x84, 0x0f, 0xfd, + 0xc0, 0x93, 0x4e, 0xe2, 0x78, 0x13, 0x5d, 0x56, 0x1a, 0x76, 0xf0, 0x99, 0x34, 0x92, 0x0c, 0x3f, 0x19, 0x81, 0x5c, 0x0a, + 0x6b, 0xcc, 0x19, 0x65, 0x06, 0x88, 0xc9, 0x9c, 0x76, 0xaa, 0xa2, 0x0c, 0x5c, 0x4a, 0x38, 0xcf, 0x6d, 0x79, 0xf6, 0xde, + 0x39, 0x7a, 0xc9, 0xe6, 0x6c, 0x42, 0xfe, 0xaa, 0xc4, 0xc0, 0x62, 0xa3, 0xda, 0xe1, 0x08, 0x86, 0x79, 0x2d, 0x80, 0x6a, + 0x5f, 0xa9, 0x79, 0x43, 0xfe, 0xfc, 0xed, 0x08, 0xb3, 0x80, 0x91, 0xa6, 0xe7, 0x9a, 0xc8, 0x77, 0xc7, 0x4c, 0x7e, 0x6a, + 0x79, 0x76, 0x9f, 0x28, 0x0f, 0x24, 0xd2, 0xee, 0x5e, 0x4f, 0x76, 0xe8, 0xa9, 0xd3, 0x1a, 0xf1, 0xe4, 0x0d, 0xb8, 0x26, + 0x95, 0x63, 0xd3, 0x59, 0xfb, 0x03, 0x08, 0xea, 0x59, 0x4e, 0xe2, 0x6d, 0x74, 0x47, 0xa2, 0x8b, 0x1c, 0x21, 0x9f, 0x1c, + 0x68, 0x54, 0x76, 0x78, 0x8a, 0xfa, 0xa3, 0x65, 0x87, 0xd4, 0x6c, 0x16, 0x38, 0xaa, 0xc9, 0x11, 0x58, 0x25, 0x05, 0xba, + 0x68, 0x92, 0xd8, 0x06, 0x85, 0x19, 0x1e, 0xcc, 0xdb, 0x07, 0x27, 0xa8, 0xe9, 0xec, 0xfb, 0xb9, 0xbd, 0x5e, 0x67, 0x22, + 0xae, 0xcd, 0xbd, 0xe6, 0xdc, 0x8d, 0x5a, 0xf2, 0x3c, 0xf4, 0x06, 0xa6, 0x0e, 0x98, 0xfc, 0xec, 0x64, 0x05, 0xb8, 0xa5, + 0xfe, 0x5b, 0x27, 0x41, 0x90, 0xe4, 0x2c, 0x93, 0x38, 0xec, 0xc6, 0xa2, 0x08, 0xe4, 0xab, 0xb2, 0xb5, 0x7b, 0xa6, 0xe0, + 0x89, 0x97, 0xb6, 0xc0, 0xd4, 0xa8, 0x1f, 0xcb, 0xf4, 0xc6, 0x59, 0xcd, 0xaa, 0x99, 0x40, 0xc6, 0x41, 0x18, 0x3a, 0x95, + 0x3a, 0x71, 0x06, 0x5c, 0x0d, 0x4c, 0xdf, 0xc2, 0x37, 0x37, 0x78, 0x33, 0x5d, 0x35, 0x7c, 0x0e, 0x33, 0x7c, 0xfd, 0x97, + 0x18, 0x07, 0xad, 0x54, 0xf0, 0x83, 0xed, 0x20, 0x6c, 0x8a, 0x28, 0x48, 0x29, 0x5c, 0x2c, 0x61, 0x25, 0x87, 0x0b, 0xfc, + 0x96, 0x8a, 0x51, 0x74, 0x8d, 0x21, 0x0b, 0x6d, 0x6a, 0x88, 0x6c, 0xa5, 0xc0, 0xd7, 0x9a, 0xe7, 0x16, 0x49, 0x66, 0xbf, + 0xb3, 0x96, 0x73, 0x4d, 0x61, 0x9e, 0x7f, 0x3b, 0x6d, 0x37, 0x5d, 0x31, 0x3f, 0x00, 0x5c, 0x92, 0x20, 0x6e, 0xab, 0x25, + 0xb3, 0xe9, 0x7a, 0xba, 0xeb, 0xaa, 0x9e, 0xb4, 0xdb, 0xf5, 0x85, 0x51, 0x71, 0xed, 0x5e, 0x4d, 0x04, 0xdc, 0x4d, 0x5d, + 0x0d, 0x24, 0x74, 0xa4, 0xaf, 0x30, 0x3f, 0x82, 0x0c, 0xe3, 0xfa, 0x21, 0x82, 0x25, 0x29, 0xda, 0x0f, 0x4b, 0x2e, 0x1c, + 0xb2, 0x06, 0xe7, 0x36, 0x56, 0xb7, 0x4c, 0xf6, 0x37, 0x2c, 0x80, 0xa3, 0x21, 0xdc, 0x3b, 0xa5, 0xed, 0x24, 0x0e, 0x69, + 0x15, 0xc2, 0x96, 0x0b, 0xa2, 0x72, 0x7a, 0xa4, 0xf8, 0xab, 0x6b, 0xa4, 0xa5, 0x7e, 0x6e, 0x3a, 0xf3, 0x4d, 0x92, 0xba, + 0x90, 0xf0, 0x9d, 0x20, 0x9f, 0xf4, 0x5c, 0xf6, 0x44, 0x74, 0x6a, 0xc3, 0xc4, 0xed, 0x6d, 0x95, 0x81, 0x53, 0x60, 0xb4, + 0x80, 0xf4, 0xd3, 0x5f, 0xad, 0xb6, 0x57, 0x9c, 0xb7, 0x59, 0xcc, 0x51, 0x54, 0x5f, 0x67, 0x32, 0x69, 0x63, 0x80, 0x77, + 0x03, 0x23, 0x07, 0x4f, 0xff, 0x27, 0xd4, 0x52, 0xce, 0xac, 0xba, 0xd5, 0x8d, 0xab, 0xf8, 0xc9, 0x48, 0x01, 0xf7, 0xea, + 0xf7, 0x76, 0x2e, 0xbc, 0xdd, 0x7b, 0x7f, 0x60, 0x12, 0x72, 0x4f, 0x04, 0x0e, 0x93, 0x5e, 0x7e, 0x15, 0x09, 0x2b, 0xa1, + 0x2c, 0xa5, 0x9d, 0x36, 0xd4, 0xbf, 0x5c, 0xb1, 0x19, 0xd4, 0x0e, 0x00, 0x0e, 0x05, 0x7a, 0x84, 0xb0, 0xba, 0xe9, 0x8e, + 0x15, 0x0a, 0xad, 0x4d, 0x8d, 0x1e, 0xff, 0x10, 0x01, 0x43, 0xbf, 0xa9, 0xbf, 0x3b, 0xdf, 0x86, 0x6b, 0xef, 0x86, 0x63, + 0xfa, 0x9e, 0x28, 0xda, 0xb7, 0x03, 0x2b, 0x0b, 0xce, 0x12, 0x5f, 0xd8, 0x42, 0xfc, 0x4f, 0x63, 0x93, 0xbe, 0xef, 0x11, + 0x73, 0xd4, 0xc0, 0xbc, 0x23, 0xc2, 0x99, 0xbc, 0x29, 0xe1, 0xd7, 0x4d, 0xc2, 0xe8, 0x3e, 0xb0, 0xaa, 0x96, 0xed, 0xf8, + 0x48, 0x20, 0x3d, 0xa6, 0xed, 0xc6, 0xa2, 0x8f, 0x89, 0x45, 0x70, 0xbf, 0xf7, 0xee, 0x6f, 0x2a, 0xd1, 0x93, 0xce, 0xad, + 0x55, 0xfe, 0xe9, 0xa8, 0xfc, 0x94, 0x24, 0x91, 0x98, 0x0a, 0xac, 0x90, 0xa6, 0xa7, 0x27, 0x05, 0x55, 0xb3, 0x3e, 0xa7, + 0x08, 0xb0, 0x4b, 0x31, 0xb5, 0xe8, 0x9f, 0x67, 0x74, 0x73, 0x3c, 0x42, 0x84, 0x67, 0x84, 0x97, 0x95, 0x33, 0x00, 0xfe, + 0x69, 0x61, 0x52, 0x05, 0x4c, 0x8b, 0x65, 0x8e, 0x00, 0xf8, 0xd8, 0xe3, 0x40, 0x66, 0x04, 0x06, 0x09, 0x05, 0x93, 0x49, + 0x18, 0xa5, 0x41, 0x6f, 0xc3, 0x28, 0xaf, 0x30, 0xaf, 0x43, 0xaa, 0x74, 0x73, 0x9f, 0xdc, 0x58, 0x83, 0xe9, 0x42, 0xa8, + 0x16, 0xdd, 0xce, 0xf9, 0xbe, 0xe9, 0x33, 0xf8, 0xbf, 0x51, 0x08, 0x25, 0xdf, 0x7a, 0xbe, 0x00, 0x8a, 0xd6, 0x82, 0xf3, + 0xdb, 0xd0, 0x21, 0x48, 0x5c, 0xd5, 0xea, 0x86, 0xd7, 0xff, 0xe0, 0x2f, 0x93, 0xfc, 0x3e, 0xc8, 0xdd, 0xb8, 0x3e, 0x79, + 0xd4, 0x22, 0xa3, 0xaa, 0xeb, 0x47, 0xec, 0xaf, 0xd8, 0xf1, 0xa8, 0x71, 0x7e, 0xae, 0x85, 0xff, 0xe1, 0x98, 0x7f, 0x59, + 0x88, 0x1d, 0xaa, 0x11, 0x89, 0xbe, 0x6e, 0x4e, 0xdc, 0x77, 0xf4, 0xe1, 0x14, 0xcc, 0x1c, 0xd4, 0x8a, 0xc3, 0x0c, 0xff, + 0xb9, 0x12, 0xc1, 0xf3, 0xb6, 0xcc, 0xa2, 0x01, 0x49, 0xad, 0x59, 0x47, 0x17, 0x4a, 0x1a, 0x90, 0xd0, 0x77, 0x77, 0x3e, + 0xad, 0xdd, 0x58, 0x08, 0x40, 0x92, 0xb6, 0xcf, 0x84, 0x64, 0x72, 0x84, 0x8d, 0x98, 0x9f, 0x64, 0x28, 0x45, 0x1a, 0xb0, + 0x88, 0x08, 0xaa, 0x7b, 0x11, 0x15, 0x08, 0xc3, 0x56, 0xa5, 0x0d, 0x7e, 0x04, 0x37, 0xe0, 0x62, 0xbb, 0x34, 0xe9, 0x84, + 0xb2, 0xd0, 0x1a, 0xec, 0xa9, 0x74, 0x9b, 0xf1, 0x0e, 0x30, 0x84, 0xb0, 0x62, 0x17, 0x92, 0x31, 0x0c, 0x11, 0x9e, 0xa0, + 0xa7, 0x48, 0x9a, 0xd7, 0xa4, 0x29, 0x05, 0xea, 0xf4, 0x11, 0x21, 0xdd, 0x8e, 0x9b, 0x79, 0x4a, 0x9b, 0x5c, 0xeb, 0x8b, + 0x55, 0x0b, 0x0d, 0x0d, 0x7e, 0xe0, 0x79, 0x2f, 0x03, 0x52, 0xec, 0x4c, 0x63, 0xa0, 0xa8, 0xc2, 0x66, 0x63, 0xda, 0x18, + 0xad, 0x93, 0xde, 0xb3, 0xb1, 0xe8, 0x08, 0xf8, 0x98, 0x5d, 0x19, 0x40, 0xae, 0xcd, 0x3e, 0xcd, 0x82, 0x09, 0x0c, 0x05, + 0x5b, 0x84, 0x77, 0xd4, 0xf8, 0x1b, 0x53, 0xa6, 0xf0, 0x93, 0x85, 0x9c, 0x79, 0x43, 0x71, 0x4c, 0x8f, 0x66, 0x05, 0x7f, + 0xc4, 0x20, 0x95, 0xfe, 0x1b, 0xd6, 0xf4, 0x2d, 0x4d, 0x42, 0xc6, 0x7f, 0x69, 0x69, 0x1e, 0xad, 0xf5, 0x26, 0xdf, 0x85, + 0x26, 0xed, 0xf3, 0xe1, 0x5c, 0x1a, 0x86, 0x03, 0xbe, 0xd8, 0x96, 0x77, 0x52, 0xd5, 0x4a, 0xb4, 0xf5, 0xfc, 0x0a, 0xb0, + 0xee, 0xb5, 0x21, 0x8c, 0xa4, 0x56, 0xf9, 0xf9, 0x05, 0x27, 0x49, 0x2d, 0x5d, 0x11, 0xac, 0xa5, 0x33, 0xe6, 0x55, 0x73, + 0x54, 0xb9, 0xd1, 0x2a, 0xf8, 0x9a, 0x1d, 0xd3, 0x30, 0x90, 0x41, 0x3f, 0x0c, 0xf1, 0x0c, 0xa9, 0xae, 0xd0, 0x4d, 0xec, + 0x66, 0x66, 0xc8, 0xb5, 0x57, 0xbc, 0xf4, 0xc0, 0xeb, 0x23, 0xb9, 0xc8, 0x8b, 0x43, 0x70, 0x96, 0x2e, 0x20, 0x14, 0x3a, + 0x70, 0x3a, 0xf7, 0x83, 0xa9, 0x7b, 0x80, 0x6d, 0xc4, 0x76, 0xa5, 0x83, 0xf0, 0x55, 0xa0, 0x78, 0xc4, 0x7f, 0xc4, 0xae, + 0xf0, 0xa9, 0x65, 0x5c, 0xd5, 0xda, 0xe1, 0xe1, 0x90, 0xb8, 0xa6, 0x07, 0x2e, 0x30, 0x82, 0x05, 0x6c, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x5d, 0x04, 0x82, 0x05, 0x59, 0x30, 0x82, 0x05, 0x55, + 0x30, 0x82, 0x05, 0x51, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, + 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, + 0x0e, 0x04, 0x08, 0x33, 0x8e, 0xe4, 0x7e, 0x74, 0x9d, 0xf7, 0xfa, 0x02, 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0x10, + 0x10, 0x9b, 0xe5, 0xa8, 0xe1, 0x82, 0x43, 0x54, 0xc5, 0xda, 0xfb, 0x4b, 0x57, 0x45, 0xd3, 0x38, 0xfe, 0x8f, 0x95, 0xf7, + 0x86, 0x7f, 0x50, 0x15, 0x3a, 0x1a, 0xee, 0xcf, 0x8a, 0xa4, 0x67, 0x2a, 0x62, 0x1e, 0x2d, 0x05, 0xab, 0x21, 0x93, 0xdc, + 0x37, 0xe3, 0xdb, 0x5c, 0xb9, 0x86, 0x7c, 0x78, 0xab, 0x62, 0x1a, 0xea, 0x7d, 0x51, 0x01, 0x72, 0x3f, 0xcd, 0x40, 0x0b, + 0x97, 0xae, 0x89, 0xe3, 0x97, 0x81, 0x0e, 0x1f, 0x27, 0x36, 0x46, 0x7b, 0x17, 0xd3, 0xe3, 0x93, 0x8c, 0xde, 0xc3, 0xf1, + 0x05, 0x0f, 0x0c, 0x40, 0x45, 0x53, 0xe9, 0xf5, 0xa9, 0x42, 0xc9, 0x22, 0x8e, 0xa5, 0xd0, 0x3b, 0xbe, 0xf0, 0x1e, 0x39, + 0x11, 0xc5, 0xf7, 0x19, 0x27, 0x65, 0x56, 0xb4, 0x4d, 0xe8, 0xee, 0xd3, 0x81, 0x21, 0xb4, 0x43, 0x9d, 0x82, 0x24, 0x03, + 0x81, 0x06, 0xc5, 0xe2, 0x9c, 0x4e, 0x10, 0x4c, 0x5d, 0xda, 0x1a, 0xc0, 0x8b, 0x54, 0x42, 0x3f, 0x6a, 0x9c, 0x9e, 0xad, + 0xfd, 0xce, 0x62, 0x30, 0xb9, 0xaf, 0x99, 0xc8, 0xea, 0xd7, 0x3c, 0x8d, 0x81, 0x9a, 0xa4, 0x13, 0x11, 0x56, 0x6a, 0x99, + 0x18, 0x40, 0x95, 0x65, 0x61, 0x54, 0x94, 0x91, 0x69, 0x37, 0x99, 0xa5, 0xd1, 0xce, 0x76, 0x3d, 0x63, 0x52, 0xb9, 0x8a, + 0x4e, 0xcb, 0x21, 0x8f, 0x6b, 0xe3, 0xe1, 0x2a, 0x6d, 0xdc, 0x58, 0xf7, 0x1b, 0x9b, 0x9b, 0xa1, 0x6a, 0xe4, 0x60, 0xc6, + 0x6b, 0x55, 0x35, 0x8c, 0x90, 0xfe, 0x12, 0xe2, 0x4a, 0xd3, 0x5d, 0x55, 0xd1, 0x19, 0x47, 0xcd, 0x3a, 0x74, 0xfb, 0xc8, + 0xfe, 0xb1, 0x82, 0xe9, 0x50, 0xb9, 0x80, 0x77, 0x4a, 0x18, 0xc5, 0xe0, 0x3d, 0x45, 0xe8, 0xf7, 0xd3, 0x96, 0x0f, 0x88, + 0x09, 0xf0, 0x49, 0xe7, 0xcf, 0x44, 0xfd, 0xe8, 0x33, 0x22, 0x98, 0x7f, 0x06, 0x1b, 0xf7, 0x54, 0xf6, 0xd1, 0xd1, 0x05, + 0xa8, 0x17, 0x94, 0x41, 0xbf, 0x2b, 0x80, 0xca, 0x41, 0xc5, 0xdc, 0xeb, 0xee, 0x1b, 0xad, 0xbe, 0xae, 0xcf, 0x67, 0x9b, + 0xfb, 0x88, 0x3d, 0xc0, 0x70, 0xb2, 0xbe, 0x16, 0x7c, 0x35, 0xa9, 0xc5, 0xdc, 0xa0, 0x2d, 0x0a, 0x59, 0x9a, 0x59, 0x51, + 0x76, 0x35, 0x85, 0x8f, 0xc7, 0xf7, 0x56, 0x0c, 0xdc, 0xc6, 0xe4, 0x6a, 0xe8, 0x26, 0x6f, 0xd4, 0x4e, 0x0a, 0xa5, 0x99, + 0x3b, 0xcc, 0x0a, 0xa3, 0x44, 0x24, 0x31, 0x28, 0x4f, 0x84, 0xeb, 0x5b, 0x00, 0xf4, 0xa2, 0xf0, 0xdd, 0xfe, 0xe0, 0x57, + 0x5a, 0x9a, 0xc0, 0x64, 0x9f, 0x9c, 0x5e, 0xf8, 0x42, 0x74, 0x54, 0xe8, 0xc4, 0x3b, 0x70, 0xe3, 0xd3, 0x08, 0x9e, 0x13, + 0xbd, 0xeb, 0x5f, 0x01, 0xe6, 0x08, 0xb8, 0x6a, 0xae, 0xe8, 0xe3, 0x9a, 0x89, 0x29, 0xb8, 0x2d, 0xb3, 0x29, 0x19, 0xee, + 0x6e, 0x3d, 0x66, 0xa1, 0x04, 0xbb, 0x17, 0xe1, 0x5b, 0xb7, 0xaa, 0x87, 0x76, 0xe5, 0x88, 0x6c, 0x24, 0x26, 0xdf, 0x69, + 0x6b, 0x40, 0xd6, 0x42, 0x13, 0xc4, 0x0a, 0x09, 0xfb, 0x92, 0x41, 0x34, 0x85, 0x6a, 0xd9, 0xb2, 0xa6, 0x3b, 0xb2, 0xbd, + 0xae, 0x50, 0x9a, 0x1a, 0xc4, 0xe1, 0xd7, 0x86, 0x3c, 0xb9, 0xf5, 0x5f, 0x99, 0x2a, 0x2a, 0xfb, 0x64, 0x2e, 0x33, 0xb2, + 0x2b, 0xb5, 0x0b, 0x87, 0x19, 0x7f, 0xc1, 0xfa, 0xa3, 0x0f, 0x8c, 0xff, 0xda, 0x64, 0x48, 0xa7, 0xe8, 0x85, 0x10, 0x2a, + 0x61, 0x1d, 0x59, 0xf8, 0x1b, 0x46, 0x8a, 0x7a, 0xa2, 0x44, 0x90, 0xd9, 0x1d, 0xe6, 0xe7, 0x69, 0x53, 0x1c, 0xd6, 0x02, + 0x27, 0x2c, 0x86, 0xed, 0xbc, 0xe8, 0xf8, 0xb9, 0xbd, 0x8c, 0xd4, 0x12, 0xf0, 0xb9, 0x66, 0x61, 0xf8, 0xda, 0x7c, 0x7c, + 0xb6, 0x72, 0xa4, 0xd6, 0xd8, 0x84, 0x0b, 0x06, 0x85, 0x25, 0x5e, 0xf8, 0x4d, 0xad, 0xcc, 0x60, 0x00, 0x61, 0xf0, 0xf0, + 0x38, 0x65, 0xe5, 0x4e, 0xfc, 0xd3, 0x8b, 0x3e, 0xae, 0xf1, 0x29, 0x2e, 0x9f, 0xb1, 0x59, 0x0c, 0x65, 0x03, 0x2e, 0x1f, + 0x95, 0xd8, 0x07, 0x19, 0x3d, 0x85, 0x27, 0xfa, 0xc5, 0x35, 0xec, 0x69, 0xda, 0x2f, 0x9e, 0x40, 0xa7, 0x5c, 0x0b, 0xed, + 0xac, 0xc4, 0x99, 0xa3, 0x63, 0xef, 0x73, 0x24, 0x9c, 0x43, 0x1c, 0x45, 0x36, 0xb9, 0x33, 0xf4, 0x2e, 0xbd, 0x7e, 0xb6, + 0xf0, 0xd1, 0xf6, 0x86, 0xf4, 0x2c, 0x1d, 0xc2, 0xc6, 0x62, 0xcf, 0x6d, 0x70, 0x89, 0x9f, 0x36, 0x26, 0xbe, 0xa3, 0x4b, + 0x23, 0x00, 0xbc, 0x62, 0x85, 0x35, 0xa4, 0x25, 0x23, 0xae, 0x60, 0x82, 0x02, 0x25, 0xfd, 0x5b, 0x6a, 0xa1, 0x6b, 0x1b, + 0xcf, 0x42, 0x40, 0xca, 0xee, 0x95, 0x08, 0xd4, 0x5b, 0xa7, 0xc8, 0x29, 0x0b, 0xea, 0xe3, 0x19, 0xb4, 0x85, 0xb7, 0x0d, + 0xcf, 0x3a, 0x0f, 0x51, 0x15, 0x84, 0x4a, 0x1d, 0xad, 0x7f, 0xd0, 0x41, 0x93, 0x10, 0x31, 0xb1, 0x54, 0xfb, 0x19, 0xad, + 0x96, 0x09, 0xb8, 0x65, 0x3f, 0xe2, 0x57, 0x40, 0xb5, 0x0c, 0xc9, 0x89, 0x52, 0x56, 0x10, 0xda, 0xe0, 0x10, 0x18, 0x91, + 0xbb, 0xe2, 0xe3, 0x2c, 0x8e, 0xd7, 0x43, 0x7a, 0xdc, 0xbb, 0x76, 0x67, 0x25, 0x9c, 0x81, 0xec, 0x59, 0x7c, 0xdc, 0xea, + 0x02, 0x29, 0x80, 0xdf, 0x20, 0xaf, 0xba, 0x26, 0xe1, 0x49, 0xcf, 0x7e, 0x69, 0x36, 0x77, 0xad, 0x0b, 0xcc, 0x7d, 0x10, + 0x3f, 0x31, 0x60, 0x0e, 0x17, 0x36, 0x8c, 0xbd, 0x4d, 0x80, 0xe8, 0xe7, 0x7a, 0x7a, 0x1e, 0x17, 0x77, 0x79, 0x9a, 0x1f, + 0xd7, 0x2f, 0x76, 0xf2, 0x4a, 0x52, 0xd9, 0x9f, 0x02, 0x2c, 0xc7, 0xd5, 0x0f, 0x05, 0x8b, 0x59, 0xd9, 0x13, 0xdc, 0x57, + 0xbb, 0x56, 0xd0, 0xc4, 0x13, 0xac, 0x34, 0x05, 0x19, 0x92, 0xb6, 0x18, 0x12, 0x26, 0xe1, 0xe6, 0xe9, 0x8d, 0x6a, 0xad, + 0x83, 0x95, 0xcf, 0x7f, 0x91, 0xad, 0xe3, 0x9f, 0x15, 0x05, 0x95, 0x96, 0x8d, 0x80, 0xc3, 0x13, 0x09, 0xac, 0xa4, 0xd9, + 0xfe, 0xb1, 0xb3, 0x9d, 0x94, 0x49, 0xb9, 0x2d, 0x84, 0x64, 0x4d, 0x75, 0xb8, 0x58, 0x75, 0xec, 0x30, 0x0a, 0xf7, 0x96, + 0xf3, 0xc8, 0x19, 0xa8, 0xbd, 0x62, 0x14, 0x00, 0xb4, 0x26, 0x35, 0x3f, 0x78, 0x43, 0xb1, 0xab, 0x8f, 0xab, 0xa1, 0xf3, + 0x43, 0x87, 0xb3, 0x88, 0x1f, 0xc1, 0x89, 0x6c, 0xcf, 0x1f, 0x38, 0x1c, 0xe0, 0x68, 0xcc, 0x93, 0x46, 0x8c, 0xde, 0x4c, + 0x2c, 0x27, 0x6d, 0xb6, 0x91, 0xa8, 0xc5, 0xee, 0xf7, 0x47, 0x17, 0x5a, 0x11, 0xb2, 0x3a, 0xbc, 0x35, 0xee, 0x05, 0xc3, + 0x17, 0x63, 0x69, 0x77, 0xbd, 0x43, 0x80, 0x71, 0xe9, 0xd6, 0x8c, 0xdd, 0xef, 0x0a, 0xf8, 0x59, 0x1d, 0x61, 0xd6, 0x19, + 0x64, 0x71, 0xe7, 0x3c, 0x36, 0xd8, 0x07, 0x5d, 0x6c, 0x0f, 0x28, 0x99, 0xa6, 0x9e, 0x01, 0x1b, 0x4c, 0x9a, 0x5f, 0xde, + 0x96, 0xb0, 0x61, 0x0a, 0x9c, 0xeb, 0x2a, 0x29, 0x09, 0x1b, 0xaa, 0x62, 0x75, 0x5e, 0xd5, 0x9f, 0xe1, 0x12, 0x69, 0xa2, + 0x1d, 0xbd, 0x97, 0x10, 0xdd, 0x62, 0xf9, 0x27, 0x47, 0xf2, 0x64, 0x12, 0xce, 0x95, 0xc0, 0xdc, 0xd6, 0x92, 0x48, 0xb4, + 0xb2, 0x18, 0x78, 0x2e, 0xaf, 0xb0, 0xd7, 0x48, 0x98, 0x29, 0x1b, 0xb9, 0x50, 0xf7, 0x95, 0x26, 0x53, 0xc4, 0xd6, 0x6f, + 0x26, 0x5f, 0x95, 0x9f, 0x51, 0xf3, 0x96, 0xbc, 0xca, 0xff, 0x0d, 0x8a, 0x69, 0xa5, 0xb0, 0x82, 0x02, 0x3e, 0x77, 0xb7, + 0x87, 0xea, 0x2a, 0xc0, 0x2e, 0xc7, 0xb6, 0x2c, 0x06, 0x19, 0x8f, 0x84, 0x46, 0xd6, 0x58, 0xf2, 0xb8, 0x8a, 0xdb, 0xd2, + 0x72, 0xe0, 0xc1, 0xa7, 0xb5, 0xb0, 0xb0, 0x2b, 0x83, 0xbb, 0x3b, 0x85, 0x3d, 0xcc, 0xc2, 0x89, 0x77, 0x65, 0x8d, 0x3c, + 0x03, 0xbe, 0x84, 0x78, 0xf7, 0x2a, 0x32, 0x9c, 0x02, 0x23, 0x7b, 0x25, 0x42, 0xec, 0x4f, 0x29, 0x77, 0x79, 0xc1, 0x48, + 0x46, 0xde, 0x76, 0xdb, 0x23, 0x9b, 0x5a, 0xee, 0xc7, 0xd1, 0x40, 0x73, 0x39, 0xa5, 0x23, 0x41, 0x66, 0x4c, 0x24, 0x1f, + 0xaa, 0xd8, 0xc7, 0x3c, 0xc4, 0xd5, 0xd7, 0x3b, 0x2d, 0x00, 0x1c, 0x49, 0x17, 0x7a, 0xb5, 0x90, 0x6c, 0x6b, 0x43, 0x2f, + 0x61, 0x6b, 0x8a, 0xdc, 0xb9, 0x58, 0xa8, 0x92, 0x49, 0x3e, 0xe9, 0x32, 0xc9, 0x3c, 0x4e, 0xeb, 0x2e, 0x15, 0xb8, 0x78, + 0x9f, 0x30, 0x05, 0xd7, 0x4d, 0x71, 0xe8, 0xd0, 0x98, 0x7c, 0xe5, 0x3b, 0xc7, 0x65, 0x27, 0x5b, 0x16, 0x35, 0x77, 0xfc, + 0x97, 0xf8, 0x1a, 0x07, 0xc2, 0x50, 0x67, 0x71, 0x7d, 0xd4, 0xd6, 0x55, 0x83, 0x8b, 0x15, 0xb1, 0xac, 0xba, 0xba, 0x8c, + 0x73, 0x6e, 0x58, 0xf9, 0x1a, 0x3a, 0x1b, 0xc0, 0xe5, 0x90, 0x5a, 0xae, 0x96, 0xeb, 0x05, 0xe1, 0x37, 0xaa, 0xeb, 0x0c, + 0xb9, 0xf2, 0xd4, 0x24, 0x82, 0x70, 0x64, 0x7a, 0x9b, 0x13, 0x27, 0xab, 0xb9, 0x18, 0xc8, 0xc7, 0xa3, 0x36, 0x5c, 0x7d, + 0xff, 0xb8, 0xde, 0xbb, 0x9b, 0xc8, 0x78, 0xdf, 0xc8, 0x99, 0x39, 0x9e, 0xce, 0x1b, 0xe0, 0x09, 0x53, 0x00, 0x7d, 0xad, + 0x86, 0x87, 0x8a, 0x31, 0x50, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x1c, + 0x1e, 0x1a, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x20, 0x00, 0x53, 0x00, 0x53, 0x00, 0x4c, 0x00, 0x20, + 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, + 0x15, 0x31, 0x16, 0x04, 0x14, 0xa6, 0x63, 0xd5, 0xb2, 0xb4, 0x24, 0x91, 0x4c, 0x75, 0xa8, 0x11, 0x34, 0xd7, 0x7f, 0xb0, + 0xa3, 0x55, 0xd4, 0xfd, 0x9a, 0x30, 0x30, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, + 0x04, 0x14, 0x2f, 0xc5, 0x73, 0xe2, 0xe4, 0xb4, 0x77, 0xfb, 0xb5, 0x49, 0x80, 0xcf, 0x13, 0xbe, 0x63, 0x7e, 0xaf, 0xdc, + 0x2b, 0xae, 0x04, 0x08, 0xdc, 0x37, 0x8d, 0x3f, 0x8d, 0xc5, 0x94, 0x54, 0x02, 0x01, 0x01 }; +unsigned int Test_ssl_user_p12_len = 2695; + /* Test identity (PKCS12 data), SMIME cert, expired in 2008 */ -unsigned char TestIDSMIME2007_p12[2805] = { +unsigned char TestIDSMIME2007_p12[2805] = { 0x30,0x82,0x0a,0xf1,0x02,0x01,0x03,0x30,0x82,0x0a,0xb8,0x06,0x09,0x2a,0x86,0x48, 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0xa9,0x04,0x82,0x0a,0xa5,0x30,0x82, 0x0a,0xa1,0x30,0x82,0x05,0x17,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, @@ -937,7 +846,7 @@ unsigned char TestIDSMIME2007_p12[2805] = { /* Test identity (PKCS12 data), SSL cert, expired in 2008 */ -unsigned char TestIDSSL2007_p12[2753] = { +unsigned char TestIDSSL2007_p12[2753] = { 0x30,0x82,0x0a,0xbd,0x02,0x01,0x03,0x30,0x82,0x0a,0x84,0x06,0x09,0x2a,0x86,0x48, 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,0x0a,0x75,0x04,0x82,0x0a,0x71,0x30,0x82, 0x0a,0x6d,0x30,0x82,0x04,0xe7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07, @@ -1116,7 +1025,6 @@ unsigned char TestIDSSL2007_p12[2753] = { static int quiet = 0; static int debug = 0; -static int verbose = 0; #define MAXNAMELEN MAXPATHLEN #define MAXITEMS INT32_MAX @@ -1124,21 +1032,14 @@ static int verbose = 0; #pragma mark -- Utility Functions -- -void PrintTestResult(char *testStr, OSStatus status, OSStatus expected) +static void PrintTestResult(char *testStr, OSStatus status, OSStatus expected) { - if (verbose) { - fprintf(stdout, "%s: %s (result=%d, expected=%d)\n", testStr, - (status==expected) ? "OK" : "FAILED", - (int)status, (int)expected); - } - if (debug) { - fprintf(stdout, "\n"); - } + is(status, expected, "%s", testStr); fflush(stdout); } -void PrintStringToMatch(CFStringRef nameStr) +static void PrintStringToMatch(CFStringRef nameStr) { char *buf = (char*)malloc(MAXNAMELEN); if (buf) { @@ -1151,7 +1052,7 @@ void PrintStringToMatch(CFStringRef nameStr) } -void PrintSecCertificate(SecCertificateRef certificate) +static void PrintSecCertificate(SecCertificateRef certificate) { CFStringRef nameStr; OSStatus status = SecCertificateCopyCommonName(certificate, &nameStr); @@ -1171,7 +1072,7 @@ void PrintSecCertificate(SecCertificateRef certificate) } -void PrintSecIdentity(SecIdentityRef identity) +static void PrintSecIdentity(SecIdentityRef identity) { SecCertificateRef certRef; OSStatus status = SecIdentityCopyCertificate(identity, &certRef); @@ -1185,7 +1086,7 @@ void PrintSecIdentity(SecIdentityRef identity) } -void PrintCFStringWithFormat(const char *formatStr, CFStringRef inStr) +static void PrintCFStringWithFormat(const char *formatStr, CFStringRef inStr) { char *buf = (char*)malloc(MAXNAMELEN); if (buf) { @@ -1198,7 +1099,7 @@ void PrintCFStringWithFormat(const char *formatStr, CFStringRef inStr) } -void PrintCFThing(CFTypeRef thing) +static void PrintCFThing(CFTypeRef thing) { fprintf(stderr, "### Results: %p\n", (void*)thing); @@ -1226,98 +1127,65 @@ void PrintCFThing(CFTypeRef thing) } //%%% FIXME need to break this up into separate functions -int TestAddItems() +static int TestAddItems(SecKeychainRef keychain) { SecCertificateRef certs[5]; - SecKeychainRef keychain; CFDataRef tmpData; OSStatus status; -#if AUTO_TEST - /* the regression suite environment does not have a keychain; must create one */ - status = SecKeychainCreate("SecItemTest.keychain", 4, "test", FALSE, NULL, &keychain); -#else - status = SecKeychainCopyDefault(&keychain); -#endif - if (status) { - fprintf(stderr, "Unable to get default keychain: error %d\n", (int)status); - goto error_exit; - } - /* add test leaf */ tmpData = CFDataCreateWithBytesNoCopy(NULL, LEAF_CERT, sizeof(LEAF_CERT), kCFAllocatorNull); certs[0] = SecCertificateCreateWithData(NULL, tmpData); CFRelease(tmpData); -// will add this below using SecItemAdd instead of SecCertificateAddToKeychain -#if 0 - status = SecCertificateAddToKeychain(certs[0], keychain); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add test leaf certificate: error %d\n", (int)status); - goto error_exit; - } -#endif + /* add test intermediate */ tmpData = CFDataCreateWithBytesNoCopy(NULL, INTERMEDIATE_CERT, sizeof(INTERMEDIATE_CERT), kCFAllocatorNull); certs[1] = SecCertificateCreateWithData(NULL, tmpData); CFRelease(tmpData); -// will add this below using SecItemAdd instead of SecCertificateAddToKeychain -#if 0 - status = SecCertificateAddToKeychain(certs[1], keychain); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add test intermediate certificate: error %d\n", (int)status); - goto error_exit; - } -#endif + /* add test root */ tmpData = CFDataCreateWithBytesNoCopy(NULL, ROOT_CERT, sizeof(ROOT_CERT), kCFAllocatorNull); certs[2] = SecCertificateCreateWithData(NULL, tmpData); CFRelease(tmpData); // will add this below using SecItemAdd instead of SecCertificateAddToKeychain -#if 0 - status = SecCertificateAddToKeychain(certs[2], keychain); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add test root certificate: error %d\n", (int)status); - goto error_exit; - } -#endif /* use SecItemAdd to add an array containing certs 1-3 */ CFArrayRef certArray = CFArrayCreate(NULL, (const void**) certs, 3, &kCFTypeArrayCallBacks); CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(attrs, kSecClass, kSecClassCertificate); // we are adding certificates CFDictionaryAddValue(attrs, kSecUseItemList, certArray); // add these items (to default keychain, since we aren't specifying one) + CFDictionaryAddValue(attrs, kSecUseKeychain, keychain); // add these to the test keychain status = SecItemAdd(attrs, NULL); CFRelease(attrs); CFRelease(certArray); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add 3 test certificates: error %d\n", (int)status); + ok_status(status, "Unable to add 3 test certificates: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; - } - + } /* add test cert for S/MIME policy (encrypt only, no sign) */ tmpData = CFDataCreateWithBytesNoCopy(NULL, Test_smime_encryptonly, sizeof(Test_smime_encryptonly), kCFAllocatorNull); certs[3] = SecCertificateCreateWithData(NULL, tmpData); CFRelease(tmpData); status = SecCertificateAddToKeychain(certs[3], keychain); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add test S/MIME certificate: error %d\n", (int)status); + ok_status(status, "Unable to add test S/MIME certificate: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; - } + } /* add test cert for Code Signing policy */ tmpData = CFDataCreateWithBytesNoCopy(NULL, Test_codesign, sizeof(Test_codesign), kCFAllocatorNull); certs[4] = SecCertificateCreateWithData(NULL, tmpData); CFRelease(tmpData); status = SecCertificateAddToKeychain(certs[4], keychain); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add test Code Signing certificate: error %d\n", (int)status); + ok_status(status, "Unable to add test Code Signing certificate: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; - } + } /* import test SSL identity */ { - CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, Test_p12, (CFIndex)sizeof(Test_p12), kCFAllocatorNull); + CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, Test_ssl_user_p12, (CFIndex)sizeof(Test_ssl_user_p12), kCFAllocatorNull); SecExternalFormat format = kSecFormatPKCS12; SecExternalItemType itemType = kSecItemTypeAggregate; SecItemImportExportFlags flags = 0; @@ -1355,10 +1223,10 @@ int TestAddItems() CFRelease(keyUsagesArray); CFRelease(keyAttrsArray); #endif - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to import test SSL identity: error %d\n", (int)status); + ok_status(status, "Unable to import test SSL identity: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; - } + } } /* import test S/MIME signing identity */ @@ -1401,12 +1269,12 @@ int TestAddItems() CFRelease(keyUsagesArray); CFRelease(keyAttrsArray); #endif - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to import test S/MIME identity: error %d\n", (int)status); + ok_status(status, "Unable to import test S/MIME identity: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } } - + /* import expired SSL identity */ { CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, TestIDSSL2007_p12, (CFIndex)sizeof(TestIDSSL2007_p12), kCFAllocatorNull); @@ -1431,8 +1299,8 @@ int TestAddItems() NULL, &format, &itemType, flags, &keyParams, keychain, NULL); CFRelease(keyUsagesArray); CFRelease(keyAttrsArray); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to import TestIDSSL2007_p12 identity: error %d\n", (int)status); + ok_status(status, "Unable to import TestIDSSL2007_p12 identity: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } } @@ -1461,20 +1329,20 @@ int TestAddItems() NULL, &format, &itemType, flags, &keyParams, keychain, NULL); CFRelease(keyUsagesArray); CFRelease(keyAttrsArray); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to import TestIDSMIME2007_p12 identity: error %d\n", (int)status); + ok_status(status, "Unable to import TestIDSMIME2007_p12 identity: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } } - + /* add generic password items */ status = SecKeychainAddGenericPassword(keychain, strlen("Test Service 42"), "Test Service 42", strlen("nobody"), "nobody", strlen("weakpass"), "weakpass", NULL); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add \"Test Service 42\" generic password: error %d\n", (int)status); + ok_status(status, "Unable to add \"Test Service 42\" generic password: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } status = SecKeychainAddGenericPassword(keychain, @@ -1482,11 +1350,11 @@ int TestAddItems() strlen("nobody"), "nobody", strlen("weakpass"), "weakpass", NULL); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add \"Test Service 69\" generic password: error %d\n", (int)status); + ok_status(status, "Unable to add \"Test Service 69\" generic password: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } - + /* add internet password items */ status = SecKeychainAddInternetPassword(keychain, strlen("test1.subdomain.apple.com"), "test1.subdomain.apple.com", @@ -1496,8 +1364,8 @@ int TestAddItems() 80, kSecProtocolTypeHTTP, kSecAuthenticationTypeDefault, strlen("weakpass"), "weakpass", NULL); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add \"test1.subdomain.apple.com\" internet password: error %d\n", (int)status); + ok_status(status, "Unable to add \"test1.subdomain.apple.com\" internet password: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } status = SecKeychainAddInternetPassword(keychain, @@ -1508,8 +1376,8 @@ int TestAddItems() 443, kSecProtocolTypeHTTPS, kSecAuthenticationTypeDefault, strlen("weakpass"), "weakpass", NULL); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add \"test2.subdomain.apple.com\" internet password: error %d\n", (int)status); + ok_status(status, "Unable to add \"test2.subdomain.apple.com\" internet password: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } @@ -1522,8 +1390,8 @@ int TestAddItems() 143, kSecProtocolTypeIMAP, kSecAuthenticationTypeDefault, strlen("testpass"), "testpass", NULL); - if (status && status != errSecDuplicateItem) { // ignore error if duplicate - fprintf(stderr, "Unable to add \"mail.apple.com\" internet password: error %d\n", (int)status); + ok_status(status, "Unable to add \"mail.apple.com\" internet password: error %d\n", (int)status); + if (status && status != errSecDuplicateItem) { goto error_exit; } @@ -1535,12 +1403,12 @@ error_exit: if (keychain) CFRelease(keychain); PrintTestResult("TestAddItems", status, noErr); - + return (int)status; } -int CheckResults(CFTypeRef results, CFIndex minMatchesExpected, CFIndex maxMatchesExpected) +static int CheckResults(CFTypeRef results, CFIndex minMatchesExpected, CFIndex maxMatchesExpected) { OSStatus status = noErr; if (debug) { @@ -1569,6 +1437,13 @@ int CheckResults(CFTypeRef results, CFIndex minMatchesExpected, CFIndex maxMatch /* should not happen, unless SecItemCopyMatching has a bug */ status = errSecInternalError; } + if(matchesFound < minMatchesExpected) { + fail("CheckResults: %ld < %ld (minimum required)", matchesFound, minMatchesExpected); + } else if(matchesFound > maxMatchesExpected) { + fail("CheckResults: %ld > %ld (maximum allowed", matchesFound, maxMatchesExpected); + } else { + pass("CheckResults: matches found fall within requirements: %ld <= %ld <= %ld", minMatchesExpected, matchesFound, maxMatchesExpected); + } } return (int)status; } @@ -1577,7 +1452,8 @@ int CheckResults(CFTypeRef results, CFIndex minMatchesExpected, CFIndex maxMatch #pragma mark -- Individual Test Cases -- -int FindCertificateByEmail(CFStringRef emailStr, +static int FindCertificateByEmail(SecKeychainRef keychain, + CFStringRef emailStr, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, @@ -1593,6 +1469,10 @@ int FindCertificateByEmail(CFStringRef emailStr, CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFTypeRef results = NULL; if (debug) { PrintStringToMatch(emailStr); @@ -1608,12 +1488,13 @@ int FindCertificateByEmail(CFStringRef emailStr, CFRelease(query); PrintTestResult("FindCertificateByEmail", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindCertificateByLabel(CFStringRef labelStr, +static int FindCertificateByLabel(SecKeychainRef keychain, + CFStringRef labelStr, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, @@ -1630,6 +1511,10 @@ int FindCertificateByLabel(CFStringRef labelStr, CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFTypeRef results = NULL; if (debug) { PrintStringToMatch(labelStr); @@ -1643,14 +1528,15 @@ int FindCertificateByLabel(CFStringRef labelStr, } if (query) CFRelease(query); - + PrintTestResult("FindCertificateByLabel", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindCertificateByNameInSubject(CFStringRef nameStr, +static int FindCertificateByNameInSubject(SecKeychainRef keychain, + CFStringRef nameStr, CFTypeRef matchType, CFTypeRef returnType, CFTypeRef matchLimit, @@ -1667,6 +1553,10 @@ int FindCertificateByNameInSubject(CFStringRef nameStr, CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFTypeRef results = NULL; if (debug) { PrintStringToMatch(nameStr); @@ -1687,30 +1577,19 @@ int FindCertificateByNameInSubject(CFStringRef nameStr, } -int FindCertificateByNameAndPolicy(CFStringRef nameStr, - CFTypeRef policyIdentifier, - Boolean isClientPolicy, +static int FindCertificateByNameAndPolicy(SecKeychainRef keychain, + CFStringRef nameStr, + SecPolicyRef policy, CFTypeRef returnType, CFTypeRef matchLimit, - CFIndex minMatchesExpected, + CFIndex matchesExpected, OSStatus expected) { - /* given the policy OID, create a SecPolicyRef */ - SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier); - if (policy == NULL) - return errSecPolicyNotFound; - if (isClientPolicy == TRUE) { - /* specify the kSecPolicyClient property key for this policy */ - const void *keys[] = { kSecPolicyClient }; - const void *values[] = { kCFBooleanTrue }; - CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, - sizeof(keys) / sizeof(*keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - SecPolicySetProperties(policy, properties); - } + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecMatchSubjectContains, kSecMatchPolicy, @@ -1718,6 +1597,7 @@ int FindCertificateByNameAndPolicy(CFStringRef nameStr, returnType }; const void *values[] = { + searchList, kSecClassCertificate, nameStr, policy, @@ -1734,27 +1614,26 @@ int FindCertificateByNameAndPolicy(CFStringRef nameStr, if (debug) { PrintStringToMatch(nameStr); - PrintStringToMatch(CFCopyDescription(policyIdentifier)); + PrintStringToMatch(SecPolicyGetName(policy)); } status = SecItemCopyMatching(query, &results); if (!status && results) { - status = CheckResults(results, minMatchesExpected, MAXITEMS); + status = CheckResults(results, matchesExpected, matchesExpected); CFRelease(results); } if (query) CFRelease(query); - if (policy) - CFRelease(policy); - + PrintTestResult("FindCertificateByNameAndPolicy", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindCertificateByNameAndValidDate(CFStringRef nameStr, +static int FindCertificateByNameAndValidDate(SecKeychainRef keychain, + CFStringRef nameStr, CFTypeRef validOnDate, CFTypeRef returnType, CFTypeRef matchLimit, @@ -1772,6 +1651,10 @@ int FindCertificateByNameAndValidDate(CFStringRef nameStr, CFDictionaryAddValue( query, kSecMatchLimit, matchLimit ); CFDictionaryAddValue( query, returnType, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFTypeRef results = NULL; if (debug) { PrintStringToMatch(nameStr); @@ -1786,14 +1669,15 @@ int FindCertificateByNameAndValidDate(CFStringRef nameStr, } if (query) CFRelease(query); - + PrintTestResult("FindCertificateByNameAndValidDate", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindCertificateForSMIMEEncryption(CFStringRef emailAddr, +static int FindCertificateForSMIMEEncryption(SecKeychainRef keychain, + CFStringRef emailAddr, CFTypeRef validOnDate, CFTypeRef returnType, CFTypeRef matchLimit, @@ -1820,6 +1704,10 @@ int FindCertificateForSMIMEEncryption(CFStringRef emailAddr, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + /* set up the query */ CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); CFDictionaryAddValue( query, kSecMatchPolicy, policy ); @@ -1846,15 +1734,15 @@ int FindCertificateForSMIMEEncryption(CFStringRef emailAddr, CFRelease(policy); if (properties) CFRelease(properties); - + PrintTestResult("FindCertificateForSMIMEEncryption", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindPreferredCertificateForSMIMEEncryption(CFStringRef emailAddr, - CFTypeRef validOnDate) +static int FindPreferredCertificateForSMIMEEncryption(SecKeychainRef keychain, + CFStringRef emailAddr, CFTypeRef validOnDate) { // Note: this function assumes that a preferred certificate has been set up // previously for the given email address. This is handled in the calling @@ -1885,7 +1773,7 @@ int FindPreferredCertificateForSMIMEEncryption(CFStringRef emailAddr, CFDictionaryRef properties = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecPolicyKU_KeyEncipherment, (const void **)&kCFBooleanTrue, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); status = SecPolicySetProperties(policy, properties); CFRelease(properties); - + // set up an item list consisting of just our preferred certificate CFArrayRef itemList = CFArrayCreate(kCFAllocatorDefault, (const void **)&preferredCertificate, 1, &kCFTypeArrayCallBacks); @@ -1898,6 +1786,10 @@ int FindPreferredCertificateForSMIMEEncryption(CFStringRef emailAddr, CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); // only need to match one item! CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + if (debug) { PrintStringToMatch(emailAddr); PrintStringToMatch(CFCopyDescription(validOnDate)); @@ -1921,14 +1813,14 @@ int FindPreferredCertificateForSMIMEEncryption(CFStringRef emailAddr, if (preferredCertificate) CFRelease(preferredCertificate); - + PrintTestResult("FindPreferredCertificateForSMIMEEncryption", status, noErr); - + return (status==noErr) ? (int)noErr : (int)status; } -int SetPreferredCertificateForSMIMEEncryption(CFStringRef nameStr, +static int SetPreferredCertificateForSMIMEEncryption(SecKeychainRef keychain, CFStringRef nameStr, CFStringRef emailAddr) { // find the certificate exactly matching the given common name @@ -1936,6 +1828,10 @@ int SetPreferredCertificateForSMIMEEncryption(CFStringRef nameStr, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFDictionaryAddValue( query, kSecClass, kSecClassCertificate ); CFDictionaryAddValue( query, kSecMatchSubjectWholeString, nameStr ); CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); @@ -1943,10 +1839,10 @@ int SetPreferredCertificateForSMIMEEncryption(CFStringRef nameStr, CFTypeRef results = NULL; OSStatus status = SecItemCopyMatching(query, &results); - + if (!quiet && status) fprintf(stderr, "SetPreferredCertificateForSMIMEEncryption: SecItemCopyMatching error %d\n", (int)status); - + if (!status && results) { // since we asked for kSecMatchLimitOne, the result is a single item SecCertificateRef certificate = (SecCertificateRef) results; @@ -1971,19 +1867,25 @@ int SetPreferredCertificateForSMIMEEncryption(CFStringRef nameStr, } -int FindIdentityByName(CFStringRef nameStr, +static int FindIdentityByName(SecKeychainRef keychain, + CFStringRef nameStr, CFTypeRef returnType, CFTypeRef matchLimit, - CFIndex minMatchesExpected, + CFIndex matchesExpected, OSStatus expected) { + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecMatchSubjectContains, kSecMatchLimit, returnType }; const void *values[] = { + searchList, kSecClassIdentity, nameStr, matchLimit, @@ -2002,47 +1904,37 @@ int FindIdentityByName(CFStringRef nameStr, status = SecItemCopyMatching(query, &results); if (!status && results) { - status = CheckResults(results, minMatchesExpected, MAXITEMS); + status = CheckResults(results, matchesExpected, matchesExpected); CFRelease(results); } if (query) CFRelease(query); PrintTestResult("FindIdentityByName", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindIdentityByPolicy(CFTypeRef policyIdentifier, - Boolean isClientPolicy, +static int FindIdentityByPolicy(SecKeychainRef keychain, + SecPolicyRef policy, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, OSStatus expected) { - /* given the policy OID, create a SecPolicyRef */ - SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier); - if (policy == NULL) - return errSecPolicyNotFound; - if (isClientPolicy == TRUE) { - /* specify the kSecPolicyClient property key for this policy */ - const void *keys[] = { kSecPolicyClient }; - const void *values[] = { kCFBooleanTrue }; - CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, - sizeof(keys) / sizeof(*keys), - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - SecPolicySetProperties(policy, properties); - } + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecMatchPolicy, kSecMatchLimit, returnType }; const void *values[] = { + searchList, kSecClassIdentity, policy, matchLimit, @@ -2056,7 +1948,7 @@ int FindIdentityByPolicy(CFTypeRef policyIdentifier, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - if (debug) PrintStringToMatch(CFCopyDescription(policyIdentifier)); + if (debug) PrintStringToMatch(SecPolicyGetName(policy)); status = SecItemCopyMatching(query, &results); @@ -2066,22 +1958,21 @@ int FindIdentityByPolicy(CFTypeRef policyIdentifier, } if (query) CFRelease(query); - if (policy) - CFRelease(policy); - + PrintTestResult("FindIdentityByPolicy", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindIdentityByPolicyAndValidDate(CFTypeRef policyIdentifier, +static int FindIdentityByPolicyAndValidDate(SecKeychainRef keychain, + CFTypeRef policyIdentifier, Boolean isClientPolicy, CFTypeRef validOnDate, CFStringRef forbidStr, CFTypeRef returnType, CFTypeRef matchLimit, - CFIndex minMatchesExpected, + CFIndex matchesExpected, OSStatus expected) { /* given the policy OID, create a SecPolicyRef */ @@ -2099,7 +1990,11 @@ int FindIdentityByPolicyAndValidDate(CFTypeRef policyIdentifier, SecPolicySetProperties(policy, properties); } + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecMatchPolicy, kSecMatchValidOnDate, @@ -2107,6 +2002,7 @@ int FindIdentityByPolicyAndValidDate(CFTypeRef policyIdentifier, returnType }; const void *values[] = { + searchList, kSecClassIdentity, policy, validOnDate, @@ -2124,7 +2020,7 @@ int FindIdentityByPolicyAndValidDate(CFTypeRef policyIdentifier, if (debug) PrintStringToMatch(CFCopyDescription(policyIdentifier)); status = SecItemCopyMatching(query, &results); - + // check returned items for forbidStr as a substring in the label attribute; // return errSecInternalError if found if (!status && results && forbidStr) { @@ -2150,21 +2046,22 @@ int FindIdentityByPolicyAndValidDate(CFTypeRef policyIdentifier, if (!status && results) { - status = CheckResults(results, minMatchesExpected, MAXITEMS); + status = CheckResults(results, matchesExpected, matchesExpected); CFRelease(results); } if (query) CFRelease(query); if (policy) CFRelease(policy); - + PrintTestResult("FindIdentityByPolicyAndValidDate", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindIdentityByNameAndValidDate(CFStringRef nameStr, +static int FindIdentityByNameAndValidDate(SecKeychainRef keychain, + CFStringRef nameStr, CFTypeRef validOnDate, CFTypeRef returnType, CFTypeRef matchLimit, @@ -2175,6 +2072,10 @@ int FindIdentityByNameAndValidDate(CFStringRef nameStr, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + /* set up the query */ CFDictionaryAddValue( query, kSecClass, kSecClassIdentity ); CFDictionaryAddValue( query, kSecMatchSubjectContains, nameStr ); @@ -2196,14 +2097,14 @@ int FindIdentityByNameAndValidDate(CFStringRef nameStr, } if (query) CFRelease(query); - + PrintTestResult("FindIdentityByNameAndValidDate", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindPreferredIdentityForSMIMESigning(CFStringRef emailAddr, +static int FindPreferredIdentityForSMIMESigning(SecKeychainRef keychain, CFStringRef emailAddr, CFTypeRef validOnDate) { // Note: this function assumes that a preferred identity has been set up @@ -2213,17 +2114,21 @@ int FindPreferredIdentityForSMIMESigning(CFStringRef emailAddr, OSStatus status = noErr; SecIdentityRef preferredIdentity = NULL; SecIdentityRef validatedIdentity = NULL; - + // Pass an explicit key usage value to SecIdentityCopyPreferred to test CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanSign, 1, &kCFTypeArrayCallBacks); - + preferredIdentity = SecIdentityCopyPreferred(emailAddr, keyUsage, NULL); + isnt(preferredIdentity, NULL, "FindPreferredIdentityForSMIMESigning: SecIdentityCopyPreferred"); + if (!preferredIdentity) status = errSecItemNotFound; // our test expects a preferred identity to exist, so we return an error if (keyUsage) CFRelease(keyUsage); if (!status && preferredIdentity) { + pass("FindPreferredIdentityForSMIMESigning: found a preferred identity"); + // We found a preferred identity, but it may have expired. // Verify the preferred identity by looking up all identities which // are valid for SMIME signing, and using the kSecMatchItemList query @@ -2231,11 +2136,8 @@ int FindPreferredIdentityForSMIMESigning(CFStringRef emailAddr, // we end up with 0 results, the preferred identity wasn't valid. // set up the S/MIME policy first to check for Digital Signature key usage - SecPolicyRef policy = SecPolicyCreateWithOID(kSecPolicyAppleSMIME); - CFDictionaryRef properties = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecPolicyKU_DigitalSignature, (const void **)&kCFBooleanTrue, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - status = SecPolicySetProperties(policy, properties); - CFRelease(properties); - + SecPolicyRef policy = SecPolicyCreateSMIME(kSecSignSMIMEUsage, emailAddr); + // set up an item list consisting of just our preferred identity CFArrayRef itemList = CFArrayCreate(kCFAllocatorDefault, (const void **)&preferredIdentity, 1, &kCFTypeArrayCallBacks); @@ -2248,12 +2150,17 @@ int FindPreferredIdentityForSMIMESigning(CFStringRef emailAddr, CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); // only need to match one item! CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + if (debug) { PrintStringToMatch(emailAddr); PrintStringToMatch(CFCopyDescription(validOnDate)); } status = SecItemCopyMatching(query, (CFTypeRef*)&validatedIdentity); + ok_status(status, "FindPreferredIdentityForSMIMESigning: SecItemCopyMatching"); if (!status && validatedIdentity) { status = CheckResults(validatedIdentity, 1, 1); // expect exactly 1 result @@ -2266,19 +2173,20 @@ int FindPreferredIdentityForSMIMESigning(CFStringRef emailAddr, if (itemList) CFRelease(itemList); } - else if (!quiet) - fprintf(stderr, "FindPreferredIdentityForSMIMESigning: unexpected error %d\n", (int)status); + else { + fail("FindPreferredIdentityForSMIMESigning: unexpected error %d\n", (int)status); + } if (preferredIdentity) CFRelease(preferredIdentity); - + PrintTestResult("FindPreferredIdentityForSMIMESigning", status, noErr); - + return (status==noErr) ? (int)noErr : (int)status; } -int SetPreferredIdentityForSMIMESigning(CFStringRef nameStr, +static int SetPreferredIdentityForSMIMESigning(SecKeychainRef keychain, CFStringRef nameStr, CFStringRef emailAddr) { // find the identity exactly matching the given common name @@ -2286,6 +2194,10 @@ int SetPreferredIdentityForSMIMESigning(CFStringRef nameStr, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFDictionaryAddValue( query, kSecClass, kSecClassIdentity ); CFDictionaryAddValue( query, kSecMatchSubjectWholeString, nameStr ); CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); @@ -2293,25 +2205,22 @@ int SetPreferredIdentityForSMIMESigning(CFStringRef nameStr, CFTypeRef results = NULL; OSStatus status = SecItemCopyMatching(query, &results); - - if (!quiet && status) - fprintf(stderr, "SetPreferredIdentityForSMIMESigning: SecItemCopyMatching error %d\n", (int)status); - + + ok_status(status, "SetPreferredIdentityForSMIMESigning: SecItemCopyMatching error %d\n", (int)status); + if (!status && results) { // since we asked for kSecMatchLimitOne, the result is a single SecIdentityRef SecIdentityRef identity = (SecIdentityRef) results; - if (SecIdentityGetTypeID() != CFGetTypeID(identity)) { - fprintf(stderr, "SetPreferredCertificateForSMIMEEncryption: unexpected result type!\n"); - } - else { - // Pass an explicit key usage value to SecIdentitySetPreferred to test - CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanSign, 1, &kCFTypeArrayCallBacks); - status = SecIdentitySetPreferred(identity, emailAddr, keyUsage); - if (!quiet && status) - fprintf(stderr, "SetPreferredIdentityForSMIMESigning: SecIdentitySetPreferred error %d\n", (int)status); - if (keyUsage) - CFRelease(keyUsage); - } + + is(SecIdentityGetTypeID(),CFGetTypeID(identity), "SetPreferredCertificateForSMIMEEncryption: unexpected result type!\n"); + + // Pass an explicit key usage value to SecIdentitySetPreferred to test + CFArrayRef keyUsage = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecAttrCanSign, 1, &kCFTypeArrayCallBacks); + status = SecIdentitySetPreferred(identity, emailAddr, keyUsage); + ok_status(status, "SetPreferredIdentityForSMIMESigning: SecIdentitySetPreferred error %d\n", (int)status); + if (keyUsage) + CFRelease(keyUsage); + CFRelease(results); } if (query) @@ -2321,19 +2230,25 @@ int SetPreferredIdentityForSMIMESigning(CFStringRef nameStr, } -int FindGenericPasswordByAccount(CFStringRef accountStr, +static int FindGenericPasswordByAccount(SecKeychainRef keychain, + CFStringRef accountStr, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, OSStatus expected) { + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecAttrAccount, kSecMatchLimit, returnType }; const void *values[] = { + searchList, kSecClassGenericPassword, accountStr, matchLimit, @@ -2350,6 +2265,7 @@ int FindGenericPasswordByAccount(CFStringRef accountStr, if (debug) PrintStringToMatch(accountStr); status = SecItemCopyMatching(query, &results); + ok_status(status, "FindGenericPasswordByAccount: SecItemCopyMatching"); if (!status && results) { status = CheckResults(results, minMatchesExpected, MAXITEMS); @@ -2359,19 +2275,24 @@ int FindGenericPasswordByAccount(CFStringRef accountStr, CFRelease(query); PrintTestResult("FindGenericPasswordByAccount", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindGenericPasswordByAccountAndService(CFStringRef accountStr, +static int FindGenericPasswordByAccountAndService(SecKeychainRef keychain, + CFStringRef accountStr, CFStringRef serviceStr, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, OSStatus expected) { + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecAttrAccount, kSecAttrService, @@ -2379,6 +2300,7 @@ int FindGenericPasswordByAccountAndService(CFStringRef accountStr, returnType }; const void *values[] = { + searchList, kSecClassGenericPassword, accountStr, serviceStr, @@ -2398,6 +2320,7 @@ int FindGenericPasswordByAccountAndService(CFStringRef accountStr, PrintStringToMatch(serviceStr); } status = SecItemCopyMatching(query, &results); + ok_status(status, "FindGenericPasswordByAccountAndService: SecItemCopyMatching"); if (!status && results) { status = CheckResults(results, minMatchesExpected, MAXITEMS); @@ -2407,24 +2330,30 @@ int FindGenericPasswordByAccountAndService(CFStringRef accountStr, CFRelease(query); PrintTestResult("FindGenericPasswordByAccountAndService", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindInternetPasswordByAccount(CFStringRef accountStr, +static int FindInternetPasswordByAccount(SecKeychainRef keychain, + CFStringRef accountStr, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, OSStatus expected) { + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecAttrAccount, kSecMatchLimit, returnType }; const void *values[] = { + searchList, kSecClassInternetPassword, accountStr, matchLimit, @@ -2441,6 +2370,7 @@ int FindInternetPasswordByAccount(CFStringRef accountStr, if (debug) PrintStringToMatch(accountStr); status = SecItemCopyMatching(query, &results); + ok_status(status, "FindInternetPasswordByAccount: SecItemCopyMatching"); if (!status && results) { status = CheckResults(results, minMatchesExpected, MAXITEMS); @@ -2450,19 +2380,24 @@ int FindInternetPasswordByAccount(CFStringRef accountStr, CFRelease(query); PrintTestResult("FindInternetPasswordByAccount", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindInternetPasswordByAccountAndServer(CFStringRef accountStr, +static int FindInternetPasswordByAccountAndServer(SecKeychainRef keychain, + CFStringRef accountStr, CFStringRef serverStr, CFTypeRef returnType, CFTypeRef matchLimit, CFIndex minMatchesExpected, OSStatus expected) { + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + const void *keys[] = { + kSecMatchSearchList, kSecClass, kSecAttrAccount, kSecAttrServer, @@ -2470,6 +2405,7 @@ int FindInternetPasswordByAccountAndServer(CFStringRef accountStr, returnType }; const void *values[] = { + searchList, kSecClassInternetPassword, accountStr, serverStr, @@ -2489,6 +2425,7 @@ int FindInternetPasswordByAccountAndServer(CFStringRef accountStr, PrintStringToMatch(serverStr); } status = SecItemCopyMatching(query, &results); + ok_status(status, "FindInternetPasswordByAccountAndServer: SecItemCopyMatching"); if (!status && results) { status = CheckResults(results, minMatchesExpected, MAXITEMS); @@ -2498,22 +2435,22 @@ int FindInternetPasswordByAccountAndServer(CFStringRef accountStr, CFRelease(query); PrintTestResult("FindInternetPasswordByAccountAndServer", status, expected); - + return (status==expected) ? (int)noErr : (int)status; } -int FindMailPassword( +static int FindMailPassword(SecKeychainRef keychain, CFStringRef account, CFStringRef server) { CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - + SInt16 port = 143; CFNumberRef portNumber = CFNumberCreate(NULL, kCFNumberSInt16Type, &port); - + // set up query for a Mail password (IMAP, port 143) for given account and server CFDictionaryAddValue( query, kSecClass, kSecClassInternetPassword ); CFDictionaryAddValue( query, kSecAttrAccount, account ); @@ -2523,21 +2460,21 @@ int FindMailPassword( CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); CFDictionaryAddValue( query, kSecReturnData, kCFBooleanTrue ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionaryAddValue(query, kSecMatchSearchList, searchList); + CFTypeRef results = NULL; OSStatus status = SecItemCopyMatching(query, &results); - - if (!quiet && status) - fprintf(stderr, "FindMailPassword: SecItemCopyMatching error %d\n", (int)status); - + ok_status(status, "FindMailPassword: SecItemCopyMatching error %d\n", (int)status); + if (!status && results) { // since we asked for kSecMatchLimitOne w/kSecReturnData, the result is the found password CFDataRef password = (CFDataRef) results; - if (CFDataGetTypeID() != CFGetTypeID(password)) { - fprintf(stderr, "FindMailPassword: unexpected result type!\n"); - } - else { - if (debug) CFShow(password); - } + is(CFDataGetTypeID(), CFGetTypeID(password), "FindMailPassword: unexpected result type!\n"); + + if (debug) CFShow(password); + CFRelease(results); } if (query) @@ -2563,7 +2500,8 @@ const CFStringRef gUUID = CFSTR("550e8400-e29b-41d4-a716-446655441234"); // then the attempt would fail and leave a "turd" key with no label in your // keychain: , fixed in 11A268a. -int CreateSymmetricKey( +static int CreateSymmetricKey( + SecKeychainRef keychain, CFStringRef keyLabel, CFStringRef keyAppLabel, CFStringRef keyAppTag, @@ -2573,11 +2511,6 @@ int CreateSymmetricKey( int keySizeValue = 128; CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); - // get a SecKeychainRef for the keychain in which we want the key to be created - // (this step is optional, but if omitted, the key is NOT saved in any keychain!) - SecKeychainRef keychain = NULL; - status = SecKeychainCopyDefault(&keychain); - // create a SecAccessRef to set up the initial access control settings for this key // (this step is optional; if omitted, the creating application has access to the key) // note: the access descriptor should be the same string as will be used for the item's label, @@ -2628,20 +2561,21 @@ int CreateSymmetricKey( status = (error) ? (OSStatus) CFErrorGetCode(error) : noErr; // if (status == errSecDuplicateItem) // status = noErr; // it's OK if the key already exists - + if (key) CFRelease(key); if (error) CFRelease(error); if (params) CFRelease(params); if (keychain) CFRelease(keychain); if (access) CFRelease(access); - + PrintTestResult("CreateSymmetricKey", status, expected); - + return status; } -int FindSymmetricKey( +static int FindSymmetricKey( + SecKeychainRef keychain, CFStringRef keyLabel, CFStringRef keyAppLabel, CFStringRef keyAppTag, @@ -2653,6 +2587,10 @@ int FindSymmetricKey( &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFDictionaryAddValue( query, kSecClass, kSecClassKey ); CFDictionaryAddValue( query, kSecAttrKeyClass, kSecAttrKeyClassSymmetric ); CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitOne ); // we only want the first match @@ -2667,6 +2605,11 @@ int FindSymmetricKey( CFTypeRef result = NULL; OSStatus status = SecItemCopyMatching(query, &result); + if(expected == errSecSuccess) { + ok_status(status, "FindSymmetricKey: SecItemCopyMatching"); + } else { + is(status, expected, "FindSymmetricKey: SecItemCopyMatching"); + } // print result and clean up if (debug) { @@ -2695,14 +2638,15 @@ int FindSymmetricKey( if (key) CFRelease(key); if (query) CFRelease(query); - + PrintTestResult("FindSymmetricKey", status, expected); - + return status; } -int FindAndDeleteItemsByName( +static int FindAndDeleteItemsByName( + SecKeychainRef keychain, CFStringRef nameStr, CFStringRef accountStr, CFTypeRef itemClass, @@ -2714,6 +2658,10 @@ int FindAndDeleteItemsByName( &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + CFTypeRef nameMatchKey; if (CFEqual(itemClass, kSecClassCertificate) || CFEqual(itemClass, kSecClassIdentity)) { @@ -2737,13 +2685,14 @@ int FindAndDeleteItemsByName( } OSStatus status = SecItemCopyMatching(query, &results); + ok_status(status, "FindAndDeleteItemsByName: SecItemCopyMatching"); if (!status) { /* Make sure that we found the items we expected to find */ status = CheckResults(results, minMatchesExpected, MAXITEMS); CFRelease(results); } - + if (!status) { /* OK, now the real reason we're here... the same query must work for SecItemDelete */ status = SecItemDelete(query); @@ -2757,17 +2706,17 @@ int FindAndDeleteItemsByName( if (!status) { /* oops... we still found matches using this query */ int count = (int)CFArrayGetCount(results); - fprintf(stderr, "### still found %d items, expected 0\n", count); + is(count, 0, "### FindAndDeleteItemsByName: still found %d items, expected 0\n", count); CFRelease(results); } PrintTestResult("FindAndDeleteItemsByName: find after delete", status, errSecItemNotFound); - + status = (status == errSecItemNotFound) ? expected : errSecInternalError; } if (query) CFRelease(query); - + return (status==expected) ? (int)noErr : (int)status; } @@ -2775,79 +2724,90 @@ int FindAndDeleteItemsByName( #pragma mark -- Test Functions -- -int TestIdentityLookup() +static int TestIdentityLookup(SecKeychainRef keychain) { int result = 0; // look up identity by name, want first result as a SecIdentityRef - result += FindIdentityByName(CFSTR("Test SSL User"), kSecReturnRef, kSecMatchLimitOne, 1, noErr); + result += FindIdentityByName(keychain, CFSTR("Test SSL User"), kSecReturnRef, kSecMatchLimitOne, 1, noErr); // look up existing non-identity certificate by name, expect errSecItemNotFound error - result += FindIdentityByName(CFSTR("Test-5685316-LEAF"), kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + result += FindIdentityByName(keychain, CFSTR("Test-5685316-LEAF"), kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); // look up non-existent identity by name, expect errSecItemNotFound error - result += FindIdentityByName(CFSTR("myxlpytk"), kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); - + result += FindIdentityByName(keychain, CFSTR("myxlpytk"), kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + + /* given the policy OID, create a SecPolicyRef */ + const void *keys[] = { kSecPolicyClient }; + const void *values[] = { kCFBooleanTrue }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + SecPolicyRef sslPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, properties); + SecPolicyRef codeSigningPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleCodeSigning, NULL); + // look up identity by policy, want first result as a SecIdentityRef (should find "Test SSL User" identity) - result += FindIdentityByPolicy(kSecPolicyAppleSSL, TRUE, kSecReturnRef, kSecMatchLimitOne, 1, noErr); + result += FindIdentityByPolicy(keychain, sslPolicy, kSecReturnRef, kSecMatchLimitOne, 1, noErr); // look up identity by policy, want first result as a CFDictionary of attributes (should find "Test SSL User" identity) - result += FindIdentityByPolicy(kSecPolicyAppleSSL, TRUE, kSecReturnAttributes, kSecMatchLimitOne, 1, noErr); - + result += FindIdentityByPolicy(keychain, sslPolicy, kSecReturnAttributes, kSecMatchLimitOne, 1, noErr); + // look up identity by policy, expect errSecItemNotFound error (this assumes no code signing identity is present!) - result += FindIdentityByPolicy(kSecPolicyAppleCodeSigning, FALSE, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); + result += FindIdentityByPolicy(keychain, codeSigningPolicy, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); // ------------------------- // test kSecMatchValidOnDate // ------------------------- // make a valid date which will match at least some identities we used to populate the keychain - CFGregorianDate aCurrentGDate = { 2010, 7, 20, 12, 0, 0 }; // Jul 20 2010 12:00 PM + CFGregorianDate aCurrentGDate = { 2016, 7, 20, 12, 0, 0 }; // Jul 20 2016 12:00 PM CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); - if (FindIdentityByNameAndValidDate(CFSTR("Test SSL User"), aCurrentDate, kSecReturnRef, kSecMatchLimitAll, 1, noErr)) + if (FindIdentityByNameAndValidDate(keychain, CFSTR("Test SSL User"), aCurrentDate, kSecReturnRef, kSecMatchLimitAll, 1, noErr)) ++result; if(aCurrentDate) CFRelease(aCurrentDate); - + // make a date in the past which should NOT match any identities (expect errSecItemNotFound) CFGregorianDate aPastGDate = { 1984, 7, 20, 12, 0, 0 }; // Jul 20 1984 12:00 PM CFDateRef aPastDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aPastGDate, NULL)); - if (FindIdentityByNameAndValidDate(CFSTR("Test SSL User"), aPastDate, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) + if (FindIdentityByNameAndValidDate(keychain, CFSTR("Test SSL User"), aPastDate, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) ++result; if(aPastDate) CFRelease(aPastDate); // make a date in the future which should NOT match any identities yet (expect errSecItemNotFound) CFGregorianDate aFutureGDate = { 2034, 7, 20, 12, 0, 0 }; // Jul 20 2034 12:00 PM CFDateRef aFutureDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aFutureGDate, NULL)); - if (FindIdentityByNameAndValidDate(CFSTR("Test SSL User"), aFutureDate, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) + if (FindIdentityByNameAndValidDate(keychain, CFSTR("Test SSL User"), aFutureDate, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) ++result; if(aFutureDate) CFRelease(aFutureDate); // make a date in the past which SHOULD match 2 identities we used to populate the keychain CFGregorianDate aPastValidGDate = { 2007, 12, 20, 12, 0, 0 }; // Dec 20 2007 12:00 PM CFDateRef aPastValidDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aPastValidGDate, NULL)); - if (FindIdentityByNameAndValidDate(CFSTR(" 2007"), aPastValidDate, kSecReturnRef, kSecMatchLimitAll, 0, noErr)) + if (FindIdentityByNameAndValidDate(keychain, CFSTR(" 2007"), aPastValidDate, kSecReturnRef, kSecMatchLimitAll, 0, noErr)) ++result; // test the ability of kCFNull to denote "currently valid" (should not find anything, since the " 2007" certs are expired) - if (FindIdentityByNameAndValidDate(CFSTR(" 2007"), kCFNull, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) + if (FindIdentityByNameAndValidDate(keychain, CFSTR(" 2007"), kCFNull, kSecReturnRef, kSecMatchLimitAll, 0, errSecItemNotFound)) ++result; - + // test Ian's bug: ; the 4th argument is a string which should NOT be present in any found items - if (FindIdentityByPolicyAndValidDate(kSecPolicyAppleSMIME, FALSE, kCFNull, CFSTR(" 2007"), kSecReturnAttributes, kSecMatchLimitAll, 0, noErr)) + if (FindIdentityByPolicyAndValidDate(keychain, kSecPolicyAppleSMIME, FALSE, kCFNull, CFSTR(" 2007"), kSecReturnAttributes, kSecMatchLimitAll, 0, errSecSuccess)) ++result; - + return result; } -int TestCertificateLookup() +static int TestCertificateLookup(SecKeychainRef keychain) { int result = 0; - + //====================================================================== // item attribute tests (kSecItemAttr* keys) //====================================================================== - + // %%%TBA: need to flesh out this section with all certificate attributes // ------------------------------------------ @@ -2872,7 +2832,7 @@ int TestCertificateLookup() // ------------------ // look up cert by label, want array of all results (expect only 1) as SecCertificateRef - result += FindCertificateByLabel(CFSTR("com.apple.kerberos.kdc"), + result += FindCertificateByLabel(keychain, CFSTR("Test-5685316-LEAF"), kSecReturnRef, kSecMatchLimitAll, 1, 1, noErr); @@ -2883,57 +2843,57 @@ int TestCertificateLookup() // ----------------------------------- // test kSecMatchEmailAddressIfPresent // ----------------------------------- - + // look up cert by email, want first result as a SecCertificateRef - result += FindCertificateByEmail(CFSTR("security-dev@group.apple.com"), + result += FindCertificateByEmail(keychain, CFSTR("security-dev@group.apple.com"), kSecReturnRef, kSecMatchLimitOne, 0, noErr); // look up cert by email, want first result as a CFDictionaryRef of attributes - result += FindCertificateByEmail(CFSTR("security-dev@group.apple.com"), + result += FindCertificateByEmail(keychain, CFSTR("security-dev@group.apple.com"), kSecReturnAttributes, kSecMatchLimitOne, 0, noErr); // ----------------------------- // test kSecMatchSubjectContains // ----------------------------- - // look up cert containing name, want array of all results (expect at least 3) as SecCertificateRef - result += FindCertificateByNameInSubject(CFSTR("Test-5685316"), + // look up cert containing name, want array of all results (expect at least 3) as SecCertificateRef + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-5685316"), kSecMatchSubjectContains, kSecReturnRef, kSecMatchLimitAll, 3, noErr); // look up non-existent cert by name, expect errSecItemNotFound error - result += FindCertificateByNameInSubject(CFSTR("myxlpytk"), + result += FindCertificateByNameInSubject(keychain, CFSTR("myxlpytk"), kSecMatchSubjectContains, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); // look up cert by name, want array of all results (expect at least 2) as CFDataRef - result += FindCertificateByNameInSubject(CFSTR("Test-5685316"), + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-5685316"), kSecMatchSubjectContains, kSecReturnData, kSecMatchLimitAll, 2, noErr); // look up cert by name, want array of all results (expect at least 2) as CFDictionaryRef of attributes - result += FindCertificateByNameInSubject(CFSTR("Test-5685316"), + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-5685316"), kSecMatchSubjectContains, kSecReturnAttributes, kSecMatchLimitAll, 2, noErr); // ------------------------------- // test kSecMatchSubjectStartsWith // ------------------------------- - // look up cert starting with name, want array of all results (expect at least 3) as SecCertificateRef - result += FindCertificateByNameInSubject(CFSTR("Test-568"), + // look up cert starting with name, want array of all results (expect at least 3) as SecCertificateRef + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-568"), kSecMatchSubjectStartsWith, kSecReturnRef, kSecMatchLimitAll, 3, noErr); // look up cert starting with a name which isn't at start, expect errSecItemNotFound error - result += FindCertificateByNameInSubject(CFSTR("5685316"), + result += FindCertificateByNameInSubject(keychain, CFSTR("5685316"), kSecMatchSubjectStartsWith, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); // ----------------------------- // test kSecMatchSubjectEndsWith // ----------------------------- - // look up cert ending with name, want array of all results (expect at least 1) as SecCertificateRef - result += FindCertificateByNameInSubject(CFSTR("LEAF"), + // look up cert ending with name, want array of all results (expect at least 1) as SecCertificateRef + result += FindCertificateByNameInSubject(keychain, CFSTR("LEAF"), kSecMatchSubjectEndsWith, kSecReturnRef, kSecMatchLimitAll, 1, noErr); // look up cert ending with a name which isn't at end, expect errSecItemNotFound error - result += FindCertificateByNameInSubject(CFSTR("Test-"), + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-"), kSecMatchSubjectEndsWith, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); // -------------------------------- @@ -2941,39 +2901,58 @@ int TestCertificateLookup() // -------------------------------- // look up cert by whole name, want first result (expecting 1) as a SecCertificateRef - result += FindCertificateByNameInSubject(CFSTR("Test-5685316-LEAF"), + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-5685316-LEAF"), kSecMatchSubjectWholeString, kSecReturnRef, kSecMatchLimitOne, 1, noErr); // look up cert by whole name (which is a substring in other certs), expect errSecItemNotFound error - result += FindCertificateByNameInSubject(CFSTR("Test-568"), + result += FindCertificateByNameInSubject(keychain, CFSTR("Test-568"), kSecMatchSubjectWholeString, kSecReturnRef, kSecMatchLimitOne, 0, errSecItemNotFound); // -------------------- // test kSecMatchPolicy // -------------------- + const void *keys[] = { kSecPolicyClient }; + const void *values[] = { kCFBooleanTrue }; + CFDictionaryRef properties = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + SecPolicyRef sslPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSSL, properties); + SecPolicyRef codeSigningPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleCodeSigning, NULL); + SecPolicyRef smimePolicy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, NULL); + // look up cert by name and policy (Code Signing), want first result as a SecCertificateRef - result += FindCertificateByNameAndPolicy(CFSTR("Test-7875801"), - kSecPolicyAppleCodeSigning, FALSE, - kSecReturnRef, kSecMatchLimitOne, 0, noErr); + result += FindCertificateByNameAndPolicy(keychain, CFSTR("Test-7875801"), + codeSigningPolicy, + kSecReturnRef, kSecMatchLimitOne, 1, noErr); // look up cert by name and policy (S/MIME), want first result as a SecCertificateRef - result += FindCertificateByNameAndPolicy(CFSTR("Test-"), - kSecPolicyAppleSMIME, FALSE, - kSecReturnRef, kSecMatchLimitOne, 0, noErr); + result += FindCertificateByNameAndPolicy(keychain, CFSTR("Test-"), + smimePolicy, + kSecReturnRef, kSecMatchLimitOne, 1, noErr); + + // look up cert by name and policy (SSL), want first result as a SecCertificateRef + result += FindCertificateByNameAndPolicy(keychain, CFSTR("Test "), + sslPolicy, + kSecReturnRef, kSecMatchLimitOne, 1, noErr); // look up cert by name and policy, want array of all results as SecCertificateRef - // (note that we expect an error here, since if all went well, there will be only 1 cert - // matching both name and policy parameters, but we asked for a minimum of 2 matches.) - result += FindCertificateByNameAndPolicy(CFSTR("Test-7875801"), - kSecPolicyAppleCodeSigning, FALSE, - kSecReturnAttributes, kSecMatchLimitAll, 2, errSecInternalError); - + result += FindCertificateByNameAndPolicy(keychain, CFSTR("Test-7875801"), + codeSigningPolicy, + kSecReturnAttributes, kSecMatchLimitAll, 1, noErr); + // look up cert by email address for SMIME encryption, date valid today, want array of all results as SecCertificateRef // (note that a date value of kCFNull is interpreted as the current date) - result += FindCertificateForSMIMEEncryption(CFSTR("smime-test@apple.com"), kCFNull, + result += FindCertificateForSMIMEEncryption(keychain, CFSTR("smime-test@apple.com"), kCFNull, kSecReturnRef, kSecMatchLimitAll, 1, noErr); + CFReleaseSafe(sslPolicy); + CFReleaseSafe(codeSigningPolicy); + CFReleaseSafe(smimePolicy); + CFReleaseSafe(properties); + // ------------------------- // test kSecMatchValidOnDate // ------------------------- @@ -2981,21 +2960,21 @@ int TestCertificateLookup() // make a valid date which will match at least 2 certificates we used to populate the keychain CFGregorianDate aCurrentGDate = { 2010, 7, 20, 12, 0, 0 }; // Jul 20 2010 12:00 PM CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); - if (FindCertificateByNameAndValidDate(CFSTR("Test-"), aCurrentDate, kSecReturnRef, kSecMatchLimitAll, 2, noErr)) + if (FindCertificateByNameAndValidDate(keychain, CFSTR("Test-"), aCurrentDate, kSecReturnRef, kSecMatchLimitAll, 2, noErr)) ++result; if(aCurrentDate) CFRelease(aCurrentDate); - + // make a date in the past which should NOT match any certificates (expect errSecItemNotFound) CFGregorianDate aPastGDate = { 1984, 7, 20, 12, 0, 0 }; // Jul 20 1984 12:00 PM CFDateRef aPastDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aPastGDate, NULL)); - if (FindCertificateByNameAndValidDate(CFSTR("Test-"), aPastDate, kSecReturnRef, kSecMatchLimitAll, 2, errSecItemNotFound)) + if (FindCertificateByNameAndValidDate(keychain, CFSTR("Test-"), aPastDate, kSecReturnRef, kSecMatchLimitAll, 2, errSecItemNotFound)) ++result; if(aPastDate) CFRelease(aPastDate); // make a date in the future which should NOT match any certificates yet (expect errSecItemNotFound) CFGregorianDate aFutureGDate = { 2034, 7, 20, 12, 0, 0 }; // Jul 20 2034 12:00 PM CFDateRef aFutureDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aFutureGDate, NULL)); - if (FindCertificateByNameAndValidDate(CFSTR("Test-"), aFutureDate, kSecReturnRef, kSecMatchLimitAll, 2, errSecItemNotFound)) + if (FindCertificateByNameAndValidDate(keychain, CFSTR("Test-"), aFutureDate, kSecReturnRef, kSecMatchLimitAll, 2, errSecItemNotFound)) ++result; if(aFutureDate) CFRelease(aFutureDate); @@ -3003,71 +2982,70 @@ int TestCertificateLookup() } -int TestPreferredIdentityLookup() +static int TestPreferredIdentityLookup(SecKeychainRef keychain) { int result = 0; - + // set a preferred identity first - if (SetPreferredIdentityForSMIMESigning(CFSTR("Test-SignOnly (S/MIME)"), CFSTR("smime-test@apple.com"))) + if (SetPreferredIdentityForSMIMESigning(keychain, CFSTR("Test-SignOnly (S/MIME)"), CFSTR("smime-test@apple.com"))) ++result; - + // define a valid date for this preferred identity (typically this would just be kCFNull in a real program, meaning "now") - CFGregorianDate aCurrentGDate = { 2010, 7, 27, 21, 0, 0 }; // Jul 27 2010 9:00 PM + CFGregorianDate aCurrentGDate = { 2016, 7, 27, 21, 0, 0 }; // Jul 27 2016 9:00 PM CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); - if (FindPreferredIdentityForSMIMESigning(CFSTR("smime-test@apple.com"), aCurrentDate)) + if (FindPreferredIdentityForSMIMESigning(keychain, CFSTR("smime-test@apple.com"), aCurrentDate)) ++result; if(aCurrentDate) CFRelease(aCurrentDate); // delete identity preference(s) for this email address by setting a NULL identity - if (SecIdentitySetPreferred(NULL, CFSTR("smime-test@apple.com"), 0) != noErr) - ++result; - + ok_status(SecIdentitySetPreferred(NULL, CFSTR("smime-test@apple.com"), 0), "TestPreferredIdentityLookup: SecIdentitySetPreferred"); + return result; } -int TestPreferredCertificateLookup() +static int TestPreferredCertificateLookup(SecKeychainRef keychain) { int result = 0; - + // set a preferred certificate first - if (SetPreferredCertificateForSMIMEEncryption(CFSTR("Test-Encryption (S/MIME)"), CFSTR("smime-test@apple.com"))) + if (SetPreferredCertificateForSMIMEEncryption(keychain, CFSTR("Test-Encryption (S/MIME)"), CFSTR("smime-test@apple.com"))) ++result; - + // define a valid date for this preferred certificate (typically this would just be kCFNull in a real program, meaning "now") - CFGregorianDate aCurrentGDate = { 2010, 7, 27, 21, 0, 0 }; // Jul 27 2010 9:00 PM + CFGregorianDate aCurrentGDate = { 2016, 7, 27, 21, 0, 0 }; // Jul 27 2016 9:00 PM CFDateRef aCurrentDate = CFDateCreate(kCFAllocatorDefault, CFGregorianDateGetAbsoluteTime(aCurrentGDate, NULL)); - if (FindPreferredCertificateForSMIMEEncryption(CFSTR("smime-test@apple.com"), aCurrentDate)) + if (FindPreferredCertificateForSMIMEEncryption(keychain, CFSTR("smime-test@apple.com"), aCurrentDate)) ++result; if(aCurrentDate) CFRelease(aCurrentDate); // delete certificate preference(s) for this email address by setting a NULL identity - if (SecCertificateSetPreferred(NULL, CFSTR("smime-test@apple.com"), 0) != noErr) - ++result; + ok_status(SecCertificateSetPreferred(NULL, CFSTR("smime-test@apple.com"), 0), "TestPreferredCertificateLookup: SecCertificateSetPreferred"); return result; } -int TestSymmetricKeyLookup() +static int TestSymmetricKeyLookup(SecKeychainRef keychain) { int result = 0; // look up our symmetric key by label and UUID (it might not exist yet) - if (FindSymmetricKey(gLabel, gUUID, NULL, errSecItemNotFound) != errSecSuccess) { + if (FindSymmetricKey(keychain, gLabel, gUUID, NULL, errSecItemNotFound) != errSecSuccess) { // create test key (unique by UUID only) - if (CreateSymmetricKey(gLabel, gUUID, NULL, errSecSuccess) != errSecSuccess) + if (CreateSymmetricKey(keychain, gLabel, gUUID, NULL, errSecSuccess) != errSecSuccess) ++result; // look it up again (it should exist now!) - if (FindSymmetricKey(gLabel, gUUID, NULL, errSecSuccess) != errSecSuccess) + if (FindSymmetricKey(keychain, gLabel, gUUID, NULL, errSecSuccess) != errSecSuccess) ++result; } - + // now look up a key whose name is derived from today's date // (so we can make sure on a daily basis that SecKeyGenerateSymmetric is still working) CFGregorianDate curGDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), NULL); CFStringRef curDateLabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%4d-%02d-%02d)"), - gPrefix, curGDate.year, curGDate.month, curGDate.day); + gPrefix, (int32_t) curGDate.year, (int8_t) curGDate.month, (int8_t) curGDate.day); + // //%%% FIXME Creating a symmetric key with attributes that would duplicate an existing // key item currently results in a broken key which can't be found: @@ -3076,17 +3054,17 @@ int TestSymmetricKeyLookup() CFStringRef curAppTag = CFSTR("SecItemFind"); // look up our date-based symmetric key by label, UUID, and tag (it might not exist yet) - if (FindSymmetricKey(curDateLabel, gUUID, curAppTag, errSecItemNotFound) != errSecSuccess) { + if (FindSymmetricKey(keychain, curDateLabel, gUUID, curAppTag, errSecItemNotFound) != errSecSuccess) { // create test key (unique by combination of UUID and application tag) - if (CreateSymmetricKey(curDateLabel, gUUID, curAppTag, errSecSuccess) != errSecSuccess) + if (CreateSymmetricKey(keychain, curDateLabel, gUUID, curAppTag, errSecSuccess) != errSecSuccess) ++result; // look it up again (it should exist now!) - if (FindSymmetricKey(curDateLabel, gUUID, curAppTag, errSecSuccess) != errSecSuccess) + if (FindSymmetricKey(keychain, curDateLabel, gUUID, curAppTag, errSecSuccess) != errSecSuccess) ++result; } // test handling of duplicate symmetric key items () - if (CreateSymmetricKey(curDateLabel, gUUID, curAppTag, errSecDuplicateItem) != errSecDuplicateItem) + if (CreateSymmetricKey(keychain, curDateLabel, gUUID, curAppTag, errSecDuplicateItem) != errSecDuplicateItem) ++result; CFRelease(curDateLabel); @@ -3095,50 +3073,50 @@ int TestSymmetricKeyLookup() } -int TestInternetPasswordLookup() +static int TestInternetPasswordLookup(SecKeychainRef keychain) { int result = 0; // look up internet password by account and server, want first result as data - if (FindInternetPasswordByAccountAndServer(CFSTR("nobody"), + if (FindInternetPasswordByAccountAndServer(keychain, CFSTR("nobody"), CFSTR("test2.subdomain.apple.com"), kSecReturnData, kSecMatchLimitOne, 1, noErr)) ++result; // look up internet password by account and server, want dictionary of the item's attributes - if (FindInternetPasswordByAccountAndServer(CFSTR("nobody"), + if (FindInternetPasswordByAccountAndServer(keychain, CFSTR("nobody"), CFSTR("test2.subdomain.apple.com"), kSecReturnAttributes, kSecMatchLimitOne, 1, noErr)) ++result; // look up internet passwords by account, want array of SecKeychainItemRef results - if (FindInternetPasswordByAccount(CFSTR("nobody"), + if (FindInternetPasswordByAccount(keychain, CFSTR("nobody"), kSecReturnRef, kSecMatchLimitAll, 1, noErr)) ++result; - + // look up a Mail password for an IMAP account, replacing SecKeychainFindInternetPassword // (see ) - if (FindMailPassword(CFSTR("testacct"), CFSTR("mail.apple.com"))) + if (FindMailPassword(keychain, CFSTR("testacct"), CFSTR("mail.apple.com"))) ++result; return result; } -int TestGenericPasswordLookup() +static int TestGenericPasswordLookup(SecKeychainRef keychain) { int result = 0; // look up generic password by account and service, want first result as data - if (FindGenericPasswordByAccountAndService(CFSTR("nobody"), + if (FindGenericPasswordByAccountAndService(keychain, CFSTR("nobody"), CFSTR("Test Service 42"), kSecReturnData, kSecMatchLimitOne, 1, noErr)) ++result; // look up generic password by account and service, dictionary of the item's attributes - if (FindGenericPasswordByAccountAndService(CFSTR("nobody"), + if (FindGenericPasswordByAccountAndService(keychain, CFSTR("nobody"), CFSTR("Test Service 42"), kSecReturnAttributes, kSecMatchLimitOne, 1, noErr)) ++result; // look up generic passwords by account, want array of SecKeychainItemRef results - if (FindGenericPasswordByAccount(CFSTR("nobody"), + if (FindGenericPasswordByAccount(keychain, CFSTR("nobody"), kSecReturnRef, kSecMatchLimitAll, 1, noErr)) ++result; @@ -3146,7 +3124,7 @@ int TestGenericPasswordLookup() } -int TestUpdateItems() +static int TestUpdateItems(SecKeychainRef keychain) { int result = 0; @@ -3163,7 +3141,7 @@ int TestUpdateItems() CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA ); CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); -// CFDictionaryAddValue( params, kSecUseKeychain, keychain ); + CFDictionaryAddValue( params, kSecUseKeychain, keychain ); // CFDictionaryAddValue( params, kSecAttrAccess, access ); // %%% note that SecKeyGeneratePair will create the key pair in the default keychain // if a keychain is not given via the kSecUseKeychain parameter. @@ -3172,7 +3150,7 @@ int TestUpdateItems() ++result; } PrintTestResult("TestUpdateItems: generating key pair", status, noErr); - + // create a query which will match just the private key item (based on its known reference) CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, @@ -3184,6 +3162,10 @@ int TestUpdateItems() // CFDictionaryAddValue( query, kSecAttrKeyClass, kSecAttrKeyClassPrivate ); CFDictionaryAddValue( query, kSecMatchItemList, itemList ); + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + // create dictionary of changed attributes for the private key CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, @@ -3227,133 +3209,87 @@ int TestUpdateItems() } -int TestDeleteItems() +static int TestDeleteItems(SecKeychainRef keychain) { int result = 0; - + // delete our 3 test certificates that start with "Test-5685316-" - if (FindAndDeleteItemsByName(CFSTR("Test-5685316-"), NULL, kSecClassCertificate, kSecMatchLimitAll, 3, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test-5685316-"), NULL, kSecClassCertificate, kSecMatchLimitAll, 3, noErr)) ++result; - + // delete our 2 test identities that start with "Test Identity S" (fixed by ) - if (FindAndDeleteItemsByName(CFSTR("Test Identity S"), NULL, kSecClassIdentity, kSecMatchLimitAll, 2, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test Identity S"), NULL, kSecClassIdentity, kSecMatchLimitAll, 2, noErr)) ++result; // delete the "Test-SignOnly (S/MIME)" identity - if (FindAndDeleteItemsByName(CFSTR("Test-SignOnly (S/MIME)"), NULL, kSecClassIdentity, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test-SignOnly (S/MIME)"), NULL, kSecClassIdentity, kSecMatchLimitAll, 1, noErr)) ++result; // delete the "Test-Encryption (S/MIME)" certificate - if (FindAndDeleteItemsByName(CFSTR("Test-Encryption (S/MIME)"), NULL, kSecClassCertificate, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test-Encryption (S/MIME)"), NULL, kSecClassCertificate, kSecMatchLimitAll, 1, noErr)) ++result; // delete the "Test-7875801 (Code Signing)" certificate - if (FindAndDeleteItemsByName(CFSTR("Test-7875801 (Code Signing)"), NULL, kSecClassCertificate, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test-7875801 (Code Signing)"), NULL, kSecClassCertificate, kSecMatchLimitAll, 1, noErr)) ++result; - + // delete our test passwords (no partial string matching for password items! need an ER Radar...) - if (FindAndDeleteItemsByName(CFSTR("Test Service 42"), NULL, kSecClassGenericPassword, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test Service 42"), NULL, kSecClassGenericPassword, kSecMatchLimitAll, 1, noErr)) ++result; - if (FindAndDeleteItemsByName(CFSTR("Test Service 69"), NULL, kSecClassGenericPassword, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("Test Service 69"), NULL, kSecClassGenericPassword, kSecMatchLimitAll, 1, noErr)) ++result; - if (FindAndDeleteItemsByName(CFSTR("test1.subdomain.apple.com"), NULL, kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("test1.subdomain.apple.com"), NULL, kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) ++result; - if (FindAndDeleteItemsByName(CFSTR("test2.subdomain.apple.com"), NULL, kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("test2.subdomain.apple.com"), NULL, kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) ++result; - if (FindAndDeleteItemsByName(CFSTR("mail.apple.com"), CFSTR("testacct"), kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("mail.apple.com"), CFSTR("testacct"), kSecClassInternetPassword, kSecMatchLimitAll, 1, noErr)) ++result; // delete our test symmetric keys (no partial string matching for key items! need an ER Radar...) - if (FindAndDeleteItemsByName(gLabel, NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, gLabel, NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) ++result; CFGregorianDate curGDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), NULL); CFStringRef curDateLabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@ (%4d-%02d-%02d)"), - gPrefix, curGDate.year, curGDate.month, curGDate.day); - if (FindAndDeleteItemsByName(curDateLabel, NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + gPrefix, (int32_t) curGDate.year, (int8_t) curGDate.month, (int8_t) curGDate.day); + if (FindAndDeleteItemsByName(keychain, curDateLabel, NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) ++result; CFRelease(curDateLabel); // delete our test asymmetric key pair (remember we renamed the private key...) - if (FindAndDeleteItemsByName(CFSTR("AppleID 8658820 test key"), NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("AppleID 8658820 test key"), NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) ++result; - if (FindAndDeleteItemsByName(CFSTR("AppleID 8658820 test PRIVATE key"), NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) + if (FindAndDeleteItemsByName(keychain, CFSTR("AppleID 8658820 test PRIVATE key"), NULL, kSecClassKey, kSecMatchLimitAll, 1, noErr)) ++result; return result; } -void usage(const char *arg0) +int kc_18_find_combined (int argc, char *const *argv) { - fprintf(stdout, "Usage: %s [-q] [-d]\n", arg0); - fprintf(stdout, "Options:\n"); - fprintf(stdout, " -q : (quiet) suppress output of pass/fail lines\n"); - fprintf(stdout, " -d : (debug) show debug output\n"); -} + plan_tests(167); + printf("Getting -25308 or -25293? Try unlocking your default keychain; that's where identity and certificate preferences are stored (with no other option).\n"); -int main (int argc, const char * argv[]) -{ - int n, i, c, e; - - /* validate arguments */ - if (argc > 3) - { - usage(argv[0]); - exit(1); - } - - for (i=1; i #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" -void tests(int dont_skip) +static void tests() { SecKeychainRef source, dest; - ok_status(SecKeychainCreate("source", 4, "test", FALSE, NULL, &source), - "create source keychain"); - ok_status(SecKeychainCreate("dest", 4, "test", FALSE, NULL, &dest), - "create dest keychain"); + source = createNewKeychain("source", "test"); + dest = createNewKeychain("dest", "test"); SecKeychainItemRef original = NULL; ok_status(SecKeychainAddInternetPassword(source, 19, "members.spamcop.net", @@ -60,22 +57,17 @@ void tests(int dont_skip) is(origAttrs[0].length, copyAttrs[0].length, "creation date length same"); is(origAttrs[1].length, copyAttrs[1].length, "mod date length same"); - TODO: { - todo(" Moving/copying a keychain item " - "between keychains erroneously updates dates"); + diag("original creation: %.*s copy creation: %.*s", + (int)origAttrs[0].length, (const char *)origAttrs[0].data, + (int)copyAttrs[0].length, (const char *)copyAttrs[0].data); + ok(!memcmp(origAttrs[0].data, copyAttrs[0].data, origAttrs[0].length), + "creation date same"); - diag("original creation: %.*s copy creation: %.*s", - (int)origAttrs[0].length, (const char *)origAttrs[0].data, - (int)copyAttrs[0].length, (const char *)copyAttrs[0].data); - ok(!memcmp(origAttrs[0].data, copyAttrs[0].data, origAttrs[0].length), - "creation date same"); - - diag("original mod: %.*s copy mod: %.*s", - (int)origAttrs[1].length, (const char *)origAttrs[1].data, - (int)copyAttrs[1].length, (const char *)copyAttrs[1].data); - ok(!memcmp(origAttrs[1].data, copyAttrs[1].data, origAttrs[1].length), - "mod date same"); - } + diag("original mod: %.*s copy mod: %.*s", + (int)origAttrs[1].length, (const char *)origAttrs[1].data, + (int)copyAttrs[1].length, (const char *)copyAttrs[1].data); + ok(!memcmp(origAttrs[1].data, copyAttrs[1].data, origAttrs[1].length), + "mod date same"); ok_status(SecKeychainItemFreeContent(&origAttrList, NULL), "SecKeychainItemCopyContent"); @@ -92,21 +84,14 @@ void tests(int dont_skip) ok_status(SecKeychainDelete(dest), "delete keychain dest"); is(CFGetRetainCount(dest), 1, "dest retaincount is 1"); CFRelease(dest); - - ok(tests_end(1), "cleanup"); } -int main(int argc, char *const *argv) +int kc_19_item_copy_internet(int argc, char *const *argv) { - int dont_skip = argc > 1 && !strcmp(argv[1], "-s"); - - plan_tests(22); - - if (!tests_begin(argc, argv)) - BAIL_OUT("tests_begin failed"); + plan_tests(20); - tests(dont_skip); - ok_leaks("no leaks"); + tests(); + deleteTestFiles(); return 0; } diff --git a/OSX/libsecurity_keychain/regressions/kc-20-identity-find-stress.c b/OSX/libsecurity_keychain/regressions/kc-20-identity-find-stress.c new file mode 100644 index 00000000..88fbfb69 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-20-identity-find-stress.c @@ -0,0 +1,87 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-identity-helpers.h" + +#include +#include + +#define BLOCKS 7000 + +static void tests() { + + SecKeychainRef kc = getPopulatedTestKeychain(); + + SecIdentityRef identity = NULL; + SecCertificateRef certRef = NULL; + SecKeyRef keyRef = NULL; + + identity = copyFirstIdentity(kc); + ok_status(SecIdentityCopyCertificate(identity, &certRef), "%s: SecIdentityCopyCertificate", testName); + ok_status(SecIdentityCopyPrivateKey(identity, &keyRef), "%s: SecIdentityCopyPrivateKey", testName); + + CFReleaseNull(identity); + CFReleaseNull(keyRef); + + static dispatch_once_t onceToken = 0; + static dispatch_queue_t release_queue = NULL; + dispatch_once(&onceToken, ^{ + release_queue = dispatch_queue_create("com.apple.security.identity-search-queue", DISPATCH_QUEUE_CONCURRENT); + }); + dispatch_group_t g = dispatch_group_create(); + + for(int i = 0; i < BLOCKS; i++) { + dispatch_group_async(g, release_queue, ^() { + SecIdentityRef blockId = NULL; + SecKeyRef blockKeyRef = NULL; + + ok_status(SecIdentityCreateWithCertificate(kc, certRef, &blockId), "%s: SecIdentityCreateWithCertificate", testName); + ok_status(SecIdentityCopyPrivateKey(blockId, &blockKeyRef), "%s: SecIdentityCopyPrivateKey", testName); + + CFReleaseNull(blockKeyRef); + CFReleaseNull(blockId); + }); + } + + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + CFReleaseNull(certRef); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); +} + +int kc_20_identity_find_stress(int argc, char *const *argv) +{ + plan_tests(2*BLOCKS + 6); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-20-identity-key-attributes.c b/OSX/libsecurity_keychain/regressions/kc-20-identity-key-attributes.c new file mode 100644 index 00000000..6b9c3d1c --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-20-identity-key-attributes.c @@ -0,0 +1,101 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-identity-helpers.h" + + +// Example of looking up a SecIdentityRef in the keychain, +// then getting the attributes of its private key. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static void PrintPrivateKeyAttributes(SecKeyRef keyRef) +{ + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query: find specified item, return attributes */ + //CFDictionaryAddValue( query, kSecClass, kSecClassKey ); + CFDictionaryAddValue( query, kSecValueRef, keyRef ); + CFDictionaryAddValue( query, kSecReturnAttributes, kCFBooleanTrue ); + + CFTypeRef result = NULL; + OSStatus status = SecItemCopyMatching(query, &result); + ok_status(status, "%s: SecItemCopyMatching", testName); + + if (query) + CFRelease(query); + + if(result) { + CFShow(result); + } +} + +static void tests(SecKeychainRef kc) +{ + SecIdentityRef identity=NULL; + SecKeyRef privateKeyRef=NULL; + OSStatus status; + + identity = copyFirstIdentity(kc); + status = SecIdentityCopyPrivateKey(identity, &privateKeyRef); + ok_status(status, "%s: SecIdentityCopyPrivateKey", testName); + + if (privateKeyRef) { + PrintPrivateKeyAttributes(privateKeyRef); + CFRelease(privateKeyRef); + } + CFReleaseNull(identity); +} + +int kc_20_identity_key_attributes(int argc, char *const *argv) +{ + plan_tests(6); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + tests(kc); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-20-identity-persistent-refs.c b/OSX/libsecurity_keychain/regressions/kc-20-identity-persistent-refs.c new file mode 100644 index 00000000..c70b56f6 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-20-identity-persistent-refs.c @@ -0,0 +1,174 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +// Tests the ability of SecItemCopyMatching to return a persistent ref for either a +// SecIdentityRef or a SecCertificateRef which happens to be part of an identity, +// then reconstitute the appropriate type of ref from the persistent reference. +// + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "kc-identity-helpers.h" + +#define MAXNAMELEN MAXPATHLEN +#define MAXITEMS INT32_MAX + +static CFDataRef +copyPersistentReferenceForItem(CFTypeRef item) +{ + // Given either a SecIdentityRef or SecCertificateRef item reference, + // return a persistent reference. Caller must release the reference. + + OSStatus status; + CFDataRef persistentRef = NULL; + CFDictionaryRef query = NULL; + + const void *keys[] = { kSecReturnPersistentRef, kSecValueRef }; + const void *values[] = { kCFBooleanTrue, item }; + + query = CFDictionaryCreate(NULL, keys, values, + (sizeof(keys) / sizeof(*keys)), NULL, NULL); + status = SecItemCopyMatching(query, (CFTypeRef *)&persistentRef); + ok_status(status, "%s: SecItemCopyMatching (copyPersistentReferenceForItem)", testName); + CFRelease(query); + return persistentRef; +} + +static CFTypeRef +copyItemForPersistentReference(CFDataRef persistentRef) +{ + // Given a persistent reference, reconstitute it into an item + // reference. Depending on whether the persistent reference was + // originally made to a SecIdentityRef or SecCertificateRef, this + // should return the same item type as the original. + // Caller must release the reference. + + OSStatus status; + CFTypeRef itemRef = NULL; + CFDictionaryRef query = NULL; + const void *keys[] = { kSecReturnRef, kSecValuePersistentRef }; + const void *values[] = { kCFBooleanTrue, persistentRef }; + + query = CFDictionaryCreate(NULL, keys, values, + (sizeof(keys) / sizeof(*keys)), NULL, NULL); + status = SecItemCopyMatching(query, &itemRef); + ok_status(status, "%s: SecItemCopyMatching (copyItemForPersistentReference)", testName); + CFRelease(query); + return itemRef; +} + +static void +testIdentityPersistence(SecKeychainRef kc) +{ + startTest(__FUNCTION__); + + // Step 1: get a SecIdentityRef + SecIdentityRef identity = copyFirstIdentity(kc); + is(CFGetTypeID(identity), SecIdentityGetTypeID(), "%s: retrieved identity is an identity", testName); + + // Step 2: make a persistent reference for it + CFDataRef data = copyPersistentReferenceForItem((CFTypeRef)identity); + + // Step 3: reconstitute the persistent reference + SecIdentityRef identity2 = (SecIdentityRef) copyItemForPersistentReference(data); + CFReleaseNull(data); + + ok(identity2, "%s: retrieved an identity", testName); + if(identity2) { + is(CFGetTypeID(identity2), SecIdentityGetTypeID(), "%s: retrieved identity is an identity", testName); + } else { + fail("%s: no identity to test", testName); + } + eq_cf(identity2, identity, "%s: identities are equal", testName); + + CFReleaseNull(identity); + CFReleaseNull(identity2); +} + +static void +testCertificatePersistence(SecKeychainRef kc) +{ + startTest(__FUNCTION__); + + // Step 1: get a SecIdentityRef + SecIdentityRef identity = copyFirstIdentity(kc); + + // Step 2: get a SecCertificateRef from it + SecCertificateRef cert = NULL, cert2 = NULL; + OSStatus status = SecIdentityCopyCertificate(identity, &cert); + ok_status(status, "%s: SecIdentityCopyCertificate", testName); + ok(cert, "%s: No certificate returned from SecIdentityCopyCertificate", testName); + CFReleaseNull(identity); + + // Step 3: make a persistent reference for it + CFDataRef data = (CFDataRef) copyPersistentReferenceForItem(cert); + + // Step 4: reconstitute the persistent reference + cert2 = (SecCertificateRef) copyItemForPersistentReference(data); + + ok(cert2, "%s: retrieved a certificate", testName); + if(cert2) { + is(CFGetTypeID(cert2), SecCertificateGetTypeID(), "%s: returned value is a certificate", testName); + } else { + fail("%s: no certificate to test", testName); + } + + eq_cf(cert2, cert, "%s: Certificates are equal", testName); + + CFReleaseNull(data); + CFReleaseNull(cert); + CFReleaseNull(cert2); +} + +int kc_20_identity_persistent_refs(int argc, char *const *argv) +{ + plan_tests(18); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + // You cannot reconsitute a Persistent Reference for an identity if the keychain is not in the search list. + addToSearchList(kc); + + testCertificatePersistence(kc); + testIdentityPersistence(kc); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-20-item-find-stress.c b/OSX/libsecurity_keychain/regressions/kc-20-item-find-stress.c new file mode 100644 index 00000000..7f044612 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-20-item-find-stress.c @@ -0,0 +1,75 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" + +#include +#include + +#define BLOCKS 7000 + +static void tests() { + + SecKeychainRef kc = getPopulatedTestKeychain(); + + static dispatch_once_t onceToken = 0; + static dispatch_queue_t release_queue = NULL; + dispatch_once(&onceToken, ^{ + release_queue = dispatch_queue_create("com.apple.security.identity-search-queue", DISPATCH_QUEUE_CONCURRENT); + }); + dispatch_group_t g = dispatch_group_create(); + + for(int i = 0; i < BLOCKS; i++) { + dispatch_group_async(g, release_queue, ^() { + SecKeychainItemRef blockItem = NULL; + + CFMutableDictionaryRef query = makeQueryCustomItemDictionaryWithService(kc, kSecClassInternetPassword, CFSTR("test_service"), CFSTR("test_service")); + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + + ok_status(SecItemCopyMatching(query, (CFTypeRef*) &blockItem), "%s: SecItemCopyMatching(%d)", testName, i); + + CFReleaseNull(blockItem); + }); + } + + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); +} + +int kc_20_item_find_stress(int argc, char *const *argv) +{ + plan_tests((1)*BLOCKS + getPopulatedTestKeychainTests + 1); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-20-key-find-stress.c b/OSX/libsecurity_keychain/regressions/kc-20-key-find-stress.c new file mode 100644 index 00000000..334de5d7 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-20-key-find-stress.c @@ -0,0 +1,75 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-key-helpers.h" + +#include +#include + +#define BLOCKS 7000 + +static void tests() { + + SecKeychainRef kc = getPopulatedTestKeychain(); + + static dispatch_once_t onceToken = 0; + static dispatch_queue_t release_queue = NULL; + dispatch_once(&onceToken, ^{ + release_queue = dispatch_queue_create("com.apple.security.identity-search-queue", DISPATCH_QUEUE_CONCURRENT); + }); + dispatch_group_t g = dispatch_group_create(); + + for(int i = 0; i < BLOCKS; i++) { + dispatch_group_async(g, release_queue, ^() { + SecKeychainItemRef blockItem = NULL; + + CFMutableDictionaryRef query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric); + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + + ok_status(SecItemCopyMatching(query, (CFTypeRef*) &blockItem), "%s: SecItemCopyMatching(%d)", testName, i); + + CFReleaseNull(blockItem); + }); + } + + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); +} + +int kc_20_key_find_stress(int argc, char *const *argv) +{ + plan_tests((1)*BLOCKS + 3); + initializeKeychainTests(__FUNCTION__); + + tests(); + + deleteTestFiles(); + return 0; +} diff --git a/SecurityTests/regressions/kc/kc-21-item-use-callback.c b/OSX/libsecurity_keychain/regressions/kc-21-item-use-callback.c similarity index 54% rename from SecurityTests/regressions/kc/kc-21-item-use-callback.c rename to OSX/libsecurity_keychain/regressions/kc-21-item-use-callback.c index 3d522600..808c93ab 100644 --- a/SecurityTests/regressions/kc/kc-21-item-use-callback.c +++ b/OSX/libsecurity_keychain/regressions/kc-21-item-use-callback.c @@ -1,16 +1,15 @@ #include #include #include -#include #include -#include "testmore.h" -#include "testenv.h" -#include "testleaks.h" +#include "keychain_regressions.h" +#include "kc-helpers.h" static char account[] = "account"; static char service[] = "service"; static char password[] = "password"; +static bool callbackCalled = false; static void checkContent(SecKeychainItemRef itemRef) { @@ -28,25 +27,13 @@ static void checkContent(SecKeychainItemRef itemRef) UInt32 length; void *data; -#if 1 ok_status(SecKeychainItemCopyContent(itemRef, &itemClass, &attrList, &length, &data), "get item data in callback"); - SKIP: { - skip("length mismatch", 1, - is(length, sizeof(password), " " - "SecKeychainItemCopyContent() returns bad data on items " - "from notifications")); - - ok(!memcmp(password, data, length), "password data matches."); - } -#else - if (length != sizeof(password) || memcmp(password, data, length)) - { - fprintf(stderr, "password '%.*s' not same as '%.*s'\n", - (int)sizeof(password), password, - (int)length, (char *)data); - } -#endif + is(length, sizeof(password), " " + "SecKeychainItemCopyContent() returns bad data on items " + "from notifications"); + + ok(!memcmp(password, data, length), "password data matches."); ok_status(SecKeychainItemFreeContent(&attrList, data), "free item data in callback"); @@ -55,31 +42,35 @@ static void checkContent(SecKeychainItemRef itemRef) static OSStatus callbackFunction(SecKeychainEvent keychainEvent, SecKeychainCallbackInfo *info, void *context) { - assert(keychainEvent == kSecAddEvent && context != NULL); - assert(info != NULL); - assert(info->item != NULL); + is(keychainEvent, kSecAddEvent, "Got an incorrect keychain event"); + ok(context != NULL, "context is null"); + ok(info != NULL, "info is NULL"); + ok(info->item != NULL, "info-item); *((UInt32 *)context) = 1; ok_status(SecKeychainItemDelete(info->item), "delete item"); + + // We processed an item, quit the run loop + callbackCalled = true; + CFRunLoopStop(CFRunLoopGetCurrent()); return 0; } int -main(int argc, char *const *argv) +kc_21_item_use_callback(int argc, char *const *argv) { - plan_tests(6); + plan_tests(14); - ok(tests_begin(argc, argv), "setup"); + // Run the CFRunLoop to clear out existing notifications + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, false); UInt32 didGetNotification = 0; ok_status(SecKeychainAddCallback(callbackFunction, kSecAddEventMask, &didGetNotification), "add callback"); - SecKeychainRef keychain; - ok_status(SecKeychainCreate("test", 4, "test", FALSE, NULL, &keychain), - "create keychain"); + SecKeychainRef keychain = createNewKeychain("test", "test"); SecKeychainItemRef itemRef; ok_status(SecKeychainAddGenericPassword(keychain, sizeof(account), account, @@ -87,16 +78,16 @@ main(int argc, char *const *argv) sizeof(password), password, &itemRef), "add generic password, release and wait for callback"); - //checkContent(itemRef); + + // Run the CFRunLoop to process events (and call our callback) + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10.0, false); + is(callbackCalled, true, "Keychain callback function was not called or did not finish"); + CFRelease(itemRef); - CFRelease(keychain); - if (argc > 1 && !strcmp(argv[1], "-l")) { - printf("pid: %d\n", getpid()); - sleep(100); - } - ok(tests_end(1), "cleanup"); - ok_leaks("leaks"); + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFRelease(keychain); + deleteTestFiles(); return 0; } diff --git a/OSX/libsecurity_keychain/regressions/kc-21-item-xattrs.c b/OSX/libsecurity_keychain/regressions/kc-21-item-xattrs.c new file mode 100644 index 00000000..5628d9cf --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-21-item-xattrs.c @@ -0,0 +1,404 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-keychain-file-helpers.h" +#include "test/testenv.h" +// +// testKeychainXattrs.c +// +// Basic test of SecKeychainItemExtendedAttributes functionality +// to store arbitrary data in the extended attributes of a keychain +// item. +// + +#include +#include +#include +#include /* private */ + +#include +#include +#include +#include +#include +#include + +static int TestAddItems(SecKeychainRef keychain) +{ + int result = 0; + OSStatus status; + SecKeychainItemRef item = NULL; + CFDataRef blob = NULL; + + /* add generic password item */ + status = SecKeychainAddGenericPassword(keychain, + strlen("Test Cloud Service 42"), "Test Cloud Service 42", + strlen("nobody"), "nobody", + strlen("weakpass"), "weakpass", + &item); + ok_status(status, "%s: SecKeychainAddGenericPassword", testName); + + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + result++; + } + /* add an extended CFDataRef attribute to this item */ + UInt8 buf1[6] = { 's', 'e', 'c', 'r', 'e', 't' }; + blob = CFDataCreate(NULL, buf1, sizeof(buf1)); + status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), blob); + ok_status(status, "%s: SecKeychainItemSetExtendedAttribute (generic)", testName); + + if (status) { + result++; + } + if (blob) { + CFRelease(blob); + blob = NULL; + } + if (item) { + CFRelease(item); + item = NULL; + } + + /* add internet password item */ + status = SecKeychainAddInternetPassword(keychain, + strlen("test42.icloud.com"), "test42.icloud.com", + 0, NULL, + strlen("nobody"), "nobody", + 0, NULL, + 80, kSecProtocolTypeHTTP, kSecAuthenticationTypeDefault, + strlen("weakpass"), "weakpass", + &item); + ok_status(status, "%s: SecKeychainAddInternetPassword", testName); + if (status && status != errSecDuplicateItem) { // ignore error if duplicate + result++; + } + /* add an extended CFDataRef attribute to this item */ + UInt8 buf2[5] = { 'm', 'a', 'g', 'i', 'c' }; + blob = CFDataCreate(NULL, buf2, sizeof(buf2)); + status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), blob); + ok_status(status, "%s: SecKeychainItemSetExtendedAttribute (internet)", testName); + + if (status) { + result++; + } + if (blob) { + CFRelease(blob); + blob = NULL; + } + if (item) { + CFRelease(item); + item = NULL; + } + + + return result; +} + +static int TestFindItems(SecKeychainRef keychain) +{ + int result = 0; + + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + + /* find generic password we added previously */ + { + const void *keys[] = { + kSecMatchSearchList, + kSecClass, + kSecAttrAccount, + kSecAttrService, + kSecMatchLimit, + kSecReturnRef + }; + const void *values[] = { + searchList, + kSecClassGenericPassword, + CFSTR("nobody"), + CFSTR("Test Cloud Service 42"), + kSecMatchLimitOne, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + status = SecItemCopyMatching(query, &results); + ok_status(status, "%s: SecItemCopyMatching (generic password)", testName); + + if (status) { + fprintf(stderr, "Unable to find \"Test Cloud Service 42\" generic password: error %d\n", (int)status); + result++; + } + if (results) { + /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */ + SecKeychainItemRef item = (SecKeychainItemRef) results; + CFDataRef blob = NULL; + status = SecKeychainItemCopyExtendedAttribute(item, CFSTR("CloudyGoodness"), &blob); + ok_status(status, "%s: SecKeychainItemCopyExtendedAttribute", testName); + + if (status) { + fprintf(stderr, "Unable to retrieve xattr from \"Test Cloud Service 42\" generic password: error %d\n", (int)status); + result++; + } + else { + const UInt8 *dataPtr = CFDataGetBytePtr(blob); + + eq_stringn( (const char *) dataPtr, strlen((const char *)dataPtr), "secret", strlen("secret"), "%s: Retrieved xattr value matches expected value", testName); + if (memcmp(dataPtr, "secret", strlen("secret"))) { + result++; + } + } + if (blob) { + CFRelease(blob); + } + CFRelease(results); + } + if (query) { + CFRelease(query); + } + } + + /* find internet password we added previously */ + { + const void *keys[] = { + kSecMatchSearchList, + kSecClass, + kSecAttrAccount, + kSecAttrServer, + kSecMatchLimit, + kSecReturnRef + }; + const void *values[] = { + searchList, + kSecClassInternetPassword, + CFSTR("nobody"), + CFSTR("test42.icloud.com"), + kSecMatchLimitOne, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + status = SecItemCopyMatching(query, &results); + ok_status(status, "%s: SecItemCopyMatching (internet password)", testName); + if (status) { + fprintf(stderr, "Unable to find \"test42.icloud.com\" internet password: error %d\n", (int)status); + result++; + } + if (results) { + /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */ + SecKeychainItemRef item = (SecKeychainItemRef) results; + CFDataRef blob = NULL; + status = SecKeychainItemCopyExtendedAttribute(item, CFSTR("CloudyGoodness"), &blob); + ok_status(status, "%s: SecKeychainItemCopyExtendedAttribute", testName); + if (status) { + fprintf(stderr, "Unable to retrieve xattr from \"test42.icloud.com2\" internet password: error %d\n", (int)status); + result++; + } + else { + const UInt8 *dataPtr = CFDataGetBytePtr(blob); + eq_stringn( (const char *) dataPtr, strlen((const char *)dataPtr), "magic", strlen("magic"), "%s: Retrieved xattr value matches expected value", testName); + + if (memcmp(dataPtr, "magic", strlen("magic"))) { + fprintf(stderr, "Retrieved xattr value did not match expected value!\n"); + result++; + } + } + if (blob) { + CFRelease(blob); + } + CFRelease(results); + } + if (query) { + CFRelease(query); + } + } + + return result; +} + +static int TestDeleteItems(SecKeychainRef keychain) +{ + int result = 0; + + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, keychain); + + /* find generic password we added previously */ + { + const void *keys[] = { + kSecMatchSearchList, + kSecClass, + kSecAttrAccount, + kSecAttrService, + kSecMatchLimit, + kSecReturnRef + }; + const void *values[] = { + searchList, + kSecClassGenericPassword, + CFSTR("nobody"), + CFSTR("Test Cloud Service 42"), + kSecMatchLimitOne, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + status = SecItemCopyMatching(query, &results); + ok_status(status, "%s: SecItemCopyMatching (Test Cloud Service 42)", testName); + + if (status) { + fprintf(stderr, "Unable to find \"Test Cloud Service 42\" generic password: error %d\n", (int)status); + result++; + } + if (results) { + /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */ + SecKeychainItemRef item = (SecKeychainItemRef) results; + + /* set the xattr to NULL in order to delete it */ + status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), NULL); + ok_status( status, "%s: SecKeychainItemSetExtendedAttribute (generic password, null data)", testName); + + if (status) { + fprintf(stderr, "Unable to remove xattr from \"Test Cloud Service 42\" generic password: error %d\n", (int)status); + result++; + } + + /* delete the item itself */ + status = SecKeychainItemDelete(item); + ok_status(status, "%s: SecKeychainItemDelete (generic password)", testName); + + if (status) { + fprintf(stderr, "Unable to delete \"Test Cloud Service 42\" generic password: error %d\n", (int)status); + result++; + } + + CFRelease(results); + } + if (query) { + CFRelease(query); + } + } + + /* find internet password we added previously */ + { + const void *keys[] = { + kSecMatchSearchList, + kSecClass, + kSecAttrAccount, + kSecAttrServer, + kSecMatchLimit, + kSecReturnRef + }; + const void *values[] = { + searchList, + kSecClassInternetPassword, + CFSTR("nobody"), + CFSTR("test42.icloud.com"), + kSecMatchLimitOne, + kCFBooleanTrue + }; + + OSStatus status = noErr; + CFTypeRef results = NULL; + CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, + sizeof(keys) / sizeof(*keys), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + status = SecItemCopyMatching(query, &results); + ok_status(status, "%s: SecItemCopyMatching (test42.icloud.com)", testName); + + if (status) { + fprintf(stderr, "Unable to find \"test42.icloud.com\" internet password: error %d\n", (int)status); + result++; + } + if (results) { + /* found the item; since we asked for one item and a ref, this is a SecKeychainItemRef */ + SecKeychainItemRef item = (SecKeychainItemRef) results; + + /* set the xattr to NULL in order to delete it */ + status = SecKeychainItemSetExtendedAttribute(item, CFSTR("CloudyGoodness"), NULL); + ok_status( status, "%s: SecKeychainItemSetExtendedAttribute (internet password, null data)", testName); + + if (status) { + fprintf(stderr, "Unable to remove xattr from \"test42.icloud.com2\" internet password: error %d\n", (int)status); + result++; + } + + /* delete the item itself */ + status = SecKeychainItemDelete(item); + ok_status(status, "%s: SecKeychainItemDelete (generic password)", testName); + + if (status) { + fprintf(stderr, "Unable to delete \"test42.icloud.com2\" internet password: error %d\n", (int)status); + result++; + } + + CFRelease(results); + } + if (query) { + CFRelease(query); + } + } + + return result; +} + +int kc_21_item_xattrs(int argc, char *const *argv) +{ + plan_tests(21); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef keychain = getPopulatedTestKeychain(); + + TestAddItems(keychain); + TestFindItems(keychain); + TestDeleteItems(keychain); + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + CFReleaseNull(keychain); + checkPrompts(0, "No prompts"); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-23-key-export-symmetric.m b/OSX/libsecurity_keychain/regressions/kc-23-key-export-symmetric.m new file mode 100644 index 00000000..6fc075ee --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-23-key-export-symmetric.m @@ -0,0 +1,142 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#if 0 +static void checkCryptoError(OSStatus status, NSString *functionName) { + if (status != errSecSuccess) { + NSError *underlyingError = [[NSError alloc] initWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:underlyingError, NSUnderlyingErrorKey, nil]; + + [underlyingError release]; + + CFStringRef message = SecCopyErrorMessageString(status, NULL); + + NSLog(@"%@ failed with error %d: %@: %@: %@", functionName, (int)status, underlyingError, userInfo, message); + + CFRelease(message); + + cssmPerror([functionName UTF8String], status); + + exit(EXIT_FAILURE); + } +} +#endif + +static SecKeyRef generateSymmetricKey(SecKeychainRef keychainRef, CFStringRef label) +{ + CFMutableDictionaryRef parameters; + int32_t rawnum; + CFNumberRef num; + CFErrorRef error = NULL; + SecKeyRef cryptokey; + + rawnum = 256; + + // Type + parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES); + + num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &rawnum); + CFDictionarySetValue(parameters, kSecAttrKeySizeInBits, num); + + // Store in keychain + CFDictionarySetValue(parameters, kSecUseKeychain, keychainRef); + CFDictionarySetValue(parameters, kSecAttrApplicationLabel, label); + CFDictionarySetValue(parameters, kSecAttrLabel, label); + + + // Extractable and permanent + CFDictionarySetValue(parameters, kSecAttrIsExtractable, kCFBooleanTrue); + CFDictionarySetValue(parameters, kSecAttrIsPermanent, kCFBooleanTrue); + + + cryptokey = SecKeyGenerateSymmetric(parameters, &error); + is(error, NULL, "%s: SecKeyGenerateSymmetric: %s", testName, (error) ? CFStringGetCStringPtr(CFErrorCopyDescription(error), kCFStringEncodingUTF8) : "no error"); + if (error) { + return NULL; + } + + return cryptokey; +} + +int kc_23_key_export_symmetric(int argc, char *const *argv) +{ + plan_tests(6); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SecKeyRef cryptokey; + OSStatus status; + + CFStringRef label = (CFStringRef)([NSString stringWithFormat:@"Symmetric Cryptotest %ld %d", (long)time(NULL), arc4random(), nil]); + cryptokey = generateSymmetricKey(kc, label); + + // Using SecItemExport + CFMutableArrayRef keyUsage = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(keyUsage, kSecAttrCanEncrypt); + CFArrayAppendValue(keyUsage, kSecAttrCanDecrypt); + CFMutableArrayRef keyAttributes = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecItemImportExportKeyParameters exportParams; + exportParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + exportParams.flags = 0; + exportParams.passphrase = NULL; + exportParams.alertTitle = NULL; + exportParams.alertPrompt = NULL; + exportParams.accessRef = NULL; + exportParams.keyUsage = keyUsage; + exportParams.keyAttributes = keyAttributes; + CFDataRef exportedKey2; + status = SecItemExport(cryptokey, kSecFormatRawKey, 0, &exportParams, (CFDataRef *)&exportedKey2); + ok_status(status, "%s: SecItemExport", testName); + + is(CFDataGetLength(exportedKey2), 32, "%s: wrong AES-256 key size", testName); + + CFRelease(exportedKey2); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + [pool drain]; + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-24-key-copy-keychains.c b/OSX/libsecurity_keychain/regressions/kc-24-key-copy-keychains.c new file mode 100644 index 00000000..2797dc6f --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-24-key-copy-keychains.c @@ -0,0 +1,290 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-key-helpers.h" +#include "kc-keychain-file-helpers.h" + +#include +#include + +#include +#include + +/****************************************************************/ + +static OSStatus GenerateRSAKeyPair( + SecKeychainRef keychain, + CFStringRef keyLabel, + int keySizeValue, + Boolean *extractable, + SecKeyRef *publicKeyRef, + SecKeyRef *privateKeyRef) +{ + OSStatus status; + CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); + + // create a SecAccessRef to set up the initial access control settings for this key + // (this step is optional; if omitted, the creating application has access to the key) + // note: the access descriptor should be the same string as will be used for the item's label, + // since it's the string that is displayed by the access confirmation dialog to describe the item. + SecAccessRef access = NULL; + status = SecAccessCreate(keyLabel, NULL, &access); + + // create a dictionary of parameters describing the key we want to create + CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); +/* + From the header doc for SecKeyGeneratePair (seems to be incomplete...): + * kSecAttrLabel default NULL + * kSecAttrIsPermanent if this key is present and has a Boolean + value of true, the key or key pair will be added to the default + keychain. + * kSecAttrApplicationTag default NULL + * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits + * kSecAttrCanEncrypt default false for private keys, true for public keys + * kSecAttrCanDecrypt default true for private keys, false for public keys + * kSecAttrCanDerive default true + * kSecAttrCanSign default true for private keys, false for public keys + * kSecAttrCanVerify default false for private keys, true for public keys + * kSecAttrCanWrap default false for private keys, true for public keys + * kSecAttrCanUnwrap default true for private keys, false for public keys +*/ + CFDictionaryAddValue( params, kSecUseKeychain, keychain ); + CFDictionaryAddValue( params, kSecAttrAccess, access ); + CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA ); + CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); + CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue ); + + if (extractable) + CFDictionaryAddValue( params, kSecAttrIsExtractable, (*extractable) ? kCFBooleanTrue : kCFBooleanFalse ); + if (keyLabel) + CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); + + // generate the key + status = SecKeyGeneratePair(params, publicKeyRef, privateKeyRef); + + ok_status(status, "%s: SecKeyGeneratePair", testName); + + if (params) CFRelease(params); + if (keychain) CFRelease(keychain); + if (access) CFRelease(access); + + return status; +} + +static SecAccessRef MakeNewAccess(SecKeychainItemRef item, CFStringRef accessLabel, Boolean allowAny) +{ + OSStatus status; + SecAccessRef access = NULL; + CFMutableArrayRef trustedApplications = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + if (!allowAny) // use default access control ("confirm access") + { + // Make an exception list of applications you want to trust, + // which are allowed to access the item without requiring user confirmation. + // In this example, the calling app and Mail will have access. + SecTrustedApplicationRef myself = NULL, someOther = NULL; + status = SecTrustedApplicationCreateFromPath(NULL, &myself); + ok_status(status, "%s: MakeNewAccess: SecTrustedApplicationCreateFromPath (self)", testName); + + if (!status && myself) { + CFArrayAppendValue(trustedApplications, myself); + CFRelease(myself); + } + status = SecTrustedApplicationCreateFromPath("/Applications/Mail.app", &someOther); + ok_status(status, "%s: MakeNewAccess: SecTrustedApplicationCreateFromPath (Mail.app)", testName); + + if (!status && someOther) { + CFArrayAppendValue(trustedApplications, someOther); + CFRelease(someOther); + } + } + + // If the keychain item already exists, use its access reference; otherwise, create a new one + if (item) { + status = SecKeychainItemCopyAccess(item, &access); + ok_status(status, "%s: MakeNewAccess: SecKeychainItemCopyAccess", testName); + } else { + status = SecAccessCreate(accessLabel, trustedApplications, &access); + ok_status(status, "%s: MakeNewAccess: SecAccessCreate", testName); + } + if (status) return NULL; + + // get the access control list for decryption operations (this controls access to an item's data) + CFArrayRef aclList = NULL; + status = SecAccessCopySelectedACLList(access, CSSM_ACL_AUTHORIZATION_DECRYPT, &aclList); + ok_status(status, "%s: MakeNewAccess: SecAccessCopySelectedACLList", testName); + if (!status) + { + // get the first entry in the access control list + SecACLRef aclRef = (SecACLRef)CFArrayGetValueAtIndex(aclList, 0); + CFArrayRef appList = NULL; + CFStringRef promptDescription = NULL; + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector; + status = SecACLCopySimpleContents(aclRef, &appList, &promptDescription, &promptSelector); + ok_status(status, "%s: MakeNewAccess: SecAccessCopySimpleContents", testName); + + if (allowAny) // "allow all applications to access this item" + { + // change the decryption ACL to not require the passphrase, and have a NULL application list. + promptSelector.flags &= ~CSSM_ACL_KEYCHAIN_PROMPT_REQUIRE_PASSPHRASE; + status = SecACLSetSimpleContents(aclRef, NULL, promptDescription, &promptSelector); + ok_status(status, "%s: MakeNewAccess: SecACLSetSimpleContents", testName); + } + else // "allow access by these applications" + { + // modify the application list + status = SecACLSetSimpleContents(aclRef, trustedApplications, promptDescription, &promptSelector); + ok_status(status, "%s: MakeNewAccess: SecACLSetSimpleContents", testName); + } + + if (appList) CFRelease(appList); + if (promptDescription) CFRelease(promptDescription); + } + if (aclList) CFRelease(aclList); + if (trustedApplications) CFRelease(trustedApplications); + + return access; +} + +static int testCopyKey(SecKeychainRef userKeychain, SecKeychainRef tempKeychain) +{ + OSStatus status; + SecAccessRef access = NULL; + SecKeyRef publicKeyRef = NULL; + SecKeyRef privateKeyRef = NULL; + CFStringRef label = CFSTR("Test Key Copied To Keychain"); + + if (!tempKeychain) { + warnc(EXIT_FAILURE, "Failed to make a new temporary keychain!"); + } + + // generate key pair in temporary keychain + status = GenerateRSAKeyPair(tempKeychain, + label, + 2048, // size + NULL, // implicitly extractable + &publicKeyRef, + &privateKeyRef); + + if (status != errSecSuccess) { + warnc(EXIT_FAILURE, "Unable to get key pair (error %d)", (int)status); + } + + // export private key from temp keychain to a wrapped data blob + CFDataRef exportedData = NULL; + CFStringRef tempPassword = CFSTR("MY_TEMPORARY_PASSWORD"); + + SecItemImportExportKeyParameters keyParams; + memset(&keyParams, 0, sizeof(keyParams)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + keyParams.passphrase = tempPassword; + + status = SecItemExport(privateKeyRef, kSecFormatWrappedPKCS8, 0, &keyParams, &exportedData); + ok_status(status, "%s: SecItemExport", testName); + + if (!exportedData || status != noErr) { + warnc(EXIT_FAILURE, "Unable to export key! (error %d)", (int)status); + } + + // set up an explicit access control instance for the imported key + // (this example allows unrestricted access to any application) + access = MakeNewAccess(NULL, label, true); + keyParams.accessRef = access; + + // import wrapped data blob to user keychain + SecExternalFormat format = kSecFormatWrappedPKCS8; + SecExternalItemType itemType = kSecItemTypePrivateKey; + + CFArrayRef importedItems = NULL; + status = SecItemImport(exportedData, NULL, &format, &itemType, 0, &keyParams, userKeychain, &importedItems); + ok_status(status, "%s: SecItemImport", testName); + + if (status != noErr) { + warnc(EXIT_FAILURE, "Unable to import key! (error %d)", (int)status); + } + if (importedItems) { + + // make sure to set a label on our newly imported key, since a label is not part of the PKCS8 format. + SecKeyRef importedKey = (SecKeyRef) CFArrayGetValueAtIndex(importedItems, 0); + if (CFGetTypeID(importedKey) == SecKeyGetTypeID()) { + // set up a query defining the item(s) to be operated on, in this case, one item uniquely identified by reference + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue( query, kSecClass, kSecClassKey ); // item class is a required attribute in any query + CFDictionaryAddValue( query, kSecValueRef, importedKey ); + + // define the attributes to be updated, in this case the label + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue( attrs, kSecAttrLabel, label ); + + // do the update + status = SecItemUpdate( query, attrs ); + ok_status(status, "%s: SecItemUpdate", testName); + + if (status != errSecSuccess) { + warnc(EXIT_FAILURE, "Failed to update label of imported key! (error %d)", (int)status); + } + + CFRelease(query); + CFRelease(attrs); + } + CFRelease(importedItems); + } + + // ensure that key was copied, and its label changed + checkN(testName, makeQueryKeyDictionaryWithLabel(userKeychain, kSecAttrKeyClassPrivate, label), 1); + + if (access) CFRelease(access); + + return 0; +} + + +int kc_24_key_copy_keychain(int argc, char *const *argv) +{ + plan_tests(18); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef keychain = getPopulatedTestKeychain(); + SecKeychainRef blankKeychain = createNewKeychain("forKeys", "password"); + + testCopyKey(keychain, blankKeychain); + + ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); + ok_status(SecKeychainDelete(blankKeychain), "%s: SecKeychainDelete", testName); + + CFReleaseNull(keychain); + CFReleaseNull(blankKeychain); + + checkPrompts(0, "No prompts while importing items"); + + deleteTestFiles(); + return 0; +} + diff --git a/OSX/libsecurity_keychain/regressions/kc-26-key-import-public.m b/OSX/libsecurity_keychain/regressions/kc-26-key-import-public.m new file mode 100644 index 00000000..49b3c6c8 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-26-key-import-public.m @@ -0,0 +1,222 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +// +// testPubKeyImport +// +// + +#import +#import + +#include +#include +#include +#include + + +/* test RSA public key to import */ +static const uint8_t kPublicKey[] = +{ + 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xE7,0xD7,0x44,0xF2,0xA2,0xE2,0x78, + 0x8B,0x6C,0x1F,0x55,0xA0,0x8E,0xB7,0x05,0x44,0xA8,0xFA,0x79,0x45,0xAA,0x8B,0xE6, + 0xC6,0x2C,0xE5,0xF5,0x1C,0xBD,0xD4,0xDC,0x68,0x42,0xFE,0x3D,0x10,0x83,0xDD,0x2E, + 0xDE,0xC1,0xBF,0xD4,0x25,0x2D,0xC0,0x2E,0x6F,0x39,0x8B,0xDF,0x0E,0x61,0x48,0xEA, + 0x84,0x85,0x5E,0x2E,0x44,0x2D,0xA6,0xD6,0x26,0x64,0xF6,0x74,0xA1,0xF3,0x04,0x92, + 0x9A,0xDE,0x4F,0x68,0x93,0xEF,0x2D,0xF6,0xE7,0x11,0xA8,0xC7,0x7A,0x0D,0x91,0xC9, + 0xD9,0x80,0x82,0x2E,0x50,0xD1,0x29,0x22,0xAF,0xEA,0x40,0xEA,0x9F,0x0E,0x14,0xC0, + 0xF7,0x69,0x38,0xC5,0xF3,0x88,0x2F,0xC0,0x32,0x3D,0xD9,0xFE,0x55,0x15,0x5F,0x51, + 0xBB,0x59,0x21,0xC2,0x01,0x62,0x9F,0xD7,0x33,0x52,0xD5,0xE2,0xEF,0xAA,0xBF,0x9B, + 0xA0,0x48,0xD7,0xB8,0x13,0xA2,0xB6,0x76,0x7F,0x6C,0x3C,0xCF,0x1E,0xB4,0xCE,0x67, + 0x3D,0x03,0x7B,0x0D,0x2E,0xA3,0x0C,0x5F,0xFF,0xEB,0x06,0xF8,0xD0,0x8A,0xDD,0xE4, + 0x09,0x57,0x1A,0x9C,0x68,0x9F,0xEF,0x10,0x72,0x88,0x55,0xDD,0x8C,0xFB,0x9A,0x8B, + 0xEF,0x5C,0x89,0x43,0xEF,0x3B,0x5F,0xAA,0x15,0xDD,0xE6,0x98,0xBE,0xDD,0xF3,0x59, + 0x96,0x03,0xEB,0x3E,0x6F,0x61,0x37,0x2B,0xB6,0x28,0xF6,0x55,0x9F,0x59,0x9A,0x78, + 0xBF,0x50,0x06,0x87,0xAA,0x7F,0x49,0x76,0xC0,0x56,0x2D,0x41,0x29,0x56,0xF8,0x98, + 0x9E,0x18,0xA6,0x35,0x5B,0xD8,0x15,0x97,0x82,0x5E,0x0F,0xC8,0x75,0x34,0x3E,0xC7, + 0x82,0x11,0x76,0x25,0xCD,0xBF,0x98,0x44,0x7B,0x02,0x03,0x01,0x00,0x01,0xD4,0x9D +}; + +#if 0 +static const uint8_t k512PublicKeyModulus[] = +{ + 0x00, + 0xE2,0x7E,0x6C,0xDE,0xF4,0x45,0x8E,0x69,0xFF,0x9B,0x39,0x76,0x41,0x44,0x2E,0x2E, + 0x61,0x27,0x07,0x0F,0x56,0xC9,0x6F,0x3F,0x71,0x82,0x67,0x1F,0xEB,0x0B,0xED,0x65, + 0x09,0x9B,0x12,0x29,0x61,0x1D,0x66,0x3B,0x8C,0x63,0x0F,0x30,0x5C,0x00,0x42,0x85, + 0x6F,0xD5,0xFB,0xF5,0x3D,0x63,0x99,0xC1,0xDE,0xD7,0x42,0x30,0x51,0x42,0xF3,0xD9 +}; + +static const uint8_t k512PublicKeyExponent[] = { 0x01,0x00,0x01 }; // 65537 +#endif + +static const uint8_t k1024PublicKeyModulus[] = +{ + 0x00, + 0xBF,0x53,0x5F,0x27,0x26,0x28,0xD1,0x02,0x52,0x75,0x54,0xFB,0x5F,0xF1,0xBE,0x94, + 0xB0,0x3B,0x33,0xB0,0x36,0xF6,0xF8,0x14,0xB9,0x62,0xEC,0xFC,0x31,0xF2,0xAB,0x60, + 0x59,0x02,0xB7,0x68,0x6C,0x91,0x91,0x9E,0xE8,0x08,0xF0,0x49,0xD9,0xBD,0x24,0x5A, + 0xB9,0xD6,0x08,0x89,0xA0,0xF1,0xBC,0xC7,0xB4,0x55,0xB5,0x0E,0x1A,0xA5,0xCC,0x94, + 0x4E,0x57,0xB6,0xA9,0x6B,0x5C,0x90,0x28,0x6F,0xBD,0x8C,0x12,0xF9,0x59,0x5E,0x47, + 0xDB,0x4C,0x7F,0x4D,0xB8,0x12,0x0A,0x36,0x9B,0x6F,0x8B,0xCC,0xB3,0x0F,0x60,0x23, + 0xED,0x91,0x78,0x28,0x0A,0x5E,0xF4,0x24,0xC6,0xDD,0x80,0x50,0xC4,0xCD,0xF6,0x52, + 0x6B,0xDD,0x35,0x82,0xCE,0xF2,0x7B,0xA4,0x73,0xD9,0x5F,0x75,0x2D,0xB6,0x77,0xAD +}; + +static const uint8_t k1024PublicKeyExponent[] = { 0x01,0x00,0x01 }; // 65537 + + +static void +testPubKeyImport(void) +{ + OSStatus status = errSecSuccess; + NSArray* outputItems = nil; + SecKeychainRef keychain = NULL; + NSData* keyData = [NSData dataWithBytes:kPublicKey length:sizeof(kPublicKey)]; + SecExternalFormat format = kSecFormatUnknown; + SecExternalItemType keyType = kSecItemTypePublicKey; + + status = SecKeychainCopyDefault(&keychain); + // ignoring error + + status = SecItemImport((CFDataRef)keyData, + NULL, &format, &keyType, 0, NULL, + keychain, (CFArrayRef *)&outputItems); + + NSLog(@"SecItemImport result = %d", (int)status); + + if (keychain) CFRelease(keychain); + if (outputItems) CFRelease(outputItems); +} + +static void +testPubKeyImportWithModulusAndExponent(SecKeychainRef keychain) +{ + OSStatus status = errSecSuccess; + + typedef struct SecRSAPublicKeyParams { + uint8_t *modulus; /* modulus */ + CFIndex modulusLength; + uint8_t *exponent; /* public exponent */ + CFIndex exponentLength; + } SecRSAPublicKeyParams; +#if 0 + SecRSAPublicKeyParams pubKeyParams = { + .modulus = (uint8_t *)k512PublicKeyModulus, + .modulusLength = sizeof(k512PublicKeyModulus), + .exponent = (uint8_t *)k512PublicKeyExponent, + .exponentLength = sizeof(k512PublicKeyExponent), + }; +#else + SecRSAPublicKeyParams pubKeyParams = { + .modulus = (uint8_t *)k1024PublicKeyModulus, + .modulusLength = sizeof(k1024PublicKeyModulus), + .exponent = (uint8_t *)k1024PublicKeyExponent, + .exponentLength = sizeof(k1024PublicKeyExponent), + }; +#endif +// SecKeyRef key = SecKeyCreateRSAPublicKey(NULL, (const uint8_t *)&pubKeyParams, +// sizeof(pubKeyParams), kSecKeyEncodingRSAPublicParams); + + // wrap as PKCS1 + DERSize m_size = pubKeyParams.modulusLength; + DERSize e_size = pubKeyParams.exponentLength; + const DERSize seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) + + DERLengthOfItem(ASN1_INTEGER, e_size); + const DERSize result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size); + DERSize r_size, remaining_size = result_size; + DERReturn drtn; + + CFMutableDataRef pkcs1 = CFDataCreateMutable(NULL, result_size); + ok(pkcs1, "%s: create CFData", testName); + if (pkcs1 == NULL) { + NSLog(@"CFDataCreateMutable failed"); + return; + } + CFDataSetLength(pkcs1, result_size); + uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); + + *bytes++ = ONE_BYTE_ASN1_CONSTR_SEQUENCE; + remaining_size--; + r_size = 4; + drtn = DEREncodeLength(seq_size, bytes, &r_size); + if (r_size <= remaining_size) { + bytes += r_size; + remaining_size -= r_size; + } + r_size = remaining_size; + drtn = DEREncodeItem(ASN1_INTEGER, m_size, (const DERByte *)pubKeyParams.modulus, (DERByte *)bytes, &r_size); + if (r_size <= remaining_size) { + bytes += r_size; + remaining_size -= r_size; + } + r_size = remaining_size; + drtn = DEREncodeItem(ASN1_INTEGER, e_size, (const DERByte *)pubKeyParams.exponent, (DERByte *)bytes, &r_size); + + + SecExternalFormat externalFormat = kSecFormatBSAFE; //kSecFormatOpenSSL; + SecExternalItemType externalItemType = kSecItemTypePublicKey; + CFArrayRef outArray = NULL; + + status = SecItemImport(pkcs1, NULL, &externalFormat, &externalItemType, 0, NULL, keychain, &outArray); + ok_status(status, "%s: SecItemImport", testName); + if (status != errSecSuccess) { + NSLog(@"SecItemImport result = %d", (int)status); + return; + } + + // TODO: encrypt something with this key and check the result + + if (outArray) CFRelease(outArray); +} + +int kc_26_key_import_public(int argc, char *const *argv) +{ + plan_tests(5); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +// testPubKeyImport(); + testPubKeyImportWithModulusAndExponent(kc); + [pool drain]; + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + deleteTestFiles(); + return 0; +} + +#pragma clang diagnostic pop diff --git a/OSX/libsecurity_keychain/regressions/kc-27-key-non-extractable.c b/OSX/libsecurity_keychain/regressions/kc-27-key-non-extractable.c new file mode 100644 index 00000000..8dd17e33 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-27-key-non-extractable.c @@ -0,0 +1,236 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#import + +#include "keychain_regressions.h" +#include "kc-helpers.h" + +// +// Test for +// + +#include +#include + +#include +#include +#include + +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +/* + Note: the following will show all private keys with their label + and extractable attribute value (in attribute 0x00000010): + + $ security dump | grep -A 16 "0x00000000 =0x00000010" | grep -e ^\ *0x000000[01][01] -e -- +*/ + + +static OSStatus GenerateRSAKeyPair( + SecKeychainRef keychain, + CFStringRef keyLabel, + int keySizeValue, + Boolean *extractable, + SecKeyRef *publicKeyRef, + SecKeyRef *privateKeyRef) +{ + OSStatus status; + CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue); + + // create a SecAccessRef to set up the initial access control settings for this key + // (this step is optional; if omitted, the creating application has access to the key) + // note: the access descriptor should be the same string as will be used for the item's label, + // since it's the string that is displayed by the access confirmation dialog to describe the item. + SecAccessRef access = NULL; + status = SecAccessCreate(keyLabel, NULL, &access); + + // create a dictionary of parameters describing the key we want to create + CFMutableDictionaryRef params = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); +/* + From the header doc for SecKeyGeneratePair (seems to be incomplete...): + * kSecAttrLabel default NULL + * kSecAttrIsPermanent if this key is present and has a Boolean + value of true, the key or key pair will be added to the default + keychain. + * kSecAttrApplicationTag default NULL + * kSecAttrEffectiveKeySize default NULL same as kSecAttrKeySizeInBits + * kSecAttrCanEncrypt default false for private keys, true for public keys + * kSecAttrCanDecrypt default true for private keys, false for public keys + * kSecAttrCanDerive default true + * kSecAttrCanSign default true for private keys, false for public keys + * kSecAttrCanVerify default false for private keys, true for public keys + * kSecAttrCanWrap default false for private keys, true for public keys + * kSecAttrCanUnwrap default true for private keys, false for public keys +*/ + CFDictionaryAddValue( params, kSecUseKeychain, keychain ); + CFDictionaryAddValue( params, kSecAttrAccess, access ); + CFDictionaryAddValue( params, kSecAttrKeyType, kSecAttrKeyTypeRSA ); + CFDictionaryAddValue( params, kSecAttrKeySizeInBits, keySize ); + CFDictionaryAddValue( params, kSecAttrIsPermanent, kCFBooleanTrue ); + + if (extractable) + CFDictionaryAddValue( params, kSecAttrIsExtractable, (*extractable) ? kCFBooleanTrue : kCFBooleanFalse ); + if (keyLabel) + CFDictionaryAddValue( params, kSecAttrLabel, keyLabel ); + + // generate the key + status = SecKeyGeneratePair(params, publicKeyRef, privateKeyRef); + ok_status(status, "%s: SecKeyGeneratePair", testName); + + if (params) CFRelease(params); + if (access) CFRelease(access); + + return status; +} + +static int testExtractable( + SecKeychainRef keychain, + Boolean extractable, + Boolean explicit) +{ + OSStatus status; + SecKeyRef publicKeyRef = NULL; + SecKeyRef privateKeyRef = NULL; + CFStringRef label = (extractable) ? CFSTR("test-extractable-YES") : CFSTR("test-extractable-NO"); + Boolean *extractablePtr = (explicit) ? &extractable : NULL; + + status = GenerateRSAKeyPair(keychain, + label, + 1024, // size + extractablePtr, + &publicKeyRef, + &privateKeyRef); + + if (status != noErr) { + //errx(EXIT_FAILURE, "Unable to get key pair (err = %d)", status); + return status; + } + + // check that the attributes of the generated private key are what we think they are + const CSSM_KEY *cssmPrivKey; + status = SecKeyGetCSSMKey(privateKeyRef, &cssmPrivKey); + ok_status(status, "%s: SecKeyGetCSSMKey", testName); + + if (status != noErr) { + //errx(EXIT_FAILURE, "Unable to get CSSM reference key (err = %d)", status); + return status; + } + if (extractable) { + ok(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE, "%s: check private key marked as extractable (as requested)", testName); + if (!(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) { + //errx(EXIT_FAILURE, "Oops! the private key was not marked as extractable!"); + return 1; + } + } + else { + ok(!(cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE), "%s: check private key marked as non-extractable (as requested)", testName); + if (cssmPrivKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE) { + //errx(EXIT_FAILURE, "Oops! the private key was marked as extractable!"); + return 1; + } + } + + SecKeyImportExportParameters keyParams; + memset(&keyParams, 0, sizeof(keyParams)); + keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + keyParams.passphrase = CFSTR("borken"); + + CFDataRef exportedData = NULL; + + status = SecKeychainItemExport(privateKeyRef, kSecFormatWrappedPKCS8, 0, &keyParams, &exportedData); + if(extractable) { + ok_status(status, "%s: SecKeychainItemExport (PKCS8) (and we expected it to succeed)", testName); + } else { + is(status, errSecDataNotAvailable, "%s: SecKeychainItemExport (PKCS8) (and we expected this to fail with errSecDataNotAvailable)", testName); + } + + status = SecKeychainItemExport(privateKeyRef, kSecFormatPKCS12, 0, &keyParams, &exportedData); + if(extractable) { + ok_status(status, "%s: SecKeychainItemExport(and we expected it to succeed)", testName); + } else { + is(status, errSecDataNotAvailable, "%s: SecKeychainItemExport (PKCS12) (and we expected this to fail with errSecDataNotAvailable)", testName); + } + + if (status != noErr) { + if (extractable) { + //errx(EXIT_FAILURE, "Unable to export extractable key! (err = %d)", status); + return 1; + } + else { + status = 0; // wasn't extractable, so this is the expected result + } + } + else if (status == noErr && !extractable) { + //errx(EXIT_FAILURE, "Was able to export non-extractable key! (err = %d)", status); + return 1; + } + + status = SecKeychainItemDelete((SecKeychainItemRef)publicKeyRef); + ok_status(status, "%s: SecKeychainItemDelete", testName); + if (status != noErr) { + warnx("Unable to delete created public key from keychain (err = %d)", (int)status); + } + + status = SecKeychainItemDelete((SecKeychainItemRef)privateKeyRef); + ok_status(status, "%s: SecKeychainItemDelete", testName); + if (status != noErr) { + warnx("Unable to delete created private key from keychain (err = %d)", (int)status); + } + + CFRelease(publicKeyRef); + CFRelease(privateKeyRef); + + return 0; +} + + +int kc_27_key_non_extractable(int argc, char *const *argv) +{ + plan_tests(24); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + // test case 1: extractable + startTest("Extract extractable key"); + testExtractable(kc, TRUE, TRUE); + + // test case 2: non-extractable + startTest("Extract non-extractable key"); + testExtractable(kc, FALSE, TRUE); + + // test case 3: extractable (when not explicitly specified) + startTest("Extract implicitly extractable key"); + testExtractable(kc, TRUE, FALSE); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFRelease(kc); + + deleteTestFiles(); + return 0; +} + diff --git a/OSX/libsecurity_keychain/regressions/kc-28-cert-sign.c b/OSX/libsecurity_keychain/regressions/kc-28-cert-sign.c new file mode 100644 index 00000000..19f48da1 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-28-cert-sign.c @@ -0,0 +1,733 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-keychain-file-helpers.h" +#include "test/testenv.h" + +// +// Test for Radar 17159227 +// + +#include +#include +#include // for SecIdentityCreate +#include + +#include +#include +#include +#include +#include + +/* Test CA certificate + */ +unsigned char coreOSTestCA[995]={ + 0x30,0x82,0x03,0xDF,0x30,0x82,0x02,0xC7,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x78, + 0x0C,0x4B,0x30,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, + 0x30,0x81,0x9F,0x31,0x31,0x30,0x2F,0x06,0x03,0x55,0x04,0x03,0x0C,0x28,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,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,0x27,0x30,0x25,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x1E,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x20,0x2D,0x20, + 0x44,0x45,0x56,0x45,0x4C,0x4F,0x50,0x4D,0x45,0x4E,0x54,0x20,0x55,0x53,0x45,0x20, + 0x4F,0x4E,0x4C,0x59,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,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x30,0x1E,0x17,0x0D,0x31,0x34,0x30,0x37,0x31,0x37,0x30,0x31,0x33,0x35, + 0x30,0x37,0x5A,0x17,0x0D,0x31,0x36,0x30,0x37,0x31,0x37,0x30,0x31,0x33,0x35,0x30, + 0x37,0x5A,0x30,0x81,0x9F,0x31,0x31,0x30,0x2F,0x06,0x03,0x55,0x04,0x03,0x0C,0x28, + 0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 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,0x27,0x30, + 0x25,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1E,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x20, + 0x2D,0x20,0x44,0x45,0x56,0x45,0x4C,0x4F,0x50,0x4D,0x45,0x4E,0x54,0x20,0x55,0x53, + 0x45,0x20,0x4F,0x4E,0x4C,0x59,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, + 0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72, + 0x74,0x69,0x6E,0x6F,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,0xE3,0xC9,0x79,0xA2,0x1F,0xC8,0xFC,0x4F,0xF4,0x70,0x07, + 0xAA,0x8A,0xFA,0xB2,0x60,0xEE,0x3E,0x9D,0xD6,0xA4,0x4F,0x4B,0x17,0x68,0x63,0x54, + 0xC1,0x1C,0x12,0xE1,0x7A,0x93,0x5A,0x04,0x48,0x56,0x1B,0xDD,0x9C,0xC5,0x09,0xB0, + 0x5F,0x39,0xE2,0xB0,0x86,0x60,0xAF,0x13,0x7A,0x8F,0x97,0x35,0x02,0xCC,0xC0,0x83, + 0x90,0xAC,0x5C,0x44,0xFE,0xF2,0xC1,0xAB,0xB6,0x01,0xFF,0x57,0x7F,0x0B,0xF5,0xA9, + 0x7B,0x5E,0xF0,0x99,0x1D,0xAE,0xA9,0x56,0xC6,0x32,0x71,0xB5,0x7E,0xEA,0xAB,0xBD, + 0x01,0xFE,0xF8,0x35,0xFE,0xE6,0xB2,0x83,0x32,0x00,0x9D,0x51,0x74,0x64,0x00,0xDA, + 0x58,0xD6,0x73,0xB4,0x11,0x8B,0xB6,0x7C,0x86,0x60,0x54,0x42,0x24,0xF9,0xC4,0xAD, + 0x70,0x07,0xB1,0x05,0x29,0x1E,0x57,0x3B,0x97,0xDC,0x2F,0x51,0x4C,0xBB,0x3A,0x1D, + 0x30,0xB5,0xC9,0x69,0x85,0x3D,0xFE,0x9B,0xE8,0x96,0xD9,0xC3,0xC0,0xB4,0xEB,0xB8, + 0x48,0x90,0x74,0xDC,0xC0,0x65,0x50,0x01,0x36,0xCF,0x10,0x8A,0xBF,0xDA,0x9D,0x00, + 0x07,0x2D,0xE9,0x9F,0x58,0x0D,0xF1,0x07,0x55,0xAE,0xC2,0x0F,0xE2,0x2D,0xB8,0xCF, + 0xF5,0x79,0x1D,0x05,0xFD,0xE3,0xE9,0xB1,0x4D,0xD8,0xAA,0xB6,0x26,0xC2,0xC2,0x6E, + 0x72,0xA2,0x18,0xA4,0x81,0x39,0x80,0xA6,0x6B,0x6D,0x16,0x4F,0xB5,0xA0,0xE3,0x20, + 0xE2,0x5B,0x0E,0xE0,0x2D,0x31,0xAD,0x92,0xD6,0x4C,0x13,0x3D,0x81,0x55,0xD1,0xB3, + 0x36,0xC0,0xFB,0xDD,0xCF,0x01,0x9F,0xED,0xCE,0x3B,0x47,0x70,0x59,0xE4,0x25,0x69, + 0x99,0x5C,0x21,0x0C,0x13,0x02,0x03,0x01,0x00,0x01,0xA3,0x23,0x30,0x21,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, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0xA1,0xFD,0xD2,0x4A,0xCC,0x63,0x5F,0x5C,0xC3,0xBD,0x59,0x47,0x53, + 0x92,0xE9,0x7C,0x66,0xF6,0x17,0xC3,0x96,0x27,0xB3,0xE1,0xD3,0x52,0x40,0xF6,0xAA, + 0xA3,0x96,0xC4,0xE2,0x76,0x7B,0xE3,0xA6,0xCD,0x6C,0xA1,0x49,0x52,0x82,0x09,0x77, + 0xC6,0x87,0x1D,0x44,0x6E,0x47,0x8F,0x34,0xE2,0xB6,0x4B,0x1E,0x13,0x31,0x9E,0x93, + 0x3E,0xF2,0x7B,0x56,0xEC,0x88,0x93,0x81,0x99,0x55,0x26,0x54,0x72,0x6E,0xD3,0x02, + 0x45,0x9F,0x51,0x67,0xC2,0x7D,0x46,0xA1,0x4E,0xE5,0x37,0x3F,0x88,0xAB,0x4F,0xD6, + 0x87,0xBC,0xEE,0xBA,0x29,0x07,0x10,0xCC,0x1E,0x3A,0xD6,0x38,0x5F,0x9D,0x12,0xE6, + 0x8A,0x9B,0xD0,0xEB,0x5A,0x88,0xC0,0xE8,0x90,0x78,0xCB,0x8A,0x8A,0xBB,0x63,0xA1, + 0x58,0x1C,0x32,0x8E,0xF0,0xB3,0xA5,0xB5,0x93,0x65,0xA1,0xE2,0x18,0xB1,0xE3,0x2C, + 0xF8,0xF1,0x6C,0xC8,0xCD,0x7B,0xA8,0x8B,0x84,0x42,0xD0,0x5F,0x9A,0x72,0x4A,0x2C, + 0x97,0x50,0x44,0x70,0x0D,0x95,0x86,0xE8,0xDF,0xA4,0x52,0xEB,0xE4,0x87,0xF2,0x69, + 0xD6,0x78,0xA3,0x96,0x37,0x55,0x3D,0x5B,0x86,0x5B,0xED,0xF9,0x93,0x2A,0x75,0xE2, + 0x1A,0x7D,0xF5,0xC9,0x34,0x76,0x80,0x37,0x0D,0x77,0x2B,0x37,0xCA,0x19,0x3D,0xB6, + 0xB4,0xEB,0xC9,0xC8,0x76,0x75,0x07,0xE5,0x24,0x8C,0xB1,0xA3,0x29,0x53,0x54,0x43, + 0xFC,0xE3,0x40,0x5B,0x31,0xC6,0x43,0x13,0x62,0xA8,0x1B,0xB9,0xE2,0xED,0x33,0x40, + 0x0A,0xAB,0x43,0x69,0x31,0x4A,0x13,0x7B,0xCB,0xC8,0x33,0x93,0xDE,0x70,0xAD,0x80, + 0x29,0xBF,0x9E, +}; + +/* Normal code signing certificate, issued by CA above + */ +unsigned char leafSigningCertificate[1007]={ + 0x30,0x82,0x03,0xEB,0x30,0x82,0x02,0xD3,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x78, + 0x0C,0xC5,0xD9,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x30,0x81,0x9F,0x31,0x31,0x30,0x2F,0x06,0x03,0x55,0x04,0x03,0x0C,0x28,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,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,0x27,0x30,0x25,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x1E,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x20,0x2D,0x20, + 0x44,0x45,0x56,0x45,0x4C,0x4F,0x50,0x4D,0x45,0x4E,0x54,0x20,0x55,0x53,0x45,0x20, + 0x4F,0x4E,0x4C,0x59,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,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x30,0x1E,0x17,0x0D,0x31,0x34,0x31,0x30,0x33,0x30,0x32,0x32,0x34,0x37, + 0x32,0x30,0x5A,0x17,0x0D,0x31,0x35,0x31,0x30,0x33,0x30,0x32,0x32,0x34,0x37,0x32, + 0x30,0x5A,0x30,0x81,0xA4,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x03,0x0C,0x0E, + 0x52,0x61,0x64,0x61,0x72,0x20,0x31,0x37,0x31,0x35,0x39,0x32,0x32,0x37,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x0C,0x10,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,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,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,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,0xD0,0x6A,0xA3,0x00,0xEE,0xFC, + 0x30,0x30,0x8C,0x4F,0xC1,0x51,0x7C,0x6E,0xF6,0x45,0x3C,0xE5,0x41,0xAB,0x77,0xDB, + 0xEE,0x73,0x9E,0xE3,0x21,0xBF,0x89,0x3F,0xA7,0xBF,0x23,0x0B,0x3F,0x68,0xF6,0xA4, + 0x80,0xB7,0xF4,0xE3,0xF0,0x10,0x21,0xF0,0xF6,0xBB,0x97,0x08,0x9E,0xA9,0xD0,0x9F, + 0xAB,0xC8,0xF8,0xE9,0xFB,0x9A,0x89,0x2C,0x3C,0x30,0x93,0x92,0x9D,0x08,0x2C,0x0F, + 0x63,0x1C,0xCC,0x4E,0x69,0x0E,0x62,0x9F,0xA6,0x3E,0xAE,0x8B,0x76,0x60,0x6F,0xD9, + 0x5D,0xD2,0xBD,0x38,0x95,0xAA,0x22,0xFD,0xCE,0xDF,0x41,0x15,0x79,0x5E,0x4C,0xAB, + 0x51,0x90,0x3D,0xD7,0x41,0xC3,0x90,0x41,0x58,0xEC,0xB4,0xB5,0x5A,0xBD,0x58,0x1B, + 0x38,0x5D,0xFE,0xB6,0x55,0xA0,0xDA,0x67,0xDF,0x34,0x4F,0x3E,0xE2,0x1A,0xF1,0x8C, + 0x44,0x57,0x2E,0xBB,0xE3,0x19,0xFA,0x08,0xE3,0xF1,0x9C,0x17,0xA2,0xDE,0x74,0xF4, + 0xF7,0x5D,0x6B,0xA2,0xE8,0x2B,0xB3,0xF0,0x3B,0x77,0x4C,0xAE,0x63,0xCA,0xAD,0xB1, + 0xBB,0x32,0x71,0xE0,0xC2,0x8D,0x6B,0x7B,0x3E,0xB4,0xAC,0x61,0xCA,0x40,0xDC,0xEA, + 0xE4,0xA7,0x2C,0xA4,0xE4,0x40,0xCC,0xD1,0x1F,0xE9,0x05,0x91,0xA9,0x44,0x54,0xB2, + 0x96,0x66,0xC5,0xF2,0x28,0xBF,0xA6,0xDA,0xA5,0xD8,0x09,0x53,0x08,0xF6,0x7D,0x09, + 0xA3,0x6C,0x40,0x7B,0x3C,0x8D,0x09,0xE8,0xED,0xD2,0x55,0x86,0x1B,0x42,0x1C,0x72, + 0xAB,0xAB,0xF2,0x6F,0x0B,0xB4,0x6F,0xCB,0xE7,0x59,0x29,0xFB,0x6A,0x4A,0x91,0xF4, + 0x8C,0xFC,0xA0,0xF8,0x8B,0x55,0x4A,0xD3,0x3A,0x41,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x2A,0x30,0x28,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30, + 0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x60, + 0xF9,0x1C,0xE5,0x5E,0xCE,0x79,0x57,0x7E,0x24,0xC1,0x7E,0x07,0x87,0xC6,0x55,0x6E, + 0x38,0xBB,0x17,0x0B,0xAE,0xBC,0xDB,0x72,0xBD,0xA0,0x47,0x2F,0x54,0x34,0x53,0xE7, + 0x21,0xD7,0x04,0x8B,0x06,0x84,0x76,0x81,0x2A,0x6A,0x75,0x06,0xB4,0x62,0xA0,0xBC, + 0xC3,0x78,0x08,0x50,0x3D,0x63,0x44,0x32,0xEA,0xDA,0xFA,0x66,0xDF,0xF9,0xC2,0xE8, + 0xEF,0x72,0x83,0xAF,0x3E,0x2F,0x20,0x83,0x08,0x61,0xD8,0x6A,0x1A,0x71,0x68,0xB8, + 0x21,0x1F,0x0E,0xA8,0x2A,0xDA,0xF0,0x87,0xB1,0xAC,0xCE,0xAB,0xFB,0x9C,0xBC,0x43, + 0x04,0xE5,0x2F,0xF3,0x7D,0xAD,0x78,0x43,0x00,0x74,0x65,0x28,0x8D,0x3F,0x27,0x8F, + 0x33,0x7B,0x36,0xCD,0xAF,0x35,0x33,0xAF,0x06,0xF5,0x22,0x67,0xC7,0xD1,0x88,0x9B, + 0x55,0xE8,0x0E,0x48,0x5F,0x9A,0x30,0x5A,0xF5,0x93,0x53,0x78,0x44,0x8B,0x3A,0xB6, + 0x24,0x7F,0x5D,0x6E,0xDB,0x68,0x72,0x15,0xAD,0xB8,0x3E,0x66,0xE7,0x0E,0x99,0xEB, + 0xAB,0x1D,0x91,0xC8,0xEF,0x5A,0x32,0xA9,0x3E,0x0B,0x82,0x4E,0x5A,0x64,0xC1,0xC5, + 0xFD,0xD0,0x93,0xE0,0x82,0x39,0x7C,0x94,0x78,0x23,0x5D,0x5E,0x65,0x67,0xB9,0x83, + 0xEB,0x3A,0xC6,0x6C,0x65,0x8A,0xC6,0x83,0x2F,0x90,0x4C,0x75,0x7F,0x7A,0x2F,0x3E, + 0xA8,0xAA,0x16,0xF5,0x67,0x5D,0x50,0xC7,0x0E,0x7F,0x7C,0xA2,0xC8,0x10,0x67,0xFD, + 0x3E,0x91,0xA4,0xD5,0xA0,0xF6,0x9D,0x5A,0x0E,0x56,0xC0,0xCA,0xBA,0xB4,0x8B,0xB1, + 0xB5,0x3A,0x22,0xC0,0xEC,0xF8,0x8F,0xD7,0x49,0xBE,0x8D,0x98,0xE0,0x30,0x0E, +}; + +/* This certificate is longer than the length claimed in its top-level ASN.1 sequence. + It is only supposed to be 1007 bytes, but has 16 extra bytes tacked onto the end. + */ +unsigned char bogusTrailingBytesSigningCertificate[1023]={ + 0x30,0x82,0x03,0xEB,0x30,0x82,0x02,0xD3,0xA0,0x03,0x02,0x01,0x02,0x02,0x04,0x78, + 0x0C,0xC5,0xD9,0x30,0x0B,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x30,0x81,0x9F,0x31,0x31,0x30,0x2F,0x06,0x03,0x55,0x04,0x03,0x0C,0x28,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,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,0x27,0x30,0x25,0x06, + 0x03,0x55,0x04,0x0B,0x0C,0x1E,0x43,0x6F,0x72,0x65,0x20,0x4F,0x53,0x20,0x2D,0x20, + 0x44,0x45,0x56,0x45,0x4C,0x4F,0x50,0x4D,0x45,0x4E,0x54,0x20,0x55,0x53,0x45,0x20, + 0x4F,0x4E,0x4C,0x59,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,0x31,0x12, + 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69, + 0x6E,0x6F,0x30,0x1E,0x17,0x0D,0x31,0x34,0x31,0x30,0x33,0x30,0x32,0x32,0x34,0x37, + 0x32,0x30,0x5A,0x17,0x0D,0x31,0x35,0x31,0x30,0x33,0x30,0x32,0x32,0x34,0x37,0x32, + 0x30,0x5A,0x30,0x81,0xA4,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x03,0x0C,0x0E, + 0x52,0x61,0x64,0x61,0x72,0x20,0x31,0x37,0x31,0x35,0x39,0x32,0x32,0x37,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,0x0B,0x0C,0x10,0x43,0x6F, + 0x72,0x65,0x20,0x4F,0x53,0x20,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,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,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x2B,0x30,0x29, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,0x16,0x1C,0x73,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x2D,0x64,0x65,0x76,0x40,0x67,0x72,0x6F,0x75,0x70,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,0xD0,0x6A,0xA3,0x00,0xEE,0xFC, + 0x30,0x30,0x8C,0x4F,0xC1,0x51,0x7C,0x6E,0xF6,0x45,0x3C,0xE5,0x41,0xAB,0x77,0xDB, + 0xEE,0x73,0x9E,0xE3,0x21,0xBF,0x89,0x3F,0xA7,0xBF,0x23,0x0B,0x3F,0x68,0xF6,0xA4, + 0x80,0xB7,0xF4,0xE3,0xF0,0x10,0x21,0xF0,0xF6,0xBB,0x97,0x08,0x9E,0xA9,0xD0,0x9F, + 0xAB,0xC8,0xF8,0xE9,0xFB,0x9A,0x89,0x2C,0x3C,0x30,0x93,0x92,0x9D,0x08,0x2C,0x0F, + 0x63,0x1C,0xCC,0x4E,0x69,0x0E,0x62,0x9F,0xA6,0x3E,0xAE,0x8B,0x76,0x60,0x6F,0xD9, + 0x5D,0xD2,0xBD,0x38,0x95,0xAA,0x22,0xFD,0xCE,0xDF,0x41,0x15,0x79,0x5E,0x4C,0xAB, + 0x51,0x90,0x3D,0xD7,0x41,0xC3,0x90,0x41,0x58,0xEC,0xB4,0xB5,0x5A,0xBD,0x58,0x1B, + 0x38,0x5D,0xFE,0xB6,0x55,0xA0,0xDA,0x67,0xDF,0x34,0x4F,0x3E,0xE2,0x1A,0xF1,0x8C, + 0x44,0x57,0x2E,0xBB,0xE3,0x19,0xFA,0x08,0xE3,0xF1,0x9C,0x17,0xA2,0xDE,0x74,0xF4, + 0xF7,0x5D,0x6B,0xA2,0xE8,0x2B,0xB3,0xF0,0x3B,0x77,0x4C,0xAE,0x63,0xCA,0xAD,0xB1, + 0xBB,0x32,0x71,0xE0,0xC2,0x8D,0x6B,0x7B,0x3E,0xB4,0xAC,0x61,0xCA,0x40,0xDC,0xEA, + 0xE4,0xA7,0x2C,0xA4,0xE4,0x40,0xCC,0xD1,0x1F,0xE9,0x05,0x91,0xA9,0x44,0x54,0xB2, + 0x96,0x66,0xC5,0xF2,0x28,0xBF,0xA6,0xDA,0xA5,0xD8,0x09,0x53,0x08,0xF6,0x7D,0x09, + 0xA3,0x6C,0x40,0x7B,0x3C,0x8D,0x09,0xE8,0xED,0xD2,0x55,0x86,0x1B,0x42,0x1C,0x72, + 0xAB,0xAB,0xF2,0x6F,0x0B,0xB4,0x6F,0xCB,0xE7,0x59,0x29,0xFB,0x6A,0x4A,0x91,0xF4, + 0x8C,0xFC,0xA0,0xF8,0x8B,0x55,0x4A,0xD3,0x3A,0x41,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x2A,0x30,0x28,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03, + 0x02,0x07,0x80,0x30,0x16,0x06,0x03,0x55,0x1D,0x25,0x01,0x01,0xFF,0x04,0x0C,0x30, + 0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x60, + 0xF9,0x1C,0xE5,0x5E,0xCE,0x79,0x57,0x7E,0x24,0xC1,0x7E,0x07,0x87,0xC6,0x55,0x6E, + 0x38,0xBB,0x17,0x0B,0xAE,0xBC,0xDB,0x72,0xBD,0xA0,0x47,0x2F,0x54,0x34,0x53,0xE7, + 0x21,0xD7,0x04,0x8B,0x06,0x84,0x76,0x81,0x2A,0x6A,0x75,0x06,0xB4,0x62,0xA0,0xBC, + 0xC3,0x78,0x08,0x50,0x3D,0x63,0x44,0x32,0xEA,0xDA,0xFA,0x66,0xDF,0xF9,0xC2,0xE8, + 0xEF,0x72,0x83,0xAF,0x3E,0x2F,0x20,0x83,0x08,0x61,0xD8,0x6A,0x1A,0x71,0x68,0xB8, + 0x21,0x1F,0x0E,0xA8,0x2A,0xDA,0xF0,0x87,0xB1,0xAC,0xCE,0xAB,0xFB,0x9C,0xBC,0x43, + 0x04,0xE5,0x2F,0xF3,0x7D,0xAD,0x78,0x43,0x00,0x74,0x65,0x28,0x8D,0x3F,0x27,0x8F, + 0x33,0x7B,0x36,0xCD,0xAF,0x35,0x33,0xAF,0x06,0xF5,0x22,0x67,0xC7,0xD1,0x88,0x9B, + 0x55,0xE8,0x0E,0x48,0x5F,0x9A,0x30,0x5A,0xF5,0x93,0x53,0x78,0x44,0x8B,0x3A,0xB6, + 0x24,0x7F,0x5D,0x6E,0xDB,0x68,0x72,0x15,0xAD,0xB8,0x3E,0x66,0xE7,0x0E,0x99,0xEB, + 0xAB,0x1D,0x91,0xC8,0xEF,0x5A,0x32,0xA9,0x3E,0x0B,0x82,0x4E,0x5A,0x64,0xC1,0xC5, + 0xFD,0xD0,0x93,0xE0,0x82,0x39,0x7C,0x94,0x78,0x23,0x5D,0x5E,0x65,0x67,0xB9,0x83, + 0xEB,0x3A,0xC6,0x6C,0x65,0x8A,0xC6,0x83,0x2F,0x90,0x4C,0x75,0x7F,0x7A,0x2F,0x3E, + 0xA8,0xAA,0x16,0xF5,0x67,0x5D,0x50,0xC7,0x0E,0x7F,0x7C,0xA2,0xC8,0x10,0x67,0xFD, + 0x3E,0x91,0xA4,0xD5,0xA0,0xF6,0x9D,0x5A,0x0E,0x56,0xC0,0xCA,0xBA,0xB4,0x8B,0xB1, + 0xB5,0x3A,0x22,0xC0,0xEC,0xF8,0x8F,0xD7,0x49,0xBE,0x8D,0x98,0xE0,0x30,0x0E,0x45, + 0x4E,0x44,0x43,0x45,0x52,0x54,0x49,0x46,0x49,0x43,0x41,0x54,0x41,0x3D,0x3D +}; + +unsigned char TestIdentity_p12[2697] = { + 0x30, 0x82, 0x0a, 0x85, 0x02, 0x01, 0x03, 0x30, 0x82, 0x0a, 0x4c, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x0a, 0x3d, 0x04, 0x82, 0x0a, 0x39, 0x30, 0x82, 0x0a, 0x35, 0x30, 0x82, + 0x04, 0xbf, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x04, 0xb0, 0x30, 0x82, 0x04, 0xac, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x04, 0xa5, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x6c, 0x66, 0xc0, + 0x46, 0x37, 0xb4, 0x92, 0x0b, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x04, + 0x78, 0x6d, 0xb4, 0x7c, 0xb4, 0x7f, 0x50, 0xfb, 0x09, 0x7a, 0xb5, 0x77, + 0x13, 0x05, 0x98, 0x98, 0x04, 0x34, 0xd1, 0xc9, 0xca, 0x97, 0x69, 0x33, + 0x28, 0xda, 0x58, 0xa6, 0x82, 0x0e, 0x1e, 0x05, 0x46, 0x47, 0x77, 0x90, + 0xa1, 0xd6, 0x2b, 0xb9, 0x18, 0x89, 0x3c, 0x8a, 0x2e, 0xec, 0xd3, 0x98, + 0x0b, 0x7b, 0x63, 0x12, 0xf3, 0x5d, 0x62, 0xc4, 0x8d, 0x52, 0xaa, 0xab, + 0x67, 0xde, 0x46, 0x93, 0xdc, 0x9d, 0x1d, 0x29, 0xfb, 0x34, 0x7b, 0x84, + 0xfa, 0x1f, 0x5b, 0x53, 0x1d, 0xab, 0x9e, 0x62, 0x4f, 0x48, 0x4e, 0xd0, + 0x99, 0x1a, 0xfc, 0x60, 0x99, 0x71, 0x3f, 0xe2, 0xd7, 0xc5, 0xb2, 0x34, + 0x24, 0x85, 0x3f, 0x3a, 0x4a, 0x40, 0x34, 0xa8, 0xc5, 0xbc, 0xa3, 0xfe, + 0x3a, 0x7c, 0xdc, 0x96, 0xf3, 0x34, 0x8b, 0xc1, 0xb0, 0xb0, 0x3f, 0x51, + 0xe2, 0x6d, 0x5e, 0x76, 0xb8, 0x44, 0x8d, 0xff, 0x65, 0xe3, 0x42, 0x05, + 0x30, 0xa0, 0x78, 0x7f, 0x69, 0xc7, 0x6f, 0x82, 0x05, 0x20, 0x69, 0x64, + 0x59, 0x84, 0xe1, 0x42, 0x37, 0x41, 0xc5, 0x78, 0x15, 0x2b, 0x77, 0x20, + 0xb8, 0x31, 0x4b, 0x4d, 0xbd, 0x2d, 0xa5, 0xce, 0x65, 0x56, 0xfb, 0x5a, + 0xfc, 0xe1, 0xdb, 0x60, 0x20, 0x1b, 0x5a, 0x91, 0x53, 0x36, 0x62, 0xdf, + 0xb5, 0x4e, 0xf2, 0xc9, 0xce, 0xeb, 0xd4, 0x85, 0xf9, 0xe6, 0x8b, 0x60, + 0xf3, 0x99, 0xfa, 0x4c, 0x13, 0x35, 0x8f, 0x17, 0x3b, 0xe3, 0x74, 0xc7, + 0x7e, 0xb1, 0xf6, 0x8f, 0x4d, 0xdd, 0x40, 0xd6, 0x31, 0x84, 0x83, 0x54, + 0x75, 0x7a, 0xc0, 0xa7, 0xc4, 0x3a, 0xc8, 0x17, 0x87, 0x0d, 0x8f, 0x4f, + 0x0f, 0x8e, 0x6e, 0x08, 0xb8, 0x0a, 0x86, 0x61, 0x03, 0x18, 0xad, 0xd3, + 0x43, 0xe7, 0x87, 0x62, 0x3e, 0x6c, 0xb5, 0x30, 0x81, 0xe0, 0x69, 0xe3, + 0x6a, 0x1f, 0x3c, 0x5f, 0x48, 0xa6, 0x38, 0x06, 0xbf, 0x5e, 0x43, 0x05, + 0xc8, 0x66, 0x97, 0xdd, 0x1c, 0x25, 0xba, 0x20, 0x44, 0xc6, 0x05, 0x31, + 0xdd, 0x6a, 0xc1, 0x10, 0xe0, 0x63, 0x80, 0xac, 0x0b, 0x55, 0x83, 0x75, + 0xc2, 0xb3, 0x39, 0xb7, 0x6b, 0x7c, 0xf6, 0x69, 0x3d, 0x6c, 0xcd, 0x35, + 0xaf, 0x25, 0xb0, 0xb2, 0x0a, 0xff, 0x33, 0xf3, 0x41, 0x38, 0x39, 0xa6, + 0xd0, 0x38, 0xb5, 0x89, 0xd5, 0xf0, 0x3c, 0x5c, 0x29, 0x8f, 0xc8, 0x1c, + 0x74, 0xe9, 0x35, 0xc8, 0x9e, 0x3a, 0xcd, 0x84, 0xdb, 0x95, 0x55, 0x57, + 0xa8, 0xe7, 0xc5, 0x58, 0xa8, 0xe6, 0xb0, 0x34, 0xbd, 0xa4, 0x00, 0x0c, + 0xb3, 0x1a, 0x00, 0xb2, 0x7d, 0xcd, 0x74, 0x22, 0xaa, 0x8f, 0x0d, 0xe4, + 0x99, 0x26, 0xcd, 0x81, 0x4f, 0xe1, 0xe1, 0x96, 0x41, 0xc6, 0x08, 0x1b, + 0x2c, 0xc7, 0x9e, 0xe6, 0x63, 0x4a, 0x1c, 0x4d, 0xbb, 0x44, 0xeb, 0xb9, + 0xd5, 0x7a, 0x55, 0xd2, 0x58, 0xa0, 0x8f, 0x4b, 0xf1, 0xdf, 0xc6, 0x67, + 0x7c, 0xe8, 0xf5, 0x65, 0xca, 0x52, 0xdd, 0xa6, 0x7c, 0xa9, 0x0d, 0x7e, + 0xec, 0x12, 0x57, 0xef, 0x09, 0x78, 0xdf, 0x40, 0x48, 0xb3, 0x6c, 0xad, + 0xef, 0x5a, 0x81, 0x44, 0xdc, 0x1f, 0x66, 0xf6, 0x2c, 0xbe, 0xf6, 0x07, + 0xc8, 0xb8, 0xff, 0xf3, 0x52, 0xe5, 0x15, 0xc8, 0xe0, 0xc9, 0x60, 0xea, + 0x26, 0x21, 0xa3, 0x21, 0x99, 0x00, 0x84, 0x18, 0x5c, 0x84, 0x16, 0xd0, + 0xf1, 0x63, 0x56, 0x7b, 0xf6, 0x66, 0x43, 0xcc, 0x1e, 0x3c, 0x1a, 0x8d, + 0x8d, 0x3f, 0xf6, 0xf1, 0xcf, 0x04, 0xbf, 0xfb, 0x96, 0x63, 0x50, 0x61, + 0xfd, 0x59, 0x66, 0x2e, 0xd7, 0xb4, 0xd8, 0x63, 0x94, 0xe1, 0x59, 0x96, + 0x9c, 0x31, 0x8a, 0x7a, 0x6d, 0x3a, 0x79, 0xb6, 0xb9, 0xb3, 0xc3, 0xc3, + 0xb8, 0xd3, 0x01, 0x02, 0x94, 0xec, 0x3a, 0x0c, 0x0e, 0x43, 0xef, 0x67, + 0x95, 0xe6, 0xef, 0xa3, 0x98, 0x03, 0x8e, 0x7d, 0x38, 0xd4, 0xaa, 0xd3, + 0xb1, 0x2c, 0x2b, 0x02, 0x76, 0x48, 0x7c, 0x5d, 0x74, 0x0e, 0x43, 0x00, + 0xf8, 0xc7, 0x65, 0xb3, 0x0d, 0xd3, 0xc3, 0x06, 0xe1, 0x77, 0xa7, 0x54, + 0x85, 0x81, 0xcb, 0xfd, 0x79, 0x0a, 0xe2, 0x9f, 0xe9, 0xe6, 0x9d, 0xc6, + 0xa7, 0x5b, 0xc6, 0xb1, 0x2a, 0xe1, 0x9c, 0x79, 0x81, 0xa6, 0xac, 0x57, + 0xa7, 0xe5, 0x96, 0x3e, 0xb7, 0x49, 0xc2, 0xcf, 0x71, 0x5b, 0x90, 0x3b, + 0x59, 0x9a, 0x69, 0x24, 0x5f, 0xb7, 0x73, 0xad, 0x2c, 0x35, 0xbe, 0xcc, + 0xd2, 0xb0, 0xe5, 0x3e, 0x86, 0x72, 0xbb, 0xe5, 0x0f, 0x34, 0x1c, 0xd5, + 0x33, 0x78, 0x41, 0xf3, 0xb8, 0x3b, 0x2f, 0x63, 0x87, 0x48, 0x05, 0xc4, + 0x29, 0x98, 0x60, 0x2f, 0xab, 0x87, 0x65, 0xdd, 0x22, 0x30, 0x48, 0xc5, + 0x68, 0x29, 0xbf, 0x0d, 0x53, 0x10, 0x0f, 0x9e, 0x6d, 0xff, 0x4f, 0x9e, + 0xab, 0x27, 0xb9, 0xca, 0xa8, 0x69, 0x5c, 0x36, 0x25, 0x48, 0xac, 0x84, + 0xcb, 0x65, 0x75, 0xec, 0xc4, 0x21, 0xf5, 0x02, 0x9d, 0x4d, 0xa9, 0x58, + 0x20, 0xae, 0x03, 0x14, 0xe4, 0x99, 0xe1, 0x22, 0x41, 0x49, 0x6b, 0x5b, + 0x8e, 0x22, 0xb8, 0x12, 0x7e, 0x79, 0xe6, 0x74, 0x91, 0xaa, 0xf3, 0x98, + 0xd8, 0x4c, 0xc1, 0xb6, 0xd7, 0x21, 0x94, 0x38, 0xa1, 0xd1, 0xa7, 0x18, + 0x90, 0xf1, 0x60, 0xef, 0x69, 0x05, 0x26, 0xbe, 0x76, 0xd1, 0xd5, 0x56, + 0x08, 0x02, 0x86, 0x33, 0x7f, 0x7d, 0xc5, 0xf4, 0x62, 0x0b, 0x5f, 0xbf, + 0x6f, 0x58, 0x31, 0xa7, 0xce, 0xe6, 0xeb, 0x5c, 0x68, 0x97, 0xd5, 0x7d, + 0xf3, 0xfb, 0x69, 0x03, 0x50, 0xac, 0x6d, 0x79, 0x83, 0x04, 0x31, 0x6e, + 0x5b, 0x8b, 0x0a, 0x47, 0x14, 0xc1, 0xd2, 0xa2, 0x9d, 0xae, 0x4c, 0xa6, + 0xe9, 0xa6, 0xb1, 0x6d, 0x9b, 0x71, 0x49, 0x89, 0x71, 0x8a, 0x9f, 0xdd, + 0xc8, 0xc1, 0x95, 0x14, 0x69, 0x69, 0x66, 0xd8, 0xd9, 0xa4, 0x37, 0x1a, + 0xdd, 0x47, 0x2c, 0xfb, 0x4a, 0x75, 0x9b, 0x02, 0x9f, 0x56, 0xdd, 0xf2, + 0xbb, 0x24, 0x38, 0x8f, 0x97, 0x9a, 0x0a, 0x61, 0xfa, 0x3b, 0xe6, 0x43, + 0xa9, 0x88, 0xd0, 0x0d, 0x65, 0x1c, 0x55, 0x67, 0x5e, 0x37, 0xd6, 0x50, + 0x0f, 0x58, 0x2e, 0x62, 0xac, 0x02, 0xbc, 0xdb, 0xf3, 0xea, 0xc4, 0x97, + 0x33, 0xf6, 0x48, 0x19, 0xb5, 0x59, 0x76, 0xd0, 0xb1, 0x5c, 0x0f, 0x02, + 0x6b, 0x8b, 0xf8, 0x91, 0x17, 0x15, 0xcb, 0xaf, 0xa7, 0x4f, 0xfe, 0x5a, + 0x04, 0x6f, 0xd8, 0x15, 0xae, 0x59, 0x8e, 0xd4, 0xfc, 0xcd, 0x21, 0xfd, + 0x2a, 0x50, 0x4b, 0x4b, 0x2b, 0x0e, 0xcd, 0xd4, 0x66, 0x99, 0xe8, 0x3d, + 0x6b, 0xad, 0x60, 0x4d, 0x40, 0xd5, 0xf5, 0xe5, 0x85, 0x19, 0xa6, 0xe0, + 0x7e, 0x1c, 0x21, 0x00, 0x04, 0x4a, 0xd2, 0x90, 0xa6, 0xf5, 0xbf, 0xa4, + 0xaf, 0x85, 0x8f, 0xec, 0xdf, 0x6d, 0xae, 0x88, 0xd5, 0x6b, 0x82, 0x8b, + 0x6c, 0xc8, 0xb7, 0x7b, 0x70, 0x16, 0x30, 0xda, 0x97, 0x33, 0x0c, 0x21, + 0x32, 0x54, 0x76, 0xe3, 0x63, 0x45, 0x8a, 0xdf, 0x07, 0xea, 0x23, 0x9b, + 0xf8, 0xbd, 0x91, 0xe2, 0x47, 0x44, 0x55, 0x8e, 0xd2, 0xff, 0x1c, 0xef, + 0x40, 0xe5, 0x69, 0xba, 0xfd, 0x4d, 0x34, 0x96, 0x80, 0x6c, 0x23, 0xbc, + 0x0f, 0x6d, 0xac, 0x6b, 0xa4, 0x69, 0xf8, 0x4a, 0x6e, 0xe6, 0x7a, 0xa9, + 0x1d, 0xf1, 0x51, 0xfe, 0xb5, 0x00, 0x86, 0xb7, 0x8b, 0x72, 0xb3, 0x56, + 0x9d, 0x44, 0xde, 0x38, 0xe7, 0x34, 0xa9, 0xe9, 0x27, 0xfa, 0x48, 0x3f, + 0xc7, 0x17, 0xe2, 0x8c, 0x28, 0xc1, 0xec, 0x90, 0xfe, 0x31, 0xb8, 0xd7, + 0x11, 0x69, 0xf8, 0xa6, 0x61, 0xa8, 0x4b, 0xeb, 0xa4, 0x0d, 0xae, 0x1c, + 0x50, 0xc1, 0x4e, 0x5b, 0xd5, 0xc5, 0x66, 0x89, 0x32, 0x88, 0x3a, 0x40, + 0x0d, 0x6e, 0xb4, 0xf4, 0x29, 0xf9, 0xc8, 0x85, 0xe3, 0x0a, 0xe0, 0xb6, + 0xb3, 0x49, 0x70, 0xf6, 0x5d, 0xd2, 0x62, 0x41, 0x92, 0x6e, 0xb5, 0x5d, + 0x85, 0xf0, 0x1e, 0xb8, 0xca, 0xbb, 0x07, 0x88, 0x6f, 0x69, 0xea, 0xe4, + 0xbb, 0x58, 0xb2, 0x6c, 0x86, 0x43, 0x04, 0xb7, 0xef, 0xc0, 0xc2, 0xeb, + 0x82, 0x33, 0xb7, 0x3c, 0xd7, 0x24, 0x40, 0x96, 0x30, 0x60, 0x82, 0xe2, + 0x00, 0x63, 0xd6, 0x06, 0x51, 0xc8, 0x3c, 0x77, 0x6c, 0x33, 0x02, 0x9a, + 0xf4, 0xc5, 0xb7, 0x25, 0x4a, 0x4a, 0x65, 0x8f, 0x04, 0xfb, 0x22, 0xbb, + 0xf0, 0x0f, 0x7e, 0x8b, 0x50, 0x74, 0x2a, 0xcf, 0xc4, 0xcf, 0xe0, 0xe6, + 0x35, 0xf5, 0x89, 0x8f, 0xe0, 0x30, 0x82, 0x05, 0x6e, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x5f, + 0x04, 0x82, 0x05, 0x5b, 0x30, 0x82, 0x05, 0x57, 0x30, 0x82, 0x05, 0x53, + 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, + 0x02, 0xa0, 0x82, 0x04, 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, + 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, + 0x0e, 0x04, 0x08, 0x38, 0xc0, 0x89, 0x4d, 0x2c, 0xbc, 0x90, 0xef, 0x02, + 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0x63, 0xb1, 0xd7, 0x6a, 0x1a, + 0x2f, 0xd9, 0xee, 0x2b, 0xf6, 0x92, 0x2d, 0xf8, 0x90, 0x04, 0x0e, 0x62, + 0xa4, 0x0a, 0x96, 0x12, 0x57, 0xe5, 0x95, 0x12, 0x61, 0xc8, 0x3e, 0x7f, + 0xe4, 0x2e, 0xbb, 0xa0, 0xdc, 0x6b, 0x77, 0x58, 0x39, 0xf0, 0xb7, 0x20, + 0xc6, 0x24, 0x6f, 0x24, 0xd9, 0xc4, 0x42, 0xb2, 0x1b, 0x97, 0xf9, 0x71, + 0x70, 0x8d, 0x08, 0x75, 0x65, 0xb8, 0x16, 0xbf, 0x29, 0x1e, 0x1e, 0x42, + 0x1e, 0xa4, 0xda, 0x7e, 0x78, 0xc5, 0x98, 0x9a, 0x79, 0xf4, 0x89, 0x2c, + 0x0e, 0xfa, 0x72, 0x21, 0xde, 0x75, 0x34, 0x55, 0xfb, 0xa1, 0x3a, 0x6a, + 0xc7, 0x0e, 0x68, 0xd8, 0x4b, 0xe4, 0x47, 0x04, 0xa2, 0x92, 0x68, 0xd0, + 0x01, 0xcc, 0x42, 0x1f, 0xdf, 0x24, 0xba, 0xac, 0x05, 0x91, 0x23, 0x96, + 0xf2, 0x94, 0x2d, 0xcb, 0x6f, 0xac, 0xea, 0x7a, 0x52, 0x7c, 0x00, 0xe5, + 0x7c, 0x73, 0xf1, 0xdd, 0x89, 0x05, 0x16, 0x87, 0x08, 0x7a, 0x3d, 0xa9, + 0x48, 0x99, 0x60, 0x01, 0xd7, 0x34, 0xf6, 0x7a, 0x90, 0xc8, 0x00, 0xa0, + 0xc3, 0x97, 0x62, 0x06, 0xab, 0x14, 0x4c, 0x0b, 0x0f, 0x88, 0x59, 0x3c, + 0x40, 0x47, 0x97, 0xcc, 0xa2, 0x6c, 0x5b, 0x09, 0x9c, 0x2d, 0xa2, 0x60, + 0xb4, 0xfe, 0x86, 0x58, 0x22, 0xeb, 0x7e, 0xab, 0xdb, 0x90, 0x00, 0x8d, + 0x59, 0xb5, 0xfa, 0x8d, 0x3f, 0x7a, 0x02, 0x4b, 0x5e, 0x11, 0x24, 0x95, + 0x6f, 0xad, 0x2c, 0x15, 0xd7, 0x76, 0xa3, 0x8c, 0xfa, 0x38, 0xf5, 0x5a, + 0x2e, 0xd8, 0xee, 0x7d, 0xd7, 0xde, 0x67, 0x7c, 0x27, 0xd0, 0x4a, 0x18, + 0xbb, 0x7c, 0x15, 0x13, 0x37, 0xd2, 0xce, 0x9d, 0xf9, 0xf6, 0x10, 0xb8, + 0xbd, 0x39, 0xa3, 0x27, 0xf2, 0x93, 0x8a, 0x6f, 0x4c, 0xe2, 0xca, 0x13, + 0xf1, 0x2c, 0x22, 0x3b, 0x8a, 0x45, 0xf9, 0x06, 0x23, 0x9f, 0x8d, 0xa1, + 0xd9, 0x35, 0x08, 0xb4, 0xdb, 0x48, 0x86, 0x64, 0x42, 0x0f, 0x4e, 0x5d, + 0xa9, 0xf2, 0x2c, 0xbd, 0x22, 0xcb, 0xa5, 0xbf, 0x40, 0xdd, 0x21, 0x80, + 0x23, 0xa4, 0xee, 0xc2, 0x9d, 0xb8, 0x78, 0x49, 0x82, 0x5e, 0x32, 0x85, + 0xb5, 0xfe, 0x28, 0x61, 0x13, 0xb3, 0x1e, 0x66, 0xad, 0xcc, 0x10, 0x7f, + 0x9e, 0x2f, 0x12, 0x38, 0x79, 0x6d, 0x59, 0x6b, 0xd6, 0x9d, 0xa7, 0xb7, + 0xec, 0x55, 0xb6, 0x98, 0xb6, 0x63, 0xd1, 0x3c, 0x35, 0x4a, 0x0b, 0xc1, + 0x4f, 0x5b, 0xca, 0x13, 0x7f, 0xe6, 0xc3, 0xc5, 0x89, 0x02, 0xf6, 0xfd, + 0x33, 0x79, 0x53, 0x07, 0xe6, 0xdf, 0xc1, 0x01, 0xb4, 0x74, 0x2c, 0x72, + 0x3d, 0x3c, 0xf6, 0xfa, 0x28, 0x73, 0x48, 0x08, 0x55, 0x4f, 0xc5, 0xb2, + 0x73, 0xd6, 0xa1, 0x27, 0xee, 0xdf, 0x89, 0x1c, 0x7c, 0x90, 0x2a, 0x9c, + 0x0f, 0x15, 0x19, 0x6f, 0x53, 0x5f, 0x99, 0xc6, 0x9b, 0x7a, 0x19, 0x08, + 0x1c, 0xe2, 0x7e, 0x22, 0x53, 0xd9, 0xe1, 0x1e, 0x35, 0xe4, 0xb1, 0xbd, + 0xdc, 0xcd, 0xf3, 0x0e, 0x31, 0x7e, 0x14, 0xea, 0x6e, 0x7f, 0x9f, 0xc7, + 0x94, 0x23, 0x42, 0x10, 0xa0, 0x32, 0x9c, 0x94, 0x09, 0xae, 0x79, 0xa2, + 0x6b, 0x6b, 0x1a, 0xf5, 0xda, 0xaf, 0xe9, 0xb3, 0xf5, 0xac, 0x75, 0xec, + 0xdb, 0xcb, 0x5c, 0x21, 0xc5, 0x7f, 0x57, 0x9e, 0xbe, 0x2d, 0xea, 0x59, + 0x8e, 0x5d, 0x88, 0x15, 0x1a, 0xfe, 0xc5, 0xaa, 0xc6, 0x68, 0x90, 0x79, + 0xd1, 0xba, 0x5d, 0xdd, 0x05, 0x90, 0xdf, 0x3c, 0x0f, 0x69, 0x11, 0x33, + 0x57, 0x6b, 0x99, 0xf7, 0x9a, 0x35, 0x07, 0x07, 0x7d, 0x28, 0x19, 0xba, + 0xac, 0x24, 0x15, 0xbd, 0x18, 0x20, 0x0b, 0xe1, 0x0b, 0x22, 0xfa, 0x03, + 0x14, 0xc8, 0x9d, 0x0e, 0x2a, 0xa4, 0x1d, 0x15, 0x91, 0x8a, 0x06, 0x02, + 0x1d, 0xe7, 0xfe, 0x2b, 0x97, 0xd1, 0x7a, 0xbb, 0x5a, 0xc1, 0x76, 0xfd, + 0x4f, 0xda, 0x87, 0xbb, 0xd4, 0xcc, 0x32, 0x12, 0xb1, 0xeb, 0xc9, 0xaa, + 0xd1, 0xe3, 0x32, 0x5d, 0xde, 0x1f, 0x4a, 0x31, 0x4d, 0x25, 0x03, 0xe2, + 0xc8, 0x44, 0xe5, 0x48, 0xab, 0x45, 0xf4, 0xe4, 0x4d, 0xd7, 0x7b, 0x0b, + 0x46, 0x80, 0xca, 0x38, 0x3b, 0x40, 0x31, 0x15, 0x5e, 0x90, 0x60, 0x0b, + 0x21, 0x29, 0xff, 0x39, 0x59, 0xaa, 0x71, 0x0b, 0xfc, 0xda, 0x23, 0xbb, + 0xdb, 0x2a, 0xe2, 0x9c, 0x8c, 0xf0, 0xf0, 0x33, 0x67, 0xff, 0xd1, 0x29, + 0x0d, 0xe2, 0xc4, 0x36, 0x4c, 0x35, 0x87, 0x8f, 0xb4, 0x61, 0x32, 0x07, + 0x56, 0x77, 0x31, 0x36, 0x6e, 0x62, 0xe8, 0x95, 0xee, 0x93, 0x05, 0x48, + 0xa3, 0xd9, 0x85, 0x42, 0xd4, 0x1f, 0x84, 0x75, 0x1d, 0x31, 0x88, 0x08, + 0xc7, 0x5c, 0xae, 0x00, 0xcf, 0x8b, 0x18, 0x36, 0x40, 0x98, 0x57, 0x5f, + 0xb2, 0x09, 0xeb, 0xd7, 0xc6, 0xbd, 0x4f, 0xa4, 0x50, 0x31, 0xb2, 0x2d, + 0x7a, 0x62, 0x7a, 0x69, 0x45, 0x3d, 0x22, 0x65, 0x7b, 0x92, 0x50, 0xfa, + 0xaa, 0x9d, 0x97, 0xb3, 0x40, 0x5f, 0x79, 0x72, 0x77, 0x24, 0x4d, 0x81, + 0x7d, 0x98, 0xeb, 0x1f, 0x39, 0x90, 0x5d, 0x94, 0x70, 0xe5, 0xc5, 0x00, + 0xb0, 0xfe, 0x0f, 0x45, 0x0e, 0xdb, 0x25, 0x1d, 0xe9, 0xa0, 0x1d, 0x29, + 0x2a, 0x0c, 0x9d, 0x6a, 0x19, 0xbd, 0x39, 0xe3, 0x5c, 0x0f, 0xc8, 0x29, + 0xb5, 0xd8, 0xf7, 0x57, 0xfd, 0x3c, 0x8c, 0xcb, 0x8b, 0x09, 0x5e, 0xe0, + 0x6c, 0xfe, 0xf2, 0x7c, 0x34, 0x8b, 0x07, 0x5e, 0x80, 0x9c, 0xc0, 0xe4, + 0x54, 0x54, 0xbc, 0xc5, 0x82, 0x30, 0x2c, 0xe5, 0xfe, 0xf0, 0x4e, 0xd1, + 0x6a, 0x5f, 0x70, 0x77, 0x3f, 0x2e, 0x57, 0x7f, 0x9e, 0x28, 0x34, 0x78, + 0x15, 0xb1, 0xd6, 0xa6, 0xfb, 0x08, 0x11, 0x2a, 0xd6, 0xa5, 0xb4, 0x24, + 0x6a, 0xd0, 0x8d, 0x4b, 0xa9, 0x54, 0x8f, 0x65, 0xb9, 0x2b, 0x3e, 0x13, + 0x80, 0x05, 0x6c, 0x83, 0x90, 0x33, 0x48, 0x1f, 0xe5, 0x4d, 0xef, 0x22, + 0x48, 0xa0, 0xbe, 0xf7, 0x4d, 0x91, 0x3d, 0xea, 0x07, 0x72, 0x83, 0x33, + 0xa4, 0x7a, 0x66, 0x2e, 0xce, 0x09, 0x10, 0xe2, 0xeb, 0xc5, 0xfa, 0x70, + 0x11, 0x52, 0x36, 0xd6, 0xc7, 0x72, 0x65, 0x9f, 0xdd, 0xdc, 0x6a, 0x19, + 0x3e, 0x14, 0x25, 0x59, 0x00, 0x20, 0xf0, 0xc2, 0x51, 0x14, 0x14, 0x16, + 0x9b, 0xeb, 0x18, 0x01, 0x4e, 0x93, 0xbf, 0xe8, 0xc0, 0x46, 0xec, 0x97, + 0xc6, 0x54, 0x3e, 0x56, 0xd3, 0x04, 0x6e, 0xa5, 0xba, 0xe9, 0xa8, 0x71, + 0x49, 0x83, 0xea, 0x0d, 0x83, 0x4e, 0x43, 0x96, 0x1e, 0x7d, 0x4b, 0x60, + 0x06, 0xd7, 0xb3, 0x48, 0xa2, 0xd8, 0xa4, 0x78, 0x1e, 0x23, 0x07, 0xb9, + 0xb4, 0x6b, 0xfd, 0xde, 0x1d, 0x01, 0xd0, 0x5b, 0x41, 0x87, 0xc5, 0xa4, + 0x0c, 0x5a, 0x0f, 0x17, 0x1c, 0x19, 0x79, 0xf3, 0x79, 0x55, 0x0a, 0x3d, + 0x67, 0xf8, 0x83, 0x02, 0xa3, 0xb3, 0xc6, 0xdc, 0x7c, 0xf0, 0x42, 0xfc, + 0x27, 0x9e, 0x02, 0xbe, 0x57, 0x9f, 0xcf, 0x5d, 0x7a, 0x14, 0xa9, 0xb1, + 0x2b, 0xc8, 0x91, 0x4c, 0x9f, 0x09, 0x9c, 0x44, 0xbd, 0xb7, 0x9f, 0x7b, + 0x3a, 0xa8, 0xec, 0x7f, 0xac, 0x0b, 0xf6, 0xdd, 0xb8, 0x23, 0xf6, 0x07, + 0xab, 0x6b, 0x7d, 0xbf, 0x1b, 0x33, 0xf2, 0x1e, 0x38, 0x0e, 0x47, 0x0f, + 0xfe, 0x3e, 0x26, 0x07, 0x8a, 0xb4, 0x3d, 0xc7, 0x02, 0x0f, 0x75, 0xb5, + 0x84, 0x74, 0x2d, 0x84, 0x43, 0x53, 0x79, 0x2e, 0xfe, 0xdd, 0xaf, 0x74, + 0x1b, 0x39, 0xb1, 0x20, 0x55, 0x97, 0xdc, 0x7c, 0x5f, 0x03, 0x9b, 0x97, + 0xd6, 0x26, 0x84, 0x81, 0x4d, 0xc1, 0x76, 0x6f, 0xaf, 0xd0, 0xee, 0x2b, + 0xee, 0x55, 0x11, 0x40, 0xfd, 0x93, 0xa0, 0x6c, 0x03, 0x47, 0x2c, 0xe8, + 0x3a, 0x36, 0xfd, 0xec, 0xa0, 0xbf, 0xeb, 0x59, 0xa9, 0x85, 0x79, 0xdf, + 0xfa, 0x70, 0x9b, 0xca, 0x78, 0x38, 0x57, 0x38, 0xed, 0x9b, 0xf6, 0xa2, + 0xa2, 0xfe, 0xd9, 0x31, 0x25, 0x80, 0xda, 0x0d, 0xb9, 0x33, 0x90, 0x17, + 0xe6, 0x5a, 0xa2, 0x04, 0xa1, 0x05, 0x74, 0x9a, 0x2d, 0x00, 0xde, 0x68, + 0x81, 0x68, 0x91, 0xe5, 0x6d, 0x55, 0xf4, 0x57, 0xd1, 0x71, 0x87, 0xd6, + 0x4b, 0xdb, 0x65, 0x53, 0x05, 0xfd, 0x78, 0x91, 0x78, 0xc0, 0xdf, 0xb9, + 0x39, 0xb2, 0x02, 0x79, 0x25, 0x3b, 0x26, 0x45, 0x6a, 0x2f, 0x87, 0x68, + 0xf6, 0x13, 0x14, 0xa6, 0xef, 0xf4, 0x39, 0xf7, 0x51, 0x2f, 0xcb, 0x2c, + 0xea, 0x7c, 0xa6, 0x43, 0x91, 0x8c, 0x33, 0xa3, 0x64, 0x45, 0x2b, 0x11, + 0x57, 0x3c, 0x60, 0xf5, 0xf0, 0x23, 0x0f, 0xd4, 0xe0, 0x6b, 0xd1, 0x97, + 0xeb, 0x77, 0x3a, 0xa3, 0x53, 0x9f, 0xa0, 0xe5, 0x9f, 0x17, 0x0a, 0xbd, + 0x2b, 0xc3, 0x04, 0xe7, 0x22, 0xcc, 0xed, 0x8a, 0xe9, 0xa3, 0x1c, 0xfe, + 0x2a, 0x8d, 0x29, 0x81, 0xb6, 0x78, 0x3e, 0x20, 0x91, 0x58, 0xb4, 0xc5, + 0x6d, 0x6a, 0xf2, 0x1d, 0x4b, 0xf7, 0x52, 0x28, 0x3a, 0xea, 0x8a, 0x10, + 0xf6, 0x3c, 0x06, 0x19, 0x6b, 0x14, 0xb2, 0xf9, 0x2e, 0xb6, 0x58, 0x86, + 0x57, 0xfa, 0xf0, 0x8f, 0x2c, 0xa5, 0x0b, 0x31, 0x52, 0x30, 0x2b, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x1e, + 0x1e, 0x1c, 0x00, 0x52, 0x00, 0x61, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, + 0x00, 0x20, 0x00, 0x31, 0x00, 0x37, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, + 0x00, 0x32, 0x00, 0x32, 0x00, 0x37, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x91, + 0xe9, 0x30, 0xa4, 0xec, 0x77, 0x61, 0x86, 0x5c, 0x44, 0x3d, 0xf0, 0x08, + 0xc3, 0xdc, 0x9f, 0x6f, 0x20, 0x21, 0xba, 0x30, 0x30, 0x30, 0x21, 0x30, + 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, + 0xc4, 0xc3, 0xdb, 0x6c, 0x25, 0xc2, 0xdb, 0x25, 0xbb, 0x9b, 0x1b, 0xab, + 0x04, 0x66, 0x32, 0x08, 0x46, 0x04, 0x94, 0xe6, 0x04, 0x08, 0xc8, 0x12, + 0xa3, 0x2a, 0xbd, 0x3f, 0xce, 0x3d, 0x02, 0x01, 0x01 +}; + +int verbose = 0; + +static int TestSignAndVerifyDataWithIdentity(SecIdentityRef identity) +{ + CMSEncoderRef encoder = NULL; + CMSDecoderRef decoder = NULL; + CFDataRef signedData = NULL; + OSStatus status; + int result = 0; + + status = CMSEncoderCreate(&encoder); + ok_status(status, "%s: CMSEncoderCreate", testName); + if (status) { + fprintf(stderr, "Unable to create encoder: error %d\n", (int)status); + return (++result); + } + + status = CMSEncoderAddSigners(encoder, identity); + ok_status(status, "%s: CMSEncodingAddSigners", testName); + if (status) { + fprintf(stderr, "Unable to add signers: error %d\n", (int)status); + return (++result); + } + + status = CMSEncoderSetCertificateChainMode(encoder, kCMSCertificateSignerOnly); + ok_status(status, "%s: CMSEncoderSetCertificateChainMode", testName); + if (status) { + fprintf(stderr, "Unable to set chain mode: error %d\n", (int)status); + return (++result); + } + + const uint8_t blob[12] = {'j','a','b','b','e','r','w','o','c','k','y','\0'}; + + status = CMSEncoderUpdateContent(encoder, blob, sizeof(blob)); + ok_status(status, "%s: CMSEncoderUpdateContent", testName); + if (status) { + fprintf(stderr, "Unable to update content: error %d\n", (int)status); + return (++result); + } + + status = CMSEncoderCopyEncodedContent(encoder, &signedData); + ok_status(status, "%s: CMSEncoderCopyEncodedContent", testName); + if (status || !signedData) { + fprintf(stderr, "Unable to encode content: error %d\n", (int)status); + return (++result); + } + + /* Verify the content... */ + status = CMSDecoderCreate(&decoder); + ok_status(status, "%s: CMSDecoderCreate", testName); + if (status) { + fprintf(stderr, "Unable to create decoder: error %d\n", (int)status); + return (++result); + } + + status = CMSDecoderUpdateMessage(decoder, (const void*)CFDataGetBytePtr(signedData), (size_t)CFDataGetLength(signedData)); + ok_status(status, "%s: CMSDecoderUpdateMessage", testName); + if (status) { + fprintf(stderr, "Unable to decode message: error %d\n", (int)status); + return (++result); + } + + status = CMSDecoderFinalizeMessage(decoder); + ok_status(status, "%s: CMSDecoderFinalizeMessage", testName); + if (status) { + fprintf(stderr, "Unable to finalize message: error %d\n", (int)status); + return (++result); + } + + CMSSignerStatus signerStatus=0; + OSStatus verifyResult=0; + SecPolicyRef policy = SecPolicyCreateBasicX509(); + status = CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, NULL, &verifyResult); + ok_status(status, "%s: CMSDecoderCopySignerStatus", testName); + if (status) { + fprintf(stderr, "Unable to copy signer status: error %d\n", (int)status); + return (++result); + } + + if (verbose) { + fprintf(stdout, "Signer status: %d\n", (int)signerStatus); + } + + is(signerStatus, kCMSSignerValid, "%s: CMS signature verified correctly", testName); + + if (decoder) CFRelease(decoder); + if (encoder) CFRelease(encoder); + if (signedData) CFRelease(signedData); + return result; +} + +static int Test() +{ + SecKeychainRef goodKeychain=NULL; + SecKeychainRef badKeychain=NULL; + SecCertificateRef goodLeaf=NULL, badLeaf=NULL, root=NULL; + CFDataRef tmpData=NULL; + CFArrayRef items=NULL; + SecKeyRef privateKey=NULL; + SecIdentityRef identity=NULL; + OSStatus status; + int result = 0; + + goodKeychain = createNewKeychain("test_rdar17159227_good.keychain", "password"); + badKeychain = createNewKeychain("test_rdar17159227_bad.keychain", "password"); + + /* get certificates */ + tmpData = CFDataCreateWithBytesNoCopy(NULL, leafSigningCertificate, + sizeof(leafSigningCertificate), kCFAllocatorNull); + goodLeaf = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); + + tmpData = CFDataCreateWithBytesNoCopy(NULL, bogusTrailingBytesSigningCertificate, + sizeof(bogusTrailingBytesSigningCertificate), kCFAllocatorNull); + badLeaf = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); + + tmpData = CFDataCreateWithBytesNoCopy(NULL, coreOSTestCA, + sizeof(coreOSTestCA), kCFAllocatorNull); + root = SecCertificateCreateWithData(NULL, tmpData); + CFRelease(tmpData); + + ok_status(SecCertificateAddToKeychain(root, goodKeychain), "%s: SecCertificateAddToKeychain (root)", testName); + ok_status(SecCertificateAddToKeychain(goodLeaf, goodKeychain), "%s: SecCertificateAddToKeychain (goodLeaf)", testName); + ok_status(SecCertificateAddToKeychain(badLeaf, badKeychain), "%s: SecCertificateAddToKeychain (badLeaf)", testName); + + /* import P12 container */ + { + CFDataRef p12DataRef = CFDataCreateWithBytesNoCopy(NULL, TestIdentity_p12, + sizeof(TestIdentity_p12), kCFAllocatorNull); + SecExternalFormat format = kSecFormatPKCS12; + SecExternalItemType itemType = kSecItemTypeAggregate; + SecItemImportExportFlags flags = 0; + + + CFTypeRef keyUsages[1] = { kSecAttrCanSign }; + CFArrayRef keyUsagesArray = CFArrayCreate(NULL, keyUsages, 1, &kCFTypeArrayCallBacks); + CFTypeRef keyAttrs[1] = { kSecAttrIsPermanent }; + CFArrayRef keyAttrsArray = CFArrayCreate(NULL, keyAttrs, 1, &kCFTypeArrayCallBacks); + SecItemImportExportKeyParameters keyParams = { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, // uint32_t version + 0, // SecKeyImportExportFlags flags + CFSTR("test"), // CFTypeRef passphrase + NULL, //CFSTR("title"), // CFStringRef alertTitle + NULL, //CFSTR("pw:"), // CFStringRef alertPrompt + NULL, // SecAccessRef accessRef (unspecified, use default) + keyUsagesArray, // CFArrayRef keyUsages + keyAttrsArray // CFArrayRef keyAttributes + }; + status = SecItemImport(p12DataRef, + NULL, &format, &itemType, flags, &keyParams, goodKeychain, &items); + ok_status(status, "%s: SecItemImport", testName); + + CFRelease(keyUsagesArray); + CFRelease(keyAttrsArray); + if (status) { + fprintf(stderr, "Unable to import identity: error %d\n", (int)status); + ++result; + } + } + if (!items || CFArrayGetCount(items) < 1) { + // Private key import succeeded but was not returned, need to look up key + CFTypeRef results = NULL; + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue( query, kSecClass, kSecClassKey ); + CFDictionaryAddValue( query, kSecAttrKeyClass, kSecAttrKeyClassPrivate ); + CFDictionaryAddValue( query, kSecAttrLabel, CFSTR("Radar 17159227") ); + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + + status = SecItemCopyMatching(query, &results); + ok_status(status, "%s: SecItemCopyMatching for private key", testName); + + privateKey = (SecKeyRef)results; + if (status || !results) { + fprintf(stderr, "Unable to find private key: error %d\n", (int)status); + } else if (verbose) { + fprintf(stdout, "Private key found in search: %p\n", privateKey); + } + } + else { + identity=(SecIdentityRef)CFArrayGetValueAtIndex(items,0); + if (identity) CFRetain(identity); + if (verbose) { + fprintf(stdout, "Identity was imported: %p\n", identity); + } + } + if (items) CFRelease(items); + + status = SecIdentityCopyPrivateKey(identity, &privateKey); + ok_status(status, "%s: SecItentityCopyPrivateKey", testName); + + /* Case 1: good leaf certificate, expected to always succeed */ + if (verbose) { + fprintf(stdout, "### cert 1 ###\n"); + } + identity = SecIdentityCreate(kCFAllocatorDefault, goodLeaf, privateKey); + + if (status) { + identity = NULL; + } + if (!identity) { + fprintf(stderr, "Failed to create identity #1: error %d\n", (int)status); + ++result; + } + result += TestSignAndVerifyDataWithIdentity(identity); + if (identity) CFRelease(identity); + + /* Case 2: bad leaf certificate, expected to succeed with the fix for rdar://17159227, but fail without it */ + if (verbose) { + fprintf(stdout, "### cert 2 ###\n"); + } + identity = SecIdentityCreate(kCFAllocatorDefault, badLeaf, privateKey); + if (status) { + identity = NULL; + } + if (!identity) { + fprintf(stderr, "Failed to create identity #2: error %d\n", (int)status); + ++result; + } + result += TestSignAndVerifyDataWithIdentity(identity); + if (identity) CFRelease(identity); + + if (privateKey) CFRelease(privateKey); + + + /* clean up temporary keychains before we leave */ + if (goodKeychain) { + ok_status(SecKeychainDelete(goodKeychain), "%s: SecKeychainDelete", testName); + CFRelease(goodKeychain); + } + if (badKeychain) { + ok_status(SecKeychainDelete(badKeychain), "%s: SecKeychainDelete", testName); + CFRelease(badKeychain); + } + + return result; +} + + +int kc_28_cert_sign(int argc, char *const *argv) +{ + plan_tests(31); + initializeKeychainTests(__FUNCTION__); + + verbose = test_verbose; + + Test(); + + checkPrompts(0, "No prompts"); + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m b/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m new file mode 100644 index 00000000..c12776d0 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-28-p12-import.m @@ -0,0 +1,268 @@ +/* + * 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 xLicense. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#import +#include "keychain_regressions.h" +#include "kc-helpers.h" +#include "kc-item-helpers.h" +#include "kc-key-helpers.h" +#include "kc-identity-helpers.h" + +#import + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// Turn off deprecated API warnings +//#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +static void +verifyPrivateKeyExtractability(BOOL extractable, NSArray *items) +{ + // After importing items, check that private keys (if any) have + // the expected extractable attribute value. + + CFIndex count = [items count]; + is(count, 1, "One identity added"); + + for (id item in items) + { + OSStatus status; + SecKeyRef aKey = NULL; + if (SecKeyGetTypeID() == CFGetTypeID((CFTypeRef)item)) { + aKey = (SecKeyRef) CFRetain((CFTypeRef)item); + fprintf(stdout, "Verifying imported SecKey\n"); + } + else if (SecIdentityGetTypeID() == CFGetTypeID((CFTypeRef)item)) { + status = SecIdentityCopyPrivateKey((SecIdentityRef)item, &aKey); + ok_status(status, "%s: SecIdentityCopyPrivateKey", testName); + } + + ok(aKey, "%s: Have a key to test", testName); + + if (aKey) + { + const CSSM_KEY *cssmKey; + OSStatus status = SecKeyGetCSSMKey(aKey, &cssmKey); + ok_status(status, "%s: SecKeyGetCSSMKey", testName); + if (status != noErr) { + continue; + } + is(cssmKey->KeyHeader.KeyClass, CSSM_KEYCLASS_PRIVATE_KEY, "%s: key is private key", testName); + + if (!(cssmKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY)) { + fprintf(stdout, "Skipping non-private key (KeyClass=%d)\n", cssmKey->KeyHeader.KeyClass); + continue; // only checking private keys + } + BOOL isExtractable = (cssmKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE) ? YES : NO; + is(isExtractable, extractable, "%s: key extractability matches expectations", testName); + + CFRelease(aKey); + } + } +} + +static void +setIdentityPreferenceForImportedIdentity(SecKeychainRef importKeychain, NSString *name, NSArray *items) +{ + CFArrayRef importedItems = (CFArrayRef)items; + + if (importedItems) + { + SecIdentityRef importedIdRef = NULL; + CFIndex dex, numItems = CFArrayGetCount(importedItems); + for(dex=0; dexversion = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + keyParams->passphrase = password; + if (!extractable) + { + // explicitly set the key attributes, omitting the CSSM_KEYATTR_EXTRACTABLE bit + keyParams->keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; + } + } + else // SecItemImport, 10.7 and later (preferred interface) + { + SecItemImportExportKeyParameters *keyParams = (SecItemImportExportKeyParameters *)keyParamsPtr; + memset(keyParams, 0, sizeof(SecItemImportExportKeyParameters)); + keyParams->version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; + keyParams->passphrase = password; + if (!extractable) + { + // explicitly set the key attributes, omitting kSecAttrIsExtractable + keyAttrs = [[NSArray alloc] initWithObjects: (id) kSecAttrIsPermanent, kSecAttrIsSensitive, nil]; + keyParams->keyAttributes = (CFArrayRef) keyAttrs; + } + } + + if (useDeprecatedAPI) // SecKeychainItemImport, deprecated as of 10.7 + { + SecKeyImportExportParameters *keyParams = (SecKeyImportExportParameters *)keyParamsPtr; + + status = SecKeychainItemImport((CFDataRef)p12Data, + NULL, + &externFormat, + &itemType, + 0, /* flags not used (yet) */ + keyParamsPtr, + keychain, + (CFArrayRef*)&outItems); + ok_status(status, "%s: SecKeychainItemImport", testName); + } + else // SecItemImport + { + SecItemImportExportKeyParameters *keyParams = (SecItemImportExportKeyParameters *)keyParamsPtr; + + status = SecItemImport((CFDataRef)p12Data, + NULL, + &externFormat, + &itemType, + 0, /* flags not used (yet) */ + keyParamsPtr, + keychain, + (CFArrayRef*)&outItems); + ok_status(status, "%s: SecItemImport", testName); + } + + verifyPrivateKeyExtractability(extractable, outItems); + + checkN(testName, makeQueryKeyDictionaryWithLabel(keychain, kSecAttrKeyClassPrivate, CFSTR("test_import")), 1); + checkN(testName, addLabel(makeBaseQueryDictionary(keychain, kSecClassCertificate), CFSTR("test_import")), 1); + + setIdentityPreferenceForImportedIdentity(keychain, @"kc-28-p12-import@apple.com", outItems); + + deleteItems((__bridge CFArrayRef) outItems); + + [keyAttrs release]; + [p12Data release]; + [outItems release]; + + return status; +} + +int kc_28_p12_import(int argc, char *const *argv) +{ + plan_tests(70); + initializeKeychainTests(__FUNCTION__); + + SecKeychainRef kc = getPopulatedTestKeychain(); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + removeIdentityPreference(false); // if there's still an identity preference in the keychain, we'll get prompts. Delete it pre-emptively (but don't test about it) + + writeFile(keychainTempFile, test_import_p12, test_import_p12_len); + testP12Import(true, kc, keychainTempFile, CFSTR("password"), false); + testP12Import(true, kc, keychainTempFile, CFSTR("password"), true); + + testP12Import(false, kc, keychainTempFile, CFSTR("password"), false); + testP12Import(false, kc, keychainTempFile, CFSTR("password"), true); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); + CFReleaseNull(kc); + + removeIdentityPreference(true); + + checkPrompts(0, "No prompts while importing items"); + + [pool release]; + + deleteTestFiles(); + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h index e5e89a0c..05c329c2 100644 --- a/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h @@ -28,9 +28,7 @@ #include #include #include "utilities/SecCFRelease.h" - -static char keychainFile[1000]; -static char keychainName[1000]; +#include "kc-helpers.h" #if TARGET_OS_MAC @@ -45,11 +43,24 @@ static SecKeychainRef newKeychain(const char * name) { // Kill the test keychain if it exists. unlink(keychainFile); + unlink(keychainDbFile); + + // Delete from CDSA-land? No tests, here, it'll work or it won't. + SecKeychainOpen(keychainName, &kc); + if(kc) { + SecKeychainDelete(kc); + CFReleaseNull(kc); + } ok_status(SecKeychainCreate(keychainName, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); + + char path[400]; + UInt32 len = sizeof(path); + ok_status(SecKeychainGetPath(kc, &len, path), "%s: SecKeychainGetPath", name); + eq_stringn(path, len, keychainDbFile, strlen(keychainDbFile), "%s: paths do not match", name); return kc; } -#define newKeychainTests 1 +#define newKeychainTests 3 /* name is the name of the test, not the name of the keychain */ static SecKeychainRef newCustomKeychain(const char * name, const char * path, const char * password) { @@ -78,10 +89,48 @@ static SecKeychainRef openCustomKeychain(const char * name, const char * path, c #define openCustomKeychainTests 2 static SecKeychainRef openKeychain(const char * name) { - return openCustomKeychain(name, "test.keychain", NULL); + return openCustomKeychain(name, keychainName, NULL); } #define openKeychainTests (openCustomKeychainTests) +#define checkPartitionIDsTests 3 +static void checkPartitionIDs(const char* name, SecKeychainItemRef item, uint32_t n) { + if(!item) { + for(int i = 0; i < checkPartitionIDsTests; i++) { + fail("%s: checkNoPartitionIDs not passed an item", name); + } + return; + } + SecAccessRef access = NULL; + ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); + + CFArrayRef acllist = NULL; + ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name); + + int partitionIDsFound = 0; + CFStringRef output = NULL; + + if(acllist) { + for(int i = 0; i < CFArrayGetCount(acllist); i++) { + SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(acllist, i); + + CFArrayRef auths = SecACLCopyAuthorizations(acl); + CFRange searchrange = {0, CFArrayGetCount(auths)}; + if(CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationPartitionID)) { + + // found a hash. match it. + partitionIDsFound++; + } + + CFReleaseNull(auths); + } + + CFReleaseNull(acllist); + } + + is(partitionIDsFound, n, "%s: Wrong number of partition IDs found", name); +} + #define getIntegrityHashTests 3 static CFStringRef getIntegrityHash(const char* name, SecKeychainItemRef item) { if(!item) { @@ -145,6 +194,10 @@ static void checkIntegrityHash(const char* name, SecKeychainItemRef item, CFStri printf("%s: Hashes didn't match. Was: ", name); fflush(stdout); CFShow(hash); + printf(" expected: "); + fflush(stdout); + CFShow(expectedHash); + fflush(stdout); fail("Hashes don't match"); } } @@ -172,36 +225,6 @@ static void checkHashesMatch(const char* name, SecKeychainItemRef item, SecKeych } #define checkHashesMatchTests (getIntegrityHashTests + getIntegrityHashTests + 1) -/* Checks to be sure there are N elements in this search, and returns the first - * if it exists. */ -static SecKeychainItemRef checkN(char* testName, const CFDictionaryRef query, uint32_t n) { - CFArrayRef results = NULL; - if(n > 0) { - ok_status(SecItemCopyMatching(query, (CFTypeRef*) &results), "%s: SecItemCopyMatching", testName); - } else { - is(SecItemCopyMatching(query, (CFTypeRef*) &results), errSecItemNotFound, "%s: SecItemCopyMatching (for no items)", testName); - } - CFRelease(query); - - SecKeychainItemRef item = NULL; - if(results) { - is(CFArrayGetCount(results), n, "%s: Wrong number of results", testName); - if(n >= 1) { - ok(item = (SecKeychainItemRef) CFArrayGetValueAtIndex(results, 0), "%s: Couldn't get item", testName); - } else { - pass("make test numbers match"); - } - } else if((!results) && n == 0) { - pass("%s: no results found (and none expected)", testName); - pass("make test numbers match"); - } else { - fail("%s: no results found (and %d expected)", testName, n); - pass("make test numbers match"); - } - return item; -} -#define checkNTests 3 - #pragma clang pop #else diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h index e2f523c1..b6f776c6 100644 --- a/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h @@ -22,6 +22,7 @@ */ #include "kc-30-xara-helpers.h" +#include "kc-item-helpers.h" #ifndef kc_30_xara_item_helpers_h #define kc_30_xara_item_helpers_h @@ -32,98 +33,14 @@ #pragma clang diagnostic ignored "-Wunused-variable" #pragma clang diagnostic ignored "-Wunused-function" - -static CFMutableDictionaryRef makeBaseItemDictionary(CFStringRef itemclass) { - CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); - CFDictionarySetValue(query, kSecClass, itemclass); - - if(CFEqual(itemclass, kSecClassInternetPassword)) { - CFDictionarySetValue(query, kSecAttrServer, CFSTR("test_service")); - CFDictionarySetValue(query, kSecAttrAuthenticationType, CFSTR("dflt")); // Default, I guess? - } else { - // Generic passwords have services - CFDictionarySetValue(query, kSecAttrService, CFSTR("test_service")); - } - return query; -} - -static CFMutableDictionaryRef makeQueryItemDictionary(SecKeychainRef kc, CFStringRef itemclass) { - CFMutableDictionaryRef query = makeBaseItemDictionary(itemclass); - - CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); - CFArrayAppendValue((CFMutableArrayRef)searchList, kc); - CFDictionarySetValue(query, kSecMatchSearchList, searchList); - - CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); - - return query; -} - -static CFMutableDictionaryRef makeQueryCustomItemDictionary(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { - CFMutableDictionaryRef query = makeQueryItemDictionary(kc, itemclass); - CFDictionarySetValue(query, kSecAttrLabel, label); - return query; -} - -static CFMutableDictionaryRef makeAddCustomItemDictionary(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label, CFStringRef account) { - CFMutableDictionaryRef query = makeBaseItemDictionary(itemclass); - - CFDictionaryAddValue(query, kSecUseKeychain, kc); - CFDictionarySetValue(query, kSecAttrAccount, account); - CFDictionarySetValue(query, kSecAttrComment, CFSTR("a comment")); - CFDictionarySetValue(query, kSecAttrLabel, label); - CFDictionarySetValue(query, kSecValueData, CFDataCreate(NULL, (void*)"data", 4)); - return query; -} - -static CFMutableDictionaryRef makeAddItemDictionary(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { - return makeAddCustomItemDictionary(kc, itemclass, label, CFSTR("test_account")); -} - -static SecKeychainItemRef makeCustomItem(const char* name, SecKeychainRef kc, CFDictionaryRef addDictionary) { - CFTypeRef result = NULL; - ok_status(SecItemAdd(addDictionary, &result), "%s: SecItemAdd", name); - ok(result != NULL, "%s: SecItemAdd returned a result", name); - - SecKeychainItemRef item = (SecKeychainItemRef) result; - ok(item != NULL, "%s: Couldn't convert into SecKeychainItemRef", name); - - return item; -} -#define makeCustomItemTests 3 - -static SecKeychainItemRef makeItem(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { - CFMutableDictionaryRef query = makeAddItemDictionary(kc, itemclass, label); - - SecKeychainItemRef item = makeCustomItem(name, kc, query); - - CFReleaseNull(query); - return item; -} -#define makeItemTests makeCustomItemTests - -static void makeCustomDuplicateItem(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { - CFMutableDictionaryRef query = makeAddItemDictionary(kc, itemclass, label); - - CFTypeRef result = NULL; - is(SecItemAdd(query, &result), errSecDuplicateItem, "%s: SecItemAdd (duplicate)", name); - - CFReleaseNull(query); -} -#define makeCustomDuplicateItemTests 1 - -static void makeDuplicateItem(const char* name, SecKeychainRef kc, CFStringRef itemclass) { - return makeCustomDuplicateItem(name, kc, itemclass, CFSTR("test_label")); -} -#define makeDuplicateItemTests makeCustomDuplicateItemTests - static void makeCustomItemWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef label, CFStringRef expectedHash) { SecKeychainItemRef item = makeItem(name, kc, itemclass, label); checkIntegrityHash(name, item, expectedHash); + checkPartitionIDs(name, (SecKeychainItemRef) item, 1); + CFReleaseNull(item); } -#define makeCustomItemWithIntegrityTests (makeItemTests + checkIntegrityHashTests) +#define makeCustomItemWithIntegrityTests (makeItemTests + checkIntegrityHashTests + checkPartitionIDsTests) static void makeItemWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef expectedHash) { makeCustomItemWithIntegrity(name, kc, itemclass, CFSTR("test_label"), expectedHash); @@ -133,19 +50,20 @@ static void makeItemWithIntegrity(const char* name, SecKeychainRef kc, CFStringR static void testAddItem(CFStringRef itemclass, CFStringRef expectedHash) { char name[100]; sprintf(name, "testAddItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); makeItemWithIntegrity(name, kc, itemclass, expectedHash); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testAddItemTests (newKeychainTests + makeItemWithIntegrityTests + 1) static void testCopyMatchingItem(CFStringRef itemclass, CFStringRef expectedHash) { char name[100]; sprintf(name, "testCopyMatchingItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); makeItemWithIntegrity(name, kc, itemclass, expectedHash); @@ -153,13 +71,14 @@ static void testCopyMatchingItem(CFStringRef itemclass, CFStringRef expectedHash SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, itemclass), 1); checkIntegrityHash(name, item, expectedHash); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testCopyMatchingItemTests (newKeychainTests + makeItemWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1) static void testUpdateItem(CFStringRef itemclass, CFStringRef expectedHashOrig, CFStringRef expectedHashAfter) { char name[100]; sprintf(name, "testUpdateItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); makeItemWithIntegrity(name, kc, itemclass, expectedHashOrig); @@ -184,21 +103,23 @@ static void testUpdateItem(CFStringRef itemclass, CFStringRef expectedHashOrig, item = checkN(name, makeQueryItemDictionary(kc, itemclass), 1); checkIntegrityHash(name, item, expectedHashAfter); + checkPartitionIDs(name, item, 1); CFReleaseNull(query); CFReleaseNull(update); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testUpdateItemTests (newKeychainTests + makeItemWithIntegrityTests \ + 1 + checkNTests + checkIntegrityHashTests \ - + 1 + checkNTests + checkIntegrityHashTests \ + + 1 + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + 1) static void testAddDuplicateItem(CFStringRef itemclass, CFStringRef expectedHash) { char name[100]; sprintf(name, "testAddDuplicateItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); makeItemWithIntegrity(name, kc, itemclass, expectedHash); @@ -206,13 +127,14 @@ static void testAddDuplicateItem(CFStringRef itemclass, CFStringRef expectedHash makeDuplicateItem(name, kc, itemclass); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testAddDuplicateItemTests (newKeychainTests + makeItemWithIntegrityTests + makeDuplicateItemTests + 1) static void testDeleteItem(CFStringRef itemclass, CFStringRef expectedHash) { char name[100]; sprintf(name, "testDeleteItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); makeItemWithIntegrity(name, kc, itemclass, expectedHash); @@ -223,6 +145,7 @@ static void testDeleteItem(CFStringRef itemclass, CFStringRef expectedHash) { ok_status(SecKeychainItemDelete(item), "%s: SecKeychainItemDelete", name); checkN(name, makeQueryItemDictionary(kc, itemclass), 0); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testDeleteItemTests (newKeychainTests + makeItemWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1 + checkNTests + 1) @@ -241,34 +164,35 @@ static void writeEmptyV512Keychain(const char* name, const char* keychainFile); static void testUpdateRetainedItem(CFStringRef itemclass) { char name[100]; sprintf(name, "testUpdateRetainedItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); - writeEmptyV512Keychain(name, keychainFile); - SecKeychainRef kc = openCustomKeychain(name, "test.keychain", "password"); + writeEmptyV512Keychain(name, keychainDbFile); + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); SecKeychainItemRef item = makeCustomItem(name, kc, makeAddCustomItemDictionary(kc, itemclass, CFSTR("test_label"), CFSTR("account1"))); CFRelease(checkN(name, makeQueryCustomItemDictionary(kc, itemclass, CFSTR("test_label")), 1)); - is(CFGetRetainCount(item), 1, "%s: CFGetRetainCount(item)", name); + cmp_ok(CFGetRetainCount(item), >=, 1, "%s: CFGetRetainCount(item)", name); // Bump our local database version number a few times, so we'll re-read the database when we reset it later CFReleaseSafe(makeCustomItem(name, kc, makeAddCustomItemDictionary(kc, itemclass, CFSTR("version"), CFSTR("version")))); CFReleaseSafe(makeCustomItem(name, kc, makeAddCustomItemDictionary(kc, itemclass, CFSTR("bump"), CFSTR("bump")))); // Simulate another process deleting the items we just made, and us not receiving the notification - writeEmptyV512Keychain(name, keychainFile); + writeEmptyV512Keychain(name, keychainDbFile); // Generate some keychain notifications on a different keychain so the AppleDatabase will reload test.keychain SecKeychainRef kc2 = newCustomKeychain(name, "unrelated.keychain", "password"); CFReleaseSafe(makeCustomItem(name, kc2, makeAddCustomItemDictionary(kc, itemclass, CFSTR("unrelated1_label"), CFSTR("unrelated1")))); ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", name); + CFReleaseNull(kc2); - secdebugfunc("integrity", "************************************* should reload database\n"); + secnotice("integrity", "************************************* should reload database\n"); SecKeychainItemRef item2 = makeCustomItem(name, kc, makeAddCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label"), CFSTR("account2"))); CFReleaseSafe(checkN(name, makeQueryCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label")), 1)); - is(CFGetRetainCount(item2), 1, "%s: CFGetRetainCount(item2)", name); + cmp_ok(CFGetRetainCount(item2), >=, 1, "%s: CFGetRetainCount(item2)", name); // Now, update the second item so it would collide with the first CFMutableDictionaryRef query = makeQueryCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label")); @@ -277,12 +201,13 @@ static void testUpdateRetainedItem(CFStringRef itemclass) { CFDictionarySetValue(update, kSecAttrLabel, CFSTR("test_label")); ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name); - is(CFGetRetainCount(item), 1, "%s: CFGetRetainCount(item)", name); + cmp_ok(CFGetRetainCount(item), >=, 1, "%s: CFGetRetainCount(item)", name); CFReleaseNull(item); SecKeychainItemRef result = checkN(name, makeQueryCustomItemDictionary(kc, itemclass, CFSTR("test_label")), 1); CFReleaseNull(result); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testUpdateRetainedItemTests (openCustomKeychainTests + makeCustomItemTests + checkNTests \ + 1 + makeCustomItemTests + makeCustomItemTests \ diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h index d9593f19..6ffa8e63 100644 --- a/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h @@ -22,107 +22,26 @@ */ #include "kc-30-xara-helpers.h" +#include "kc-key-helpers.h" #ifndef kc_30_xara_key_helpers_h #define kc_30_xara_key_helpers_h #if TARGET_OS_MAC -static CFMutableDictionaryRef makeBaseKeyDictionary() { - CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionarySetValue(query, kSecClass, kSecClassKey); - return query; -} - -static CFMutableDictionaryRef makeQueryKeyDictionary(SecKeychainRef kc, CFStringRef keyClass) { - CFMutableDictionaryRef query = makeBaseKeyDictionary(); - - CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); - CFArrayAppendValue((CFMutableArrayRef)searchList, kc); - CFDictionarySetValue(query, kSecMatchSearchList, searchList); - - CFDictionarySetValue(query, kSecAttrKeyClass, keyClass); - - CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); - return query; -} - -static CFMutableDictionaryRef makeAddKeyDictionary(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) { - CFMutableDictionaryRef query = makeBaseKeyDictionary(); - CFDictionaryAddValue(query, kSecUseKeychain, kc); - - CFDictionarySetValue(query, kSecAttrLabel, label); - CFDictionarySetValue(query, kSecAttrApplicationLabel, CFSTR("test_application")); // without setting this, it uses the current datetime. - - int32_t n = 0; - if(CFEqual(keyClass, kSecAttrKeyClassSymmetric)) { - CFDictionarySetValue(query, kSecAttrKeyType, kSecAttrKeyTypeAES); - n = 128; - } else if(CFEqual(keyClass, kSecAttrKeyClassPublic) || - CFEqual(keyClass, kSecAttrKeyClassPrivate)) { - CFDictionarySetValue(query, kSecAttrKeyType, kSecAttrKeyTypeRSA); - n = 1024; - } - CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &n); - CFDictionarySetValue(query, kSecAttrKeySizeInBits, num); - - return query; -} - -static SecKeyRef makeCustomKey(const char* name, SecKeychainRef kc, CFStringRef label) { - CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); - - CFErrorRef error = NULL; - SecKeyRef item = SecKeyGenerateSymmetric(query, &error); - ok(item != NULL, "%s: SecKeyGenerateSymmetric errored: %ld", name, error ? CFErrorGetCode(error) : -1); - - CFReleaseNull(query); - return item; -} -#define makeCustomKeyTests 1 - -static SecKeyRef makeKey(const char* name, SecKeychainRef kc) { - return makeCustomKey(name, kc, CFSTR("test_key")); -} -#define makeKeyTests makeCustomKeyTests - - static void makeCustomKeyWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef label, CFStringRef expectedHash) { SecKeyRef key = makeCustomKey(name, kc, label); checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash); + checkPartitionIDs(name, (SecKeychainItemRef) key, 1); CFReleaseNull(key); } -#define makeCustomKeyWithIntegrityTests (makeCustomKeyTests + checkIntegrityHashTests) +#define makeCustomKeyWithIntegrityTests (makeCustomKeyTests + checkIntegrityHashTests + checkPartitionIDsTests) static void makeKeyWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef expectedHash) { makeCustomKeyWithIntegrity(name, kc, CFSTR("test_key"), expectedHash); } #define makeKeyWithIntegrityTests makeCustomKeyWithIntegrityTests -static void makeCustomKeyPair(const char* name, SecKeychainRef kc, CFStringRef label, SecKeyRef* aPub, SecKeyRef* aPriv) { - CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassPublic, label); - - CFErrorRef error = NULL; - SecKeyRef pub; - SecKeyRef priv; - ok_status(SecKeyGeneratePair(query, &pub, &priv), "%s: SecKeyGeneratePair returned a result", name); - - if(aPub) { - *aPub = pub; - } - if(aPriv) { - *aPriv = priv; - } - - CFReleaseNull(query); -} -#define makeCustomKeyPairTests 1 - -static void makeKeyPair(const char* name, SecKeychainRef kc, SecKeyRef* aPub, SecKeyRef* aPriv) { - makeCustomKeyPair(name, kc, CFSTR("test_key"), aPub, aPriv); -} -#define makeKeyPairTests makeCustomKeyPairTests - // Note that this is nearly useless, as key pairs will never have stable hashes static void makeKeyPairWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef expectedPubHash, CFStringRef expectedPrivHash) { SecKeyRef pub; @@ -134,88 +53,6 @@ static void makeKeyPairWithIntegrity(const char* name, SecKeychainRef kc, CFStri } #define makeKeyPairWithIntegrityTests (makeKeyTests + checkIntegrityHashTests) -// This only works for symmetric keys; key pairs cannot ever generate a duplicate (due to setting kSecKeyLabel to the hash of the public key) -static void makeCustomDuplicateKey(const char* name, SecKeychainRef kc, CFStringRef label) { - CFMutableDictionaryRef query; - - query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); - CFErrorRef error = NULL; - SecKeyRef item = SecKeyGenerateSymmetric(query, &error); - is(CFErrorGetCode(error), errSecDuplicateItem, "%s: SecKeyGenerateSymmetric (duplicate) errored: %ld", name, error ? CFErrorGetCode(error) : -1); - - CFReleaseNull(query); -} -#define makeCustomDuplicateKeyTests 1 - -static void makeDuplicateKey(const char* name, SecKeychainRef kc) { - makeCustomDuplicateKey(name, kc, CFSTR("test_key")); -} -#define makeDuplicateKeyTests makeCustomDuplicateKeyTests - -static SecKeyRef makeCustomFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) { - SecKeyRef symkey; - - ok_status(SecKeyGenerate( - NULL, - CSSM_ALGID_AES, 128, - 0, /* contextHandle */ - CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, - CSSM_KEYATTR_EXTRACTABLE, - NULL, /* initialAccess */ - &symkey), "%s: SecKeyGenerate", name);; - - CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); - - CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); - CFArrayAppendValue((CFMutableArrayRef)itemList, symkey); - - CFDictionarySetValue(query, kSecUseItemList, itemList); - - CFTypeRef result = NULL; - ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name); - ok(result != NULL, "%s: SecItemAdd returned a result", name); - CFReleaseNull(symkey); - return (SecKeyRef) result; -} -#define makeCustomFreeKeyTests 3 - -static SecKeyRef makeFreeKey(const char* name, SecKeychainRef kc) { - return makeCustomFreeKey(name, kc, CFSTR("test_free_key")); -} -#define makeFreeKeyTests makeCustomFreeKeyTests - -static SecKeyRef makeCustomDuplicateFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) { - SecKeyRef symkey; - - ok_status(SecKeyGenerate( - NULL, - CSSM_ALGID_AES, 128, - 0, /* contextHandle */ - CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, - CSSM_KEYATTR_EXTRACTABLE, - NULL, /* initialAccess */ - &symkey), "%s: SecKeyGenerate", name);; - - CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); - - CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); - CFArrayAppendValue((CFMutableArrayRef)itemList, symkey); - - CFDictionarySetValue(query, kSecUseItemList, itemList); - - CFTypeRef result = NULL; - is(SecItemAdd(query, &result), errSecDuplicateItem, "%s: SecItemAdd (duplicate)", name); - CFReleaseNull(symkey); - return (SecKeyRef) result; -} -#define makeCustomDuplicateFreeKeyTests 2 - -static SecKeyRef makeDuplicateFreeKey(const char* name, SecKeychainRef kc) { - return makeCustomFreeKey(name, kc, CFSTR("test_free_key")); -} -#define makeDuplicateFreeKeyTests makeCustomDuplicateFreeKeyTests - - // And now for the actual tests static void testAddKey(CFStringRef expectedHash) { @@ -223,6 +60,7 @@ static void testAddKey(CFStringRef expectedHash) { SecKeychainRef kc = newKeychain(name); makeKeyWithIntegrity(name, kc, expectedHash); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testAddKeyTests (newKeychainTests + makeKeyWithIntegrityTests + 1) @@ -236,13 +74,14 @@ static void testAddFreeKey(CFStringRef expectedHash) { //checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash); //ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + //CFReleaseNull(kc); } //#define testAddFreeKeyTests (newKeychainTests + makeFreeKeyTests + checkIntegrityHashTests + 1) #define testAddFreeKeyTests 0 static void testCopyMatchingKey(CFStringRef expectedHash) { char* name = "testCopyMatchingKey"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); @@ -252,13 +91,14 @@ static void testCopyMatchingKey(CFStringRef expectedHash) { SecKeyRef item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); checkIntegrityHash(name, (SecKeychainItemRef) item, expectedHash); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testCopyMatchingKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1) static void testUpdateKey(CFStringRef expectedHash, CFStringRef expectedHashAfter) { char * name = "testUpdateKey"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); makeKeyWithIntegrity(name, kc, expectedHash); @@ -281,6 +121,7 @@ static void testUpdateKey(CFStringRef expectedHash, CFStringRef expectedHashAfte item = checkN(name, query, 1); checkIntegrityHash(name, item, expectedHashAfter); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testUpdateKeyTests (newKeychainTests + makeKeyWithIntegrityTests + checkNTests + 1 + checkNTests + checkIntegrityHashTests + 1) @@ -292,7 +133,7 @@ static void testUpdateKey(CFStringRef expectedHash, CFStringRef expectedHashAfte static void testKeyPair() { char* name = "testKeyPair"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); @@ -305,24 +146,62 @@ static void testKeyPair() { // Now that we have the key pair, make sure we can pull the individual keys // out (and the hashes match) + CFStringRef label = CFSTR("a modified label"); + CFMutableDictionaryRef query; + CFMutableDictionaryRef update; + + // Ensure that the public key still exists and can be updated + SecKeyRef item; item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); checkHashesMatch(name, (SecKeychainItemRef)pub, (SecKeychainItemRef)item); + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic); + CFDictionarySetValue(query, kSecAttrLabel, label); + item = (SecKeyRef) checkN(name, query, 0); + + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic); + update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(update, kSecAttrLabel, label); + ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate (public key)", name); + + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic); + CFDictionarySetValue(query, kSecAttrLabel, label); + item = (SecKeyRef) checkN(name, query, 1); + CFReleaseNull(item); + + // Ensure that the private key still exists and can be updated + item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); checkHashesMatch(name, (SecKeychainItemRef)priv, (SecKeychainItemRef)item); - // TODO: is there a way to test SecItemUpdate? + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate); + CFDictionarySetValue(query, kSecAttrLabel, label); + item = (SecKeyRef) checkN(name, query, 0); + + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate); + update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(update, kSecAttrLabel, label); + ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate (private key)", name); + + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate); + CFDictionarySetValue(query, kSecAttrLabel, label); + item = (SecKeyRef) checkN(name, query, 1); + CFReleaseNull(item); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testKeyPairTests (newKeychainTests + checkNTests + checkNTests + makeKeyPairTests \ + checkNTests + checkHashesMatchTests \ - + checkNTests + checkHashesMatchTests + 1) + + checkNTests + 1 + checkNTests \ + + checkNTests + checkHashesMatchTests \ + + checkNTests + 1 + checkNTests \ + + 1) static void testAddDuplicateKey(CFStringRef expectedHash) { char * name = "testAddDuplicateKey"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); @@ -334,6 +213,7 @@ static void testAddDuplicateKey(CFStringRef expectedHash) { checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testAddDuplicateKeyTests (newKeychainTests + checkNTests +makeKeyWithIntegrityTests + checkNTests + makeDuplicateKeyTests + checkNTests + 1) @@ -341,7 +221,7 @@ static void testAddDuplicateFreeKey(CFStringRef expectedHash) { // Due to SecItemAdd() will not add a generated symmetric key to the keychain // we can't actually run this test. Code is included here as a reference. //char * name = "testAddDuplicateFreeKey"; - //secdebugfunc("integrity", "************************************* %s", name); + //secnotice("integrity", "************************************* %s", name); //SecKeychainRef kc = newKeychain(name); //checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); @@ -353,6 +233,7 @@ static void testAddDuplicateFreeKey(CFStringRef expectedHash) { //checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); //ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + //CFReleaseNull(kc); } //#define testAddDuplicateFreeKeyTests (newKeychainTests + checkNTests + makeFreeKeyTests + checkIntegrityHashTests + checkNTests \ // + makeDuplicateKeyTests + checkNTests + 1) @@ -367,7 +248,7 @@ static void testAddDuplicateFreeKey(CFStringRef expectedHash) { static void testExportImportKeyPair() { char* name = "testExportImportKeyPair"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); @@ -411,7 +292,7 @@ static void testExportImportKeyPair() { CFDataRef keyData = NULL; ok_status(SecItemExport(pub, kSecFormatPEMSequence, kSecItemPemArmour, &keyParams, &keyData), "%s: SecItemExport", name); - ok_status(SecKeychainItemDelete((SecKeychainItemRef)pub), "%s: SecKeychainDelete", name);; + ok_status(SecKeychainItemDelete((SecKeychainItemRef)pub), "%s: SecKeychainItemDelete", name);; CFRelease(pub); pub = NULL; @@ -421,7 +302,7 @@ static void testExportImportKeyPair() { ok_status(SecItemExport(priv, kSecFormatPEMSequence, kSecItemPemArmour, &keyParams, &keyData), "%s: SecItemExport", name); - ok_status(SecKeychainItemDelete((SecKeychainItemRef)priv), "%s: SecKeychainDelete", name);; + ok_status(SecKeychainItemDelete((SecKeychainItemRef)priv), "%s: SecKeychainItemDelete", name);; CFRelease(priv); priv = NULL; @@ -454,6 +335,7 @@ static void testExportImportKeyPair() { checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testExportImportKeyPairTests (newKeychainTests + checkNTests + checkNTests + makeKeyPairTests \ + checkNTests + checkHashesMatchTests \ diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h index e76f69af..ab3cc06f 100644 --- a/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h @@ -29,6 +29,7 @@ #include "kc-30-xara-helpers.h" #include "kc-30-xara-item-helpers.h" #include "kc-30-xara-key-helpers.h" +#include "kc-keychain-file-helpers.h" static void makeOldKeychainBlob() { char* name = "makeOldKeychainBlob"; @@ -1411,7 +1412,6 @@ uint8_t old_keychain[OLD_KEYCHAIN_SIZE] = { 0xce, 0x81, 0xbe, 0x3a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, }; - #define EMPTY_V512_SIZE 20460 uint8_t empty_v512[EMPTY_V512_SIZE] = { 0x6b, 0x79, 0x63, 0x68, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, @@ -2439,17 +2439,1493 @@ uint8_t empty_v512[EMPTY_V512_SIZE] = { 0xd5, 0x0a, 0x04, 0x32, 0xa8, 0x84, 0xff, 0x6e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }; - -static void writeOldKeychain(const char* testname, const char * path) { - FILE * fp = fopen(path, "w+"); - fwrite(old_keychain, sizeof(uint8_t), OLD_KEYCHAIN_SIZE, fp); - fclose(fp); -} - -static void writeEmptyV512Keychain(const char* testname, const char * path) { - FILE * fp = fopen(path, "w+"); - fwrite(empty_v512, sizeof(uint8_t), EMPTY_V512_SIZE, fp); - fclose(fp); +#define FULL_V512_SIZE 29212 +uint8_t full_v512[FULL_V512_SIZE] = { + 0x6b, 0x79, 0x63, 0x68, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x72, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x18, 0x74, + 0x00, 0x00, 0x47, 0xfc, 0x00, 0x00, 0x48, 0x24, 0x00, 0x00, 0x4e, 0xd8, 0x00, 0x00, 0x58, 0x74, 0x00, 0x00, 0x6b, 0xa4, + 0x00, 0x00, 0x6d, 0x64, 0x00, 0x00, 0x70, 0x5c, 0x00, 0x00, 0x71, 0x1c, 0x00, 0x00, 0x02, 0xdc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x02, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x58, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x44, + 0x00, 0x00, 0x02, 0x8c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x16, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, + 0x41, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x53, + 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x45, 0x53, 0x00, 0x00, 0x00, 0x44, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x43, 0x53, 0x53, 0x4d, + 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x45, + 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x20, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, + 0x41, 0x5f, 0x50, 0x41, 0x52, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x06, 0x44, 0x42, 0x42, 0x6c, + 0x6f, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x1c, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, + 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, + 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x5f, 0x4b, 0x45, + 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x1f, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, + 0x44, 0x5f, 0x53, 0x59, 0x4d, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5c, + 0x00, 0x00, 0x15, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x01, 0x9c, + 0x00, 0x00, 0x01, 0xdc, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x02, 0x9c, 0x00, 0x00, 0x02, 0xdc, + 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x03, 0x5c, 0x00, 0x00, 0x03, 0x9c, 0x00, 0x00, 0x03, 0xdc, 0x00, 0x00, 0x04, 0x1c, + 0x00, 0x00, 0x04, 0x5c, 0x00, 0x00, 0x04, 0x9c, 0x00, 0x00, 0x04, 0xdc, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x05, 0x5c, + 0x00, 0x00, 0x05, 0x9c, 0x00, 0x00, 0x05, 0xdc, 0x00, 0x00, 0x06, 0x1c, 0x00, 0x00, 0x06, 0x5c, 0x00, 0x00, 0x06, 0x9c, + 0x00, 0x00, 0x06, 0xdc, 0x00, 0x00, 0x07, 0x1c, 0x00, 0x00, 0x07, 0x5c, 0x00, 0x00, 0x07, 0x9c, 0x00, 0x00, 0x07, 0xdc, + 0x00, 0x00, 0x08, 0x1c, 0x00, 0x00, 0x08, 0x5c, 0x00, 0x00, 0x08, 0x9c, 0x00, 0x00, 0x08, 0xdc, 0x00, 0x00, 0x09, 0x1c, + 0x00, 0x00, 0x09, 0x5c, 0x00, 0x00, 0x09, 0x9c, 0x00, 0x00, 0x09, 0xdc, 0x00, 0x00, 0x0a, 0x1c, 0x00, 0x00, 0x0a, 0x5c, + 0x00, 0x00, 0x0a, 0x9c, 0x00, 0x00, 0x0a, 0xdc, 0x00, 0x00, 0x0b, 0x1c, 0x00, 0x00, 0x0b, 0x5c, 0x00, 0x00, 0x0b, 0x9c, + 0x00, 0x00, 0x0b, 0xdc, 0x00, 0x00, 0x0c, 0x1c, 0x00, 0x00, 0x0c, 0x5c, 0x00, 0x00, 0x0c, 0x9c, 0x00, 0x00, 0x0c, 0xdc, + 0x00, 0x00, 0x0d, 0x1c, 0x00, 0x00, 0x0d, 0x5c, 0x00, 0x00, 0x0d, 0x9c, 0x00, 0x00, 0x0d, 0xdc, 0x00, 0x00, 0x0e, 0x1c, + 0x00, 0x00, 0x0e, 0x5c, 0x00, 0x00, 0x0e, 0x9c, 0x00, 0x00, 0x0e, 0xdc, 0x00, 0x00, 0x0f, 0x1c, 0x00, 0x00, 0x0f, 0x5c, + 0x00, 0x00, 0x0f, 0x9c, 0x00, 0x00, 0x0f, 0xdc, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x10, 0x5c, 0x00, 0x00, 0x10, 0x9c, + 0x00, 0x00, 0x10, 0xdc, 0x00, 0x00, 0x11, 0x1c, 0x00, 0x00, 0x11, 0x5c, 0x00, 0x00, 0x11, 0x9c, 0x00, 0x00, 0x11, 0xdc, + 0x00, 0x00, 0x12, 0x1c, 0x00, 0x00, 0x12, 0x5c, 0x00, 0x00, 0x12, 0x9c, 0x00, 0x00, 0x12, 0xdc, 0x00, 0x00, 0x13, 0x1c, + 0x00, 0x00, 0x13, 0x5c, 0x00, 0x00, 0x13, 0x9c, 0x00, 0x00, 0x13, 0xdc, 0x00, 0x00, 0x14, 0x1c, 0x00, 0x00, 0x14, 0x5c, + 0x00, 0x00, 0x14, 0x9c, 0x00, 0x00, 0x14, 0xdc, 0x00, 0x00, 0x15, 0x1c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x73, 0x76, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x73, 0x64, 0x6d, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x74, 0x68, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x09, 0x73, 0x64, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x61, 0x74, 0x79, 0x70, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, + 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x0e, 0x70, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x23, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x37, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x2f, 0x88, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x02, 0x88, 0x00, 0x00, 0x2f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x02, 0x88, 0x00, 0x00, 0x02, 0xd8, 0x00, 0x00, 0x03, 0x28, + 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x03, 0xc8, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x74, 0x00, 0x00, 0x04, 0xc8, + 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x05, 0x6c, 0x00, 0x00, 0x05, 0xb8, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, 0x58, + 0x00, 0x00, 0x06, 0xb0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x50, 0x00, 0x00, 0x07, 0x9c, 0x00, 0x00, 0x07, 0xec, + 0x00, 0x00, 0x08, 0x34, 0x00, 0x00, 0x08, 0x88, 0x00, 0x00, 0x08, 0xc8, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x09, 0x48, + 0x00, 0x00, 0x09, 0x88, 0x00, 0x00, 0x09, 0xc8, 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00, 0x0a, 0x48, 0x00, 0x00, 0x0a, 0x98, + 0x00, 0x00, 0x0a, 0xe4, 0x00, 0x00, 0x0b, 0x24, 0x00, 0x00, 0x0b, 0x64, 0x00, 0x00, 0x0b, 0xa4, 0x00, 0x00, 0x0b, 0xe4, + 0x00, 0x00, 0x0c, 0x24, 0x00, 0x00, 0x0c, 0x64, 0x00, 0x00, 0x0c, 0xa4, 0x00, 0x00, 0x0c, 0xe4, 0x00, 0x00, 0x0d, 0x24, + 0x00, 0x00, 0x0d, 0x64, 0x00, 0x00, 0x0d, 0xa4, 0x00, 0x00, 0x0d, 0xe4, 0x00, 0x00, 0x0e, 0x24, 0x00, 0x00, 0x0e, 0x64, + 0x00, 0x00, 0x0e, 0xb4, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x40, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x0f, 0xc0, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x10, 0xc0, 0x00, 0x00, 0x11, 0x00, + 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x11, 0x80, 0x00, 0x00, 0x11, 0xc0, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x40, + 0x00, 0x00, 0x12, 0x80, 0x00, 0x00, 0x12, 0xc0, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x40, 0x00, 0x00, 0x13, 0x90, + 0x00, 0x00, 0x13, 0xdc, 0x00, 0x00, 0x14, 0x1c, 0x00, 0x00, 0x14, 0x5c, 0x00, 0x00, 0x14, 0x9c, 0x00, 0x00, 0x14, 0xdc, + 0x00, 0x00, 0x15, 0x1c, 0x00, 0x00, 0x15, 0x5c, 0x00, 0x00, 0x15, 0x9c, 0x00, 0x00, 0x15, 0xdc, 0x00, 0x00, 0x16, 0x1c, + 0x00, 0x00, 0x16, 0x5c, 0x00, 0x00, 0x16, 0x9c, 0x00, 0x00, 0x16, 0xe8, 0x00, 0x00, 0x17, 0x38, 0x00, 0x00, 0x17, 0x84, + 0x00, 0x00, 0x17, 0xd4, 0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00, 0x18, 0xbc, 0x00, 0x00, 0x19, 0x10, + 0x00, 0x00, 0x19, 0x60, 0x00, 0x00, 0x19, 0xac, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x00, 0x1a, 0xa4, + 0x00, 0x00, 0x1a, 0xf0, 0x00, 0x00, 0x1b, 0x40, 0x00, 0x00, 0x1b, 0x94, 0x00, 0x00, 0x1b, 0xe4, 0x00, 0x00, 0x1c, 0x38, + 0x00, 0x00, 0x1c, 0x84, 0x00, 0x00, 0x1c, 0xd0, 0x00, 0x00, 0x1d, 0x1c, 0x00, 0x00, 0x1d, 0x64, 0x00, 0x00, 0x1d, 0xb0, + 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1e, 0x54, 0x00, 0x00, 0x1e, 0x9c, 0x00, 0x00, 0x1e, 0xe8, 0x00, 0x00, 0x1f, 0x34, + 0x00, 0x00, 0x1f, 0x84, 0x00, 0x00, 0x1f, 0xd0, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x6c, 0x00, 0x00, 0x20, 0xbc, + 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x21, 0x5c, 0x00, 0x00, 0x21, 0xac, 0x00, 0x00, 0x21, 0xf8, 0x00, 0x00, 0x22, 0x4c, + 0x00, 0x00, 0x22, 0xa0, 0x00, 0x00, 0x22, 0xf0, 0x00, 0x00, 0x23, 0x3c, 0x00, 0x00, 0x23, 0x8c, 0x00, 0x00, 0x23, 0xe0, + 0x00, 0x00, 0x24, 0x30, 0x00, 0x00, 0x24, 0x84, 0x00, 0x00, 0x24, 0xd0, 0x00, 0x00, 0x25, 0x1c, 0x00, 0x00, 0x25, 0x68, + 0x00, 0x00, 0x25, 0xb0, 0x00, 0x00, 0x25, 0xfc, 0x00, 0x00, 0x26, 0x4c, 0x00, 0x00, 0x26, 0xa0, 0x00, 0x00, 0x26, 0xe8, + 0x00, 0x00, 0x27, 0x34, 0x00, 0x00, 0x27, 0x80, 0x00, 0x00, 0x27, 0xd0, 0x00, 0x00, 0x28, 0x1c, 0x00, 0x00, 0x28, 0x6c, + 0x00, 0x00, 0x28, 0xb8, 0x00, 0x00, 0x29, 0x08, 0x00, 0x00, 0x29, 0x54, 0x00, 0x00, 0x29, 0xa8, 0x00, 0x00, 0x29, 0xf8, + 0x00, 0x00, 0x2a, 0x44, 0x00, 0x00, 0x2a, 0x98, 0x00, 0x00, 0x2a, 0xec, 0x00, 0x00, 0x2b, 0x3c, 0x00, 0x00, 0x2b, 0x88, + 0x00, 0x00, 0x2b, 0xd8, 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x00, 0x2c, 0x7c, 0x00, 0x00, 0x2c, 0xd0, 0x00, 0x00, 0x2d, 0x1c, + 0x00, 0x00, 0x2d, 0x68, 0x00, 0x00, 0x2d, 0xb4, 0x00, 0x00, 0x2d, 0xfc, 0x00, 0x00, 0x2e, 0x48, 0x00, 0x00, 0x2e, 0x98, + 0x00, 0x00, 0x2e, 0xec, 0x00, 0x00, 0x2f, 0x34, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x4d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x41, 0x64, 0x64, 0x69, 0x6e, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x53, 0x53, 0x49, 0x44, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x63, 0x64, 0x61, 0x74, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x6d, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x69, 0x63, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x63, 0x72, 0x74, 0x72, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x73, 0x63, 0x72, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x69, 0x6e, 0x76, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x6e, 0x65, 0x67, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x63, 0x75, 0x73, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x70, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x67, 0x65, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x63, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x6d, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x64, 0x65, 0x73, 0x63, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x69, 0x63, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x27, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x63, 0x72, 0x74, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x73, 0x63, 0x72, 0x70, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x69, 0x6e, 0x76, 0x69, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x6e, 0x65, 0x67, 0x61, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x63, 0x75, 0x73, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x70, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x73, 0x72, 0x76, 0x72, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x34, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x63, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x6d, 0x64, 0x61, 0x74, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x69, 0x63, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x63, 0x72, 0x74, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x73, 0x63, 0x72, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x69, 0x6e, 0x76, 0x69, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x6e, 0x65, 0x67, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x63, 0x75, 0x73, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x70, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x73, 0x64, 0x6d, 0x6e, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x61, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x70, 0x61, 0x74, 0x68, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x4b, 0x65, 0x79, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, + 0x4b, 0x65, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, + 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x4b, 0x65, 0x79, 0x53, + 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, + 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, + 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, + 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x10, 0x4e, 0x65, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x53, 0x69, 0x67, 0x6e, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x57, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x55, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x65, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x4b, 0x65, 0x79, 0x43, + 0x6c, 0x61, 0x73, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x65, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, + 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x10, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0f, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x4e, 0x65, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x53, 0x69, 0x67, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x57, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x55, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, + 0x4b, 0x65, 0x79, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x81, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x82, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, + 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x67, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x65, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0d, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, + 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x4e, 0x65, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x92, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x53, 0x69, 0x67, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x96, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x99, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x57, 0x72, 0x61, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x55, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xb4, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0xcc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x51, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x03, 0x61, 0x00, 0x00, 0x03, 0x65, + 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x03, 0x71, 0x00, 0x00, 0x03, 0x89, 0x00, 0x00, 0x03, 0x8d, + 0x00, 0x00, 0x03, 0xb9, 0x00, 0x00, 0x03, 0xbd, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x03, 0xc5, 0x00, 0x00, 0x03, 0xd1, + 0x00, 0x00, 0x03, 0xdd, 0x00, 0x00, 0x03, 0xe1, 0x00, 0x00, 0x03, 0xe5, 0x00, 0x00, 0x03, 0xe9, 0x00, 0x00, 0x03, 0xed, + 0x00, 0x00, 0x03, 0xf1, 0x00, 0x00, 0x03, 0xf5, 0x00, 0x00, 0x03, 0xf9, 0x00, 0x00, 0x03, 0xfd, 0x00, 0x00, 0x04, 0x01, + 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x04, 0x0d, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, 0x65, 0x78, 0x74, 0x20, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x6c, 0x3a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0xd2, 0x7e, 0xe2, 0xbe, 0x49, 0x20, 0xd5, 0xb6, 0xf4, 0x7f, 0x6b, 0x19, + 0x69, 0x6d, 0x09, 0xc9, 0xa6, 0xc1, 0xa5, 0xd8, 0x0c, 0x6f, 0x14, 0x8f, 0x77, 0x8d, 0xb2, 0x7b, 0x4b, 0xa9, 0x9d, 0x9a, + 0x5f, 0x5f, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x29, + 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, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x61, 0x72, 0x72, 0x61, + 0x79, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x63, 0x64, 0x68, 0x61, 0x73, 0x68, 0x3a, + 0x30, 0x37, 0x35, 0x61, 0x64, 0x63, 0x30, 0x34, 0x64, 0x61, 0x32, 0x38, 0x37, 0x62, 0x61, 0x65, 0x30, 0x35, 0x37, 0x31, + 0x33, 0x31, 0x32, 0x36, 0x62, 0x36, 0x37, 0x61, 0x66, 0x64, 0x33, 0x33, 0x30, 0x66, 0x37, 0x62, 0x33, 0x33, 0x36, 0x39, + 0x3c, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x0a, 0x09, 0x3c, 0x2f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, + 0x3c, 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e, 0x0a, 0x20, 0xa4, 0x75, + 0x5f, 0x5f, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc4, 0xb4, 0x70, 0x79, 0x38, + 0x48, 0x9b, 0xc6, 0x71, 0x63, 0x6e, 0x21, 0x71, 0x3b, 0x0f, 0xb0, 0xb3, 0xb5, 0x44, 0x13, 0x04, 0xae, 0xbb, 0x40, 0x29, + 0x05, 0xc7, 0x4f, 0xfc, 0x02, 0xed, 0xd2, 0x2c, 0x6a, 0x0f, 0xd8, 0xf6, 0xef, 0x23, 0x1d, 0xd1, 0x41, 0xc6, 0x00, 0x3d, + 0x50, 0x96, 0x6a, 0xfd, 0xa2, 0x01, 0xd8, 0xd6, 0xb0, 0x41, 0x19, 0x9b, 0x6d, 0x64, 0x51, 0xe7, 0xde, 0x23, 0xa2, 0x88, + 0x9c, 0x8e, 0x4c, 0x42, 0x74, 0xf7, 0x43, 0x40, 0xe5, 0xf8, 0xb4, 0xac, 0x2f, 0xb6, 0x97, 0x63, 0xf8, 0xc2, 0x74, 0x0e, + 0x33, 0x20, 0x40, 0x1c, 0x2b, 0x45, 0x0f, 0x3c, 0x98, 0x7c, 0x35, 0x75, 0xdc, 0x2d, 0x42, 0x86, 0x6e, 0x90, 0x8f, 0x59, + 0x94, 0x82, 0xaf, 0xda, 0x42, 0xaa, 0x41, 0x46, 0xdc, 0x93, 0xbd, 0x58, 0x76, 0xa8, 0xa3, 0x0e, 0xaf, 0x68, 0x47, 0x99, + 0x0e, 0x84, 0x73, 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0xea, 0x39, 0x1c, 0x40, 0x28, 0xaa, 0xcd, 0xcb, 0x89, 0x9d, 0x06, 0x84, 0x47, 0x26, 0x51, 0xa8, + 0xb4, 0x3c, 0x84, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, + 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, + 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x04, 0x64, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x05, 0x4c, + 0x00, 0x00, 0x05, 0x74, 0x00, 0x00, 0x05, 0x9c, 0x00, 0x00, 0x05, 0xc4, 0x00, 0x00, 0x05, 0xec, 0x00, 0x00, 0x06, 0x14, + 0x00, 0x00, 0x06, 0x3c, 0x00, 0x00, 0x06, 0x64, 0x00, 0x00, 0x06, 0x8c, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, + 0xea, 0x39, 0x1c, 0x40, 0x28, 0xaa, 0xcd, 0xcb, 0x89, 0x9d, 0x06, 0x84, 0x47, 0x26, 0x51, 0xa8, 0xb4, 0x3c, 0x84, 0x9d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x14, 0xea, 0x39, 0x1c, 0x40, 0x28, 0xaa, 0xcd, 0xcb, 0x89, 0x9d, 0x06, 0x84, 0x47, 0x26, 0x51, 0xa8, + 0xb4, 0x3c, 0x84, 0x9d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x9c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x07, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x06, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0xb4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x39, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x06, 0x49, 0x00, 0x00, 0x06, 0x4d, 0x00, 0x00, 0x06, 0x51, + 0x00, 0x00, 0x06, 0x55, 0x00, 0x00, 0x06, 0x59, 0x00, 0x00, 0x06, 0x71, 0x00, 0x00, 0x06, 0x75, 0x00, 0x00, 0x06, 0xa1, + 0x00, 0x00, 0x06, 0xa5, 0x00, 0x00, 0x06, 0xa9, 0x00, 0x00, 0x06, 0xad, 0x00, 0x00, 0x06, 0xb9, 0x00, 0x00, 0x06, 0xc5, + 0x00, 0x00, 0x06, 0xc9, 0x00, 0x00, 0x06, 0xcd, 0x00, 0x00, 0x06, 0xd1, 0x00, 0x00, 0x06, 0xd5, 0x00, 0x00, 0x06, 0xd9, + 0x00, 0x00, 0x06, 0xdd, 0x00, 0x00, 0x06, 0xe1, 0x00, 0x00, 0x06, 0xe5, 0x00, 0x00, 0x06, 0xe9, 0x00, 0x00, 0x06, 0xed, + 0x00, 0x00, 0x06, 0xf1, 0x00, 0x00, 0x06, 0xf5, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x24, + 0x00, 0x00, 0x05, 0xb4, 0x90, 0xb1, 0xa9, 0x5a, 0xfd, 0xf3, 0x48, 0x3b, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, + 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x86, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x06, 0x9d, 0x19, 0x10, 0xe4, 0x91, 0xac, 0xc8, 0x58, 0x5e, 0xd0, 0x9b, 0x0f, 0xfb, 0x99, 0xb5, 0xf5, + 0xc7, 0x0e, 0x54, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3c, 0x6b, 0x65, 0x79, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, + 0xec, 0x1f, 0x49, 0x31, 0xc8, 0x75, 0x58, 0x7d, 0x62, 0xff, 0xbc, 0x5e, 0x77, 0x07, 0xac, 0x84, 0x61, 0xe2, 0x6c, 0xa1, + 0x00, 0x00, 0x00, 0x40, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x63, + 0x74, 0x65, 0x73, 0x74, 0x73, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x07, 0x5a, 0xdc, 0x04, 0xda, 0x28, 0x7b, 0xae, 0x05, 0x71, 0x31, 0x26, + 0xb6, 0x7a, 0xfd, 0x33, 0x0f, 0x7b, 0x33, 0x69, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3c, 0x6b, 0x65, 0x79, + 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x4b, 0x3f, 0x7b, 0xd7, 0xf9, 0xe4, 0x8d, 0xc7, + 0x10, 0x06, 0xce, 0x67, 0x09, 0x90, 0xae, 0xd9, 0xdb, 0xa6, 0xd5, 0x08, 0x9b, 0x84, 0xd4, 0x11, 0x31, 0x21, 0xba, 0xb4, + 0x1d, 0x0a, 0x32, 0x28, 0x5f, 0x5f, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x5f, 0x5f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, + 0x00, 0x00, 0x01, 0x29, 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, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, + 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x63, 0x64, 0x68, + 0x61, 0x73, 0x68, 0x3a, 0x30, 0x37, 0x35, 0x61, 0x64, 0x63, 0x30, 0x34, 0x64, 0x61, 0x32, 0x38, 0x37, 0x62, 0x61, 0x65, + 0x30, 0x35, 0x37, 0x31, 0x33, 0x31, 0x32, 0x36, 0x62, 0x36, 0x37, 0x61, 0x66, 0x64, 0x33, 0x33, 0x30, 0x66, 0x37, 0x62, + 0x33, 0x33, 0x36, 0x39, 0x3c, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x0a, 0x09, 0x3c, 0x2f, 0x61, 0x72, 0x72, + 0x61, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e, + 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x5f, 0x5f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x6d, 0x82, 0x6b, 0x8c, 0x86, 0xc4, 0xf4, 0x08, + 0xd0, 0x94, 0x59, 0x94, 0x28, 0x90, 0x9e, 0x0a, 0x7d, 0x89, 0xef, 0x12, 0x58, 0xae, 0xec, 0x4a, 0x0a, 0xb7, 0xf1, 0x1c, + 0x2b, 0xad, 0xc4, 0xe0, 0xc1, 0x5a, 0x80, 0xec, 0x7a, 0x38, 0xa3, 0x01, 0x2f, 0x2b, 0x92, 0xac, 0x9a, 0x27, 0xb6, 0x92, + 0x25, 0xe3, 0x3d, 0xa7, 0x95, 0xfc, 0x4a, 0xbd, 0x17, 0xc2, 0x35, 0xaf, 0xe3, 0x16, 0x7e, 0xf4, 0x4c, 0x43, 0x8e, 0x5f, + 0xdc, 0x51, 0x1e, 0x0d, 0x67, 0xca, 0x2c, 0xdb, 0xc1, 0x0c, 0xa0, 0x7d, 0xbb, 0x78, 0x88, 0xac, 0xea, 0x66, 0x37, 0x50, + 0x99, 0x5f, 0x59, 0xf5, 0xc5, 0x0e, 0x19, 0xd9, 0xf2, 0x94, 0xfb, 0xea, 0x42, 0x29, 0x19, 0x49, 0x80, 0xab, 0x7e, 0x8d, + 0xbc, 0x40, 0xd4, 0xf9, 0x16, 0xc1, 0xcf, 0xa7, 0xaa, 0xa8, 0xd1, 0xe8, 0xbd, 0x57, 0x7b, 0x0e, 0x64, 0xc3, 0xb7, 0xc5, + 0xe9, 0x5e, 0xa9, 0xaf, 0x7f, 0x63, 0xdd, 0x6d, 0x04, 0xfb, 0xf9, 0x3a, 0xa3, 0x8c, 0x57, 0xb2, 0xa4, 0xce, 0x90, 0x06, + 0x1f, 0xa9, 0xd8, 0xd1, 0xcb, 0x5b, 0xc8, 0x23, 0x2f, 0xa9, 0x09, 0x28, 0xe1, 0x8c, 0x5f, 0xa5, 0xa1, 0xb9, 0x9c, 0xfb, + 0x4a, 0x30, 0x34, 0xae, 0xac, 0xdd, 0xa1, 0xe1, 0xdf, 0x63, 0xb1, 0xba, 0xac, 0xe8, 0xa6, 0x12, 0x2a, 0xb5, 0x59, 0x42, + 0x45, 0xfa, 0x00, 0x27, 0x23, 0xf2, 0x4e, 0x6a, 0xa4, 0x31, 0xdf, 0x6c, 0xbb, 0x18, 0xdd, 0xfa, 0x25, 0xcc, 0x2c, 0x61, + 0x4f, 0x15, 0xc6, 0x46, 0x7f, 0x7d, 0x16, 0xc4, 0xe0, 0xca, 0x2d, 0x48, 0x2c, 0x86, 0xa1, 0xbf, 0xf6, 0x10, 0x84, 0xe9, + 0xfc, 0xe5, 0x21, 0x10, 0x9e, 0x22, 0x22, 0x04, 0x64, 0xc2, 0x8e, 0x90, 0x5a, 0x83, 0x8c, 0x85, 0xba, 0x31, 0x6d, 0x0a, + 0x0a, 0x73, 0x0a, 0xee, 0x02, 0x0c, 0xb3, 0x43, 0x55, 0xb4, 0x2d, 0x81, 0xa4, 0x4c, 0xff, 0x0c, 0x40, 0x56, 0x5c, 0x18, + 0x36, 0x8d, 0x7f, 0x91, 0x06, 0x08, 0x90, 0x51, 0x5c, 0x20, 0xbe, 0x6b, 0x62, 0xe3, 0xc3, 0x0b, 0x64, 0x45, 0x09, 0x5e, + 0xde, 0x62, 0x0b, 0x43, 0xbb, 0x18, 0x36, 0xac, 0xa5, 0x2e, 0xd1, 0xb9, 0x4b, 0x4b, 0xe9, 0x8c, 0x0b, 0xdb, 0x7d, 0xd4, + 0xee, 0x21, 0x67, 0x91, 0xd0, 0x13, 0x6d, 0x84, 0x02, 0xde, 0xfb, 0x09, 0x5f, 0xa0, 0x15, 0x6b, 0x7c, 0x27, 0x78, 0xfb, + 0x25, 0xda, 0x2f, 0x1e, 0xcb, 0x9a, 0xa0, 0x63, 0xb5, 0x9f, 0x0d, 0xb8, 0xec, 0x7d, 0x55, 0x34, 0xb1, 0x98, 0xbe, 0xbd, + 0xa6, 0x76, 0xb5, 0x87, 0x49, 0x0e, 0x21, 0x35, 0xeb, 0xc8, 0x5e, 0xf5, 0xb4, 0x39, 0x7e, 0x20, 0xbc, 0xec, 0x7a, 0x51, + 0xb7, 0x90, 0x40, 0x5d, 0x9c, 0xaf, 0xd9, 0xea, 0x4a, 0x52, 0x1d, 0x5b, 0x6e, 0xab, 0x0b, 0xcf, 0x1b, 0x37, 0x00, 0xed, + 0xb7, 0x71, 0xad, 0xcd, 0x41, 0x03, 0x70, 0xce, 0xd0, 0x75, 0xcd, 0xa4, 0xda, 0x26, 0xcd, 0xe3, 0xde, 0x7b, 0x80, 0x0c, + 0x9a, 0x02, 0xa7, 0xdb, 0xa9, 0x50, 0x53, 0x6f, 0x4e, 0x37, 0x35, 0x6e, 0x67, 0x15, 0x97, 0x54, 0x40, 0xa3, 0xc2, 0x12, + 0x30, 0x2a, 0x74, 0x3e, 0x69, 0x2b, 0x0a, 0x9b, 0x65, 0x51, 0x8e, 0xac, 0xf0, 0x61, 0x93, 0xba, 0xc6, 0x83, 0x06, 0x35, + 0xb9, 0xc6, 0xe1, 0x8a, 0xe4, 0x60, 0xef, 0xfc, 0x6d, 0xa3, 0x98, 0x9b, 0xa2, 0x49, 0x33, 0x3c, 0xd1, 0xdc, 0xbf, 0x15, + 0x27, 0xcd, 0x23, 0x6b, 0x79, 0x88, 0x72, 0xeb, 0x1c, 0x92, 0xca, 0x23, 0x12, 0xe4, 0x0a, 0x42, 0x2b, 0x25, 0x53, 0x59, + 0x4f, 0x6a, 0xa6, 0xab, 0x7e, 0x35, 0xc4, 0x1a, 0x89, 0xda, 0xe1, 0x98, 0x12, 0x26, 0xe8, 0x93, 0x30, 0xc3, 0xca, 0xb0, + 0x40, 0x4f, 0xf0, 0x4a, 0x3b, 0xc3, 0x9a, 0xfc, 0x0e, 0x85, 0xf2, 0xf7, 0xa3, 0x17, 0xe4, 0x6a, 0x56, 0x4b, 0x07, 0xaa, + 0xcb, 0x5c, 0xc5, 0x56, 0x97, 0x35, 0x11, 0x0d, 0x43, 0xb5, 0xdf, 0xc0, 0x69, 0x9d, 0xbf, 0x01, 0x4e, 0x0d, 0x97, 0xdb, + 0x5f, 0x1e, 0x46, 0x7e, 0x6d, 0xb0, 0xc3, 0xf6, 0x28, 0x49, 0xfc, 0x48, 0x7b, 0x5e, 0xac, 0xaf, 0xe3, 0x1e, 0xa2, 0xf4, + 0x2c, 0xab, 0xe4, 0x8d, 0x48, 0x60, 0xa2, 0xaa, 0x48, 0x37, 0xfb, 0x71, 0xa4, 0x81, 0x2c, 0xf6, 0xef, 0x41, 0xd6, 0x31, + 0x02, 0xef, 0x51, 0xe3, 0x1f, 0x48, 0x9b, 0x88, 0xfd, 0x5d, 0x15, 0x53, 0x66, 0xbf, 0x58, 0xd7, 0x05, 0xeb, 0x3f, 0x91, + 0xd5, 0xa9, 0x4c, 0xb7, 0xa0, 0xf3, 0xce, 0x66, 0xfc, 0x66, 0xcf, 0x44, 0x89, 0x0d, 0xf2, 0x89, 0xc8, 0x89, 0xb8, 0xf2, + 0x10, 0xdd, 0xef, 0xad, 0xa3, 0x94, 0x02, 0x73, 0x75, 0xa8, 0xe3, 0x06, 0x88, 0x4c, 0xeb, 0x15, 0x0c, 0x2e, 0xd7, 0x9d, + 0xd1, 0xa1, 0x63, 0x07, 0xee, 0xca, 0x5f, 0x4e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0xea, 0x39, 0x1c, 0x40, 0x28, 0xaa, 0xcd, 0xcb, 0x89, 0x9d, 0x06, 0x84, 0x47, 0x26, 0x51, 0xa8, + 0xb4, 0x3c, 0x84, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, + 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, + 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x08, 0x34, + 0x00, 0x00, 0x08, 0x5c, 0x00, 0x00, 0x08, 0x84, 0x00, 0x00, 0x08, 0xac, 0x00, 0x00, 0x08, 0xd4, 0x00, 0x00, 0x08, 0xfc, + 0x00, 0x00, 0x09, 0x24, 0x00, 0x00, 0x09, 0x4c, 0x00, 0x00, 0x09, 0x74, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, + 0xea, 0x39, 0x1c, 0x40, 0x28, 0xaa, 0xcd, 0xcb, 0x89, 0x9d, 0x06, 0x84, 0x47, 0x26, 0x51, 0xa8, 0xb4, 0x3c, 0x84, 0x9d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x14, 0xea, 0x39, 0x1c, 0x40, 0x28, 0xaa, 0xcd, 0xcb, 0x89, 0x9d, 0x06, 0x84, 0x47, 0x26, 0x51, 0xa8, + 0xb4, 0x3c, 0x84, 0x9d, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x0e, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x04, 0xe4, + 0x00, 0x00, 0x09, 0xa0, 0x00, 0x00, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf1, 0x00, 0x00, 0x03, 0xf5, 0x00, 0x00, 0x04, 0x0d, + 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, 0x04, 0x19, 0x00, 0x00, 0x04, 0x1d, 0x00, 0x00, 0x04, 0x35, + 0x00, 0x00, 0x04, 0x39, 0x00, 0x00, 0x04, 0x65, 0x00, 0x00, 0x04, 0x69, 0x00, 0x00, 0x04, 0x6d, 0x00, 0x00, 0x04, 0x71, + 0x00, 0x00, 0x04, 0x7d, 0x00, 0x00, 0x04, 0x89, 0x00, 0x00, 0x04, 0x8d, 0x00, 0x00, 0x04, 0x91, 0x00, 0x00, 0x04, 0x95, + 0x00, 0x00, 0x04, 0x99, 0x00, 0x00, 0x04, 0x9d, 0x00, 0x00, 0x04, 0xa1, 0x00, 0x00, 0x04, 0xa5, 0x00, 0x00, 0x04, 0xa9, + 0x00, 0x00, 0x04, 0xad, 0x00, 0x00, 0x04, 0xb1, 0x00, 0x00, 0x04, 0xb5, 0x00, 0x00, 0x04, 0xb9, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x6c, 0xef, 0x42, 0xf5, 0xa0, 0x6a, 0xeb, 0xa5, 0x08, + 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0xdc, 0x2f, 0x52, 0x8d, 0x7e, 0xdf, 0x65, 0xe2, + 0x8e, 0xd3, 0x41, 0x88, 0x5b, 0x38, 0x9f, 0x3d, 0x2e, 0x0a, 0x94, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x00, 0x9a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x14, 0xec, 0x1f, 0x49, 0x31, 0xc8, 0x75, 0x58, 0x7d, 0x62, 0xff, 0xbc, 0x5e, 0x77, 0x07, 0xac, 0x84, + 0x61, 0xe2, 0x6c, 0xa1, 0x00, 0x00, 0x00, 0x40, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x2f, 0x73, 0x65, 0x63, 0x74, 0x65, 0x73, 0x74, 0x73, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x07, 0x5a, 0xdc, 0x04, 0xda, 0x28, 0x7b, 0xae, + 0x05, 0x71, 0x31, 0x26, 0xb6, 0x7a, 0xfd, 0x33, 0x0f, 0x7b, 0x33, 0x69, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x00, 0xe0, 0x5e, 0x86, 0x00, 0x3e, 0xec, 0xeb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, + 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x20, 0x6b, 0xa8, 0xd9, 0xf7, 0x7d, 0xdb, 0xa5, 0x4d, 0x93, 0x73, 0xb1, 0x1a, 0xe5, 0xc8, 0xf7, 0xb5, + 0x5a, 0x5e, 0x81, 0xda, 0x27, 0xe0, 0x5e, 0x86, 0x72, 0x3e, 0xec, 0xeb, 0x0a, 0x9a, 0x8e, 0x0c, 0x5f, 0x5f, 0x5f, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x29, 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, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, 0x09, + 0x09, 0x3c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x63, 0x64, 0x68, 0x61, 0x73, 0x68, 0x3a, 0x30, 0x37, 0x35, 0x61, + 0x64, 0x63, 0x30, 0x34, 0x64, 0x61, 0x32, 0x38, 0x37, 0x62, 0x61, 0x65, 0x30, 0x35, 0x37, 0x31, 0x33, 0x31, 0x32, 0x36, + 0x62, 0x36, 0x37, 0x61, 0x66, 0x64, 0x33, 0x33, 0x30, 0x66, 0x37, 0x62, 0x33, 0x33, 0x36, 0x39, 0x3c, 0x2f, 0x73, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x0a, 0x09, 0x3c, 0x2f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x64, 0x69, + 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e, 0x0a, 0xa9, 0x38, 0xd3, 0x5f, 0x5f, 0x5f, 0x50, + 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x02, 0xdd, 0x3d, 0x35, 0x3d, 0x72, 0xf0, 0xad, 0xd2, 0x36, 0x78, 0x53, 0xf8, 0x02, 0x36, 0x1a, 0x64, + 0x40, 0xe8, 0xf0, 0x6b, 0x67, 0x97, 0xc4, 0x84, 0xfd, 0x4a, 0x8c, 0xc8, 0xf1, 0x1a, 0x07, 0x8a, 0x52, 0x03, 0x04, 0xd5, + 0xc8, 0xb4, 0xa9, 0x7e, 0x30, 0x4d, 0xf5, 0xab, 0x7c, 0xe4, 0x96, 0x7b, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0x7b, 0xed, 0x8a, 0xda, 0xa1, 0x85, 0xd0, 0xef, 0xe0, 0x87, 0xec, 0xa4, 0x1d, 0xcf, 0x0b, 0x22, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0x7b, 0xed, 0x8a, 0xda, 0xa1, 0x85, 0xd0, 0xef, 0xe0, 0x87, 0xec, 0xa4, 0x1d, 0xcf, 0x0b, 0x22, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xbc, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xf1, 0x00, 0x00, 0x03, 0xf5, 0x00, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x04, 0x15, + 0x00, 0x00, 0x04, 0x19, 0x00, 0x00, 0x04, 0x1d, 0x00, 0x00, 0x04, 0x35, 0x00, 0x00, 0x04, 0x39, 0x00, 0x00, 0x04, 0x65, + 0x00, 0x00, 0x04, 0x69, 0x00, 0x00, 0x04, 0x6d, 0x00, 0x00, 0x04, 0x71, 0x00, 0x00, 0x04, 0x7d, 0x00, 0x00, 0x04, 0x89, + 0x00, 0x00, 0x04, 0x8d, 0x00, 0x00, 0x04, 0x91, 0x00, 0x00, 0x04, 0x95, 0x00, 0x00, 0x04, 0x99, 0x00, 0x00, 0x04, 0x9d, + 0x00, 0x00, 0x04, 0xa1, 0x00, 0x00, 0x04, 0xa5, 0x00, 0x00, 0x04, 0xa9, 0x00, 0x00, 0x04, 0xad, 0x00, 0x00, 0x04, 0xb1, + 0x00, 0x00, 0x04, 0xb5, 0x00, 0x00, 0x04, 0xb9, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x3c, + 0x00, 0x00, 0x03, 0x6c, 0xdf, 0xbc, 0xd2, 0x72, 0x51, 0xfe, 0x37, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, + 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x06, 0x42, 0x28, 0x33, 0xc0, 0xfe, 0x5d, 0xc9, 0x6d, 0xce, 0xdf, 0x2c, 0x4a, 0xef, 0xf7, 0x7c, 0xe2, + 0x4e, 0x5c, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0xec, 0x1f, 0x49, 0x31, + 0xc8, 0x75, 0x58, 0x7d, 0x62, 0xff, 0xbc, 0x5e, 0x77, 0x07, 0xac, 0x84, 0x61, 0xe2, 0x6c, 0xa1, 0x00, 0x00, 0x00, 0x40, + 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x63, 0x74, 0x65, 0x73, 0x74, + 0x73, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x14, 0x07, 0x5a, 0xdc, 0x04, 0xda, 0x28, 0x7b, 0xae, 0x05, 0x71, 0x31, 0x26, 0xb6, 0x7a, 0xfd, 0x33, + 0x0f, 0x7b, 0x33, 0x69, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x00, 0x35, 0x59, 0x00, 0xa5, 0x72, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, + 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x63, 0x0a, 0x9f, 0xe4, + 0xf0, 0x19, 0x1d, 0xb8, 0xa9, 0x9d, 0x6e, 0x84, 0x55, 0xe7, 0x11, 0x4f, 0x62, 0x8c, 0xe8, 0xf0, 0xf9, 0xeb, 0x35, 0x59, + 0xef, 0xa5, 0x72, 0xa9, 0x88, 0x77, 0xa2, 0xb2, 0x5f, 0x5f, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x49, 0x54, 0x59, + 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x29, 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, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x6b, 0x65, 0x79, + 0x3e, 0x0a, 0x09, 0x3c, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x3e, 0x63, 0x64, 0x68, 0x61, 0x73, 0x68, 0x3a, 0x30, 0x37, 0x35, 0x61, 0x64, 0x63, 0x30, 0x34, 0x64, 0x61, 0x32, 0x38, + 0x37, 0x62, 0x61, 0x65, 0x30, 0x35, 0x37, 0x31, 0x33, 0x31, 0x32, 0x36, 0x62, 0x36, 0x37, 0x61, 0x66, 0x64, 0x33, 0x33, + 0x30, 0x66, 0x37, 0x62, 0x33, 0x33, 0x36, 0x39, 0x3c, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x0a, 0x09, 0x3c, + 0x2f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, + 0x69, 0x73, 0x74, 0x3e, 0x0a, 0xfe, 0xc0, 0x49, 0x5f, 0x5f, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0xa2, 0x5c, 0x56, 0xd4, + 0xbe, 0x00, 0xb5, 0x12, 0xe7, 0x31, 0x27, 0x24, 0x18, 0x52, 0x27, 0xab, 0x56, 0x69, 0xa0, 0x0b, 0x91, 0x56, 0x72, 0x11, + 0x8b, 0xdf, 0x2e, 0xf9, 0x0f, 0x09, 0x5c, 0xff, 0x66, 0x0e, 0x97, 0x66, 0xd6, 0x04, 0xcd, 0x0d, 0xb1, 0xc1, 0x87, 0x88, + 0xfd, 0x46, 0xfa, 0x76, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xff, 0x99, 0x34, 0xae, + 0x3e, 0x01, 0x20, 0x7c, 0x07, 0x76, 0xda, 0x52, 0x41, 0xe7, 0xbb, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xff, 0x99, 0x34, 0xae, + 0x3e, 0x01, 0x20, 0x7c, 0x07, 0x76, 0xda, 0x52, 0x41, 0xe7, 0xbb, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, + 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x04, 0x05, + 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, 0x04, 0x19, 0x00, 0x00, 0x04, 0x1d, 0x00, 0x00, 0x04, 0x21, + 0x00, 0x00, 0x04, 0x35, 0x00, 0x00, 0x04, 0x39, 0x00, 0x00, 0x04, 0x65, 0x00, 0x00, 0x04, 0x69, 0x00, 0x00, 0x04, 0x6d, + 0x00, 0x00, 0x04, 0x71, 0x00, 0x00, 0x04, 0x7d, 0x00, 0x00, 0x04, 0x89, 0x00, 0x00, 0x04, 0x8d, 0x00, 0x00, 0x04, 0x91, + 0x00, 0x00, 0x04, 0x95, 0x00, 0x00, 0x04, 0x99, 0x00, 0x00, 0x04, 0x9d, 0x00, 0x00, 0x04, 0xa1, 0x00, 0x00, 0x04, 0xa5, + 0x00, 0x00, 0x04, 0xa9, 0x00, 0x00, 0x04, 0xad, 0x00, 0x00, 0x04, 0xb1, 0x00, 0x00, 0x04, 0xb5, 0x00, 0x00, 0x04, 0xb9, + 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x54, 0x00, 0x00, 0x03, 0x7c, 0x89, 0x4b, 0xff, 0x28, + 0x68, 0xa0, 0xff, 0x21, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, + 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x5d, 0xa4, 0xa0, 0x3a, + 0x08, 0x0c, 0xf0, 0xb4, 0xea, 0x9a, 0xa6, 0x3d, 0x77, 0xdd, 0xba, 0xc9, 0x26, 0xf7, 0x04, 0xaf, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xa8, 0xfb, 0x16, 0xec, 0xee, 0x43, 0xa7, 0xd3, 0xeb, 0x71, 0x9f, 0x77, 0xe8, 0x24, 0xea, 0x24, 0x71, 0x5c, 0x96, 0x91, + 0xf4, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0xec, 0x1f, 0x49, 0x31, + 0xc8, 0x75, 0x58, 0x7d, 0x62, 0xff, 0xbc, 0x5e, 0x77, 0x07, 0xac, 0x84, 0x61, 0xe2, 0x6c, 0xa1, 0x00, 0x00, 0x00, 0x40, + 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x63, 0x74, 0x65, 0x73, 0x74, + 0x73, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x14, 0x07, 0x5a, 0xdc, 0x04, 0xda, 0x28, 0x7b, 0xae, 0x05, 0x71, 0x31, 0x26, 0xb6, 0x7a, 0xfd, 0x33, + 0x0f, 0x7b, 0x33, 0x69, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xa8, 0xfb, 0x16, 0xec, 0xee, 0x43, 0xa7, 0xd3, + 0xeb, 0x71, 0x9f, 0x77, 0xe8, 0x24, 0xea, 0x24, 0x71, 0x5c, 0x96, 0x91, 0xf4, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, + 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0xa8, 0xfb, 0x16, 0xec, 0xee, 0x43, 0xa7, 0xd3, 0xeb, 0x71, 0x9f, 0x77, 0xe8, 0x24, 0xea, 0x24, 0x71, 0x5c, 0x96, 0x91, + 0xf4, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x44, 0xf1, 0x0f, 0x6b, 0xb5, 0x08, 0xd4, 0x7f, + 0x89, 0x05, 0x85, 0x9e, 0xfc, 0x06, 0xea, 0xee, 0x50, 0x03, 0x04, 0xbc, 0x4d, 0xa4, 0x08, 0xb1, 0xf4, 0xd2, 0xa5, 0x8c, + 0x65, 0x02, 0x14, 0x7b, 0x5f, 0x5f, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x5f, 0x5f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0c, + 0x00, 0x00, 0x01, 0x29, 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, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x6b, 0x65, 0x79, 0x3e, 0x0a, 0x09, 0x3c, + 0x61, 0x72, 0x72, 0x61, 0x79, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x63, 0x64, 0x68, + 0x61, 0x73, 0x68, 0x3a, 0x30, 0x37, 0x35, 0x61, 0x64, 0x63, 0x30, 0x34, 0x64, 0x61, 0x32, 0x38, 0x37, 0x62, 0x61, 0x65, + 0x30, 0x35, 0x37, 0x31, 0x33, 0x31, 0x32, 0x36, 0x62, 0x36, 0x37, 0x61, 0x66, 0x64, 0x33, 0x33, 0x30, 0x66, 0x37, 0x62, + 0x33, 0x33, 0x36, 0x39, 0x3c, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3e, 0x0a, 0x09, 0x3c, 0x2f, 0x61, 0x72, 0x72, + 0x61, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x64, 0x69, 0x63, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e, + 0x0a, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x5f, 0x5f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x0d, 0xb7, 0x4d, 0x14, 0x7b, 0x98, 0x46, 0x8e, + 0x10, 0x5e, 0x43, 0x19, 0x80, 0x53, 0xfd, 0xcd, 0xc4, 0xf9, 0x89, 0xf1, 0x55, 0xb4, 0x46, 0xb2, 0xc4, 0x7e, 0x8b, 0x33, + 0x56, 0xdb, 0xe2, 0xd9, 0xc0, 0x79, 0x08, 0xc1, 0xf6, 0xdc, 0x7c, 0x4c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, + 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, + 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x04, 0xd4, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0e, 0x90, 0x00, 0x00, 0x10, 0x28, 0x00, 0x00, 0x10, 0xa8, + 0x00, 0x00, 0x10, 0xf0, 0x00, 0x00, 0x11, 0x38, 0x00, 0x00, 0x11, 0x80, 0x00, 0x00, 0x11, 0xc8, 0x00, 0x00, 0x12, 0x10, + 0x00, 0x00, 0x12, 0x58, 0x00, 0x00, 0x12, 0xa0, 0x00, 0x00, 0x12, 0xe8, 0x00, 0x00, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0e, 0xdc, 0x00, 0x00, 0x0f, 0x4c, 0x00, 0x00, 0x0f, 0xbc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0x7b, 0xed, 0x8a, 0xda, 0xa1, 0x85, 0xd0, 0xef, 0xe0, 0x87, 0xec, 0xa4, 0x1d, 0xcf, 0x0b, 0x22, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, + 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, + 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xff, 0x99, 0x34, 0xae, 0x3e, 0x01, 0x20, 0x7c, + 0x07, 0x76, 0xda, 0x52, 0x41, 0xe7, 0xbb, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x10, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, + 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, + 0x32, 0x7d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x10, 0x58, 0x00, 0x00, 0x10, 0x74, 0x00, 0x00, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0x7b, 0xed, 0x8a, 0xda, 0xa1, 0x85, 0xd0, 0xef, 0xe0, 0x87, 0xec, 0xa4, 0x1d, 0xcf, 0x0b, 0x22, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xff, 0x99, 0x34, 0xae, 0x3e, 0x01, 0x20, 0x7c, 0x07, 0x76, 0xda, 0x52, + 0x41, 0xe7, 0xbb, 0xee, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x10, 0xd8, 0x00, 0x00, 0x10, 0xe0, + 0x00, 0x00, 0x10, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x11, 0x20, 0x00, 0x00, 0x11, 0x28, 0x00, 0x00, 0x11, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x11, 0x68, + 0x00, 0x00, 0x11, 0x70, 0x00, 0x00, 0x11, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x11, 0xb0, 0x00, 0x00, 0x11, 0xb8, 0x00, 0x00, 0x11, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x11, 0xf8, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x12, 0x48, + 0x00, 0x00, 0x12, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x12, 0x88, 0x00, 0x00, 0x12, 0x90, 0x00, 0x00, 0x12, 0x98, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x12, 0xd0, + 0x00, 0x00, 0x12, 0xd8, 0x00, 0x00, 0x12, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x13, 0x18, 0x00, 0x00, 0x13, 0x20, 0x00, 0x00, 0x13, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xc0, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x8d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x67, 0x70, + 0x7b, 0xed, 0x8a, 0xda, 0xa1, 0x85, 0xd0, 0xef, 0xe0, 0x87, 0xec, 0xa4, 0x1d, 0xcf, 0x0b, 0x22, 0x64, 0x23, 0x55, 0xfb, + 0x1c, 0xc1, 0x1a, 0x17, 0x20, 0xbf, 0x30, 0xd7, 0x43, 0x41, 0xa9, 0x59, 0x32, 0x30, 0x31, 0x36, 0x30, 0x32, 0x31, 0x36, + 0x30, 0x32, 0x30, 0x36, 0x32, 0x37, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x36, 0x30, 0x32, 0x31, 0x36, 0x30, 0x32, 0x30, 0x36, + 0x32, 0x37, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x09, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x10, + 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x61, 0x63, 0x63, 0x74, 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x34, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xac, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x02, 0xf8, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0xe1, + 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x05, + 0x73, 0x73, 0x67, 0x70, 0xff, 0x99, 0x34, 0xae, 0x3e, 0x01, 0x20, 0x7c, 0x07, 0x76, 0xda, 0x52, 0x41, 0xe7, 0xbb, 0xee, + 0x1d, 0x1f, 0x57, 0x42, 0x58, 0x09, 0x6a, 0x38, 0xc7, 0xd0, 0x2b, 0xa2, 0xbd, 0x98, 0xef, 0xeb, 0x32, 0x30, 0x31, 0x36, + 0x30, 0x32, 0x31, 0x36, 0x30, 0x32, 0x30, 0x36, 0x32, 0x37, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x36, 0x30, 0x32, 0x31, 0x36, + 0x30, 0x32, 0x30, 0x36, 0x32, 0x37, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x09, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x01, 0xc4, 0x00, 0x00, 0x01, 0xf8, + 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x02, 0xa8, 0x00, 0x00, 0x02, 0xd0, + 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x61, 0x63, 0x63, 0x74, + 0x73, 0x64, 0x6d, 0x6e, 0x73, 0x72, 0x76, 0x72, 0x70, 0x74, 0x63, 0x6c, 0x61, 0x74, 0x79, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x70, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x73, 0x64, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x70, 0x74, 0x63, 0x6c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x74, 0x79, 0x70, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, + 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x70, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x90, + 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x61, 0x63, 0x63, 0x74, 0x76, 0x6c, 0x6d, 0x65, 0x61, 0x64, 0x64, 0x72, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, + 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xa8, 0xb6, 0x68, 0x7e, 0xb7, 0x0a, 0x4a, 0xfa, 0x2d, 0x87, 0x91, 0x6b, 0xd9, + 0xfc, 0x82, 0xea, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x89, 0x89, 0x0a, + 0x29, 0xf3, 0x34, 0x62, 0xed, 0x14, 0x1b, 0x2e, 0x52, 0x23, 0x4b, 0x05, 0xeb, 0x93, 0xdf, 0x92, 0x58, 0x36, 0x27, 0xc2, + 0x36, 0xa5, 0x60, 0x75, 0xd9, 0xc1, 0x94, 0xe4, 0xb2, 0xbb, 0xca, 0x4a, 0x41, 0x84, 0x97, 0x47, 0x37, 0x96, 0x1f, 0xc1, + 0xcf, 0x28, 0xc3, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x25, 0x2e, 0x33, 0x01, 0x00, 0x00, 0x00, 0xb4, 0x90, 0xac, 0x1a, 0x44, 0xd4, 0xc6, 0x0f, + 0x4a, 0x82, 0xe5, 0xb8, 0x72, 0x0b, 0x97, 0xf3, 0x99, 0x20, 0x30, 0x02, 0xec, 0x1d, 0x19, 0x51, 0x4b, 0xed, 0x3a, 0x27, + 0x41, 0x19, 0x47, 0xd4, 0x72, 0xce, 0xf4, 0xff, 0x7e, 0x40, 0x82, 0x15, 0x9e, 0xb6, 0xee, 0xec, 0x5c, 0xcf, 0x88, 0x5c, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, +}; + +// This is the master key and random signature for full_v512 +uint8_t full_v512_keyfile[] = { + 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x0e, 0x3a, 0xf9, 0xde, 0x93, 0xda, 0xac, 0x5d, 0x6e, 0xa0, 0x7a, 0x76, 0x75, 0xdb, 0xca, 0x06, 0x9e, 0x41, 0x77, 0xa8, 0x3c, 0xdb, 0xdf, + 0xb6, 0x68, 0x7e, 0xb7, 0x0a, 0x4a, 0xfa, 0x2d, 0x87, 0x91, 0x6b, 0xd9, 0xfc, 0x82, 0xea, 0x3c, +}; +#define FULL_V512_KEYFILE_SIZE sizeof(full_v512_keyfile) + +static void writeOldKeychain(const char* testname, const char * path) { + writeFile(path, old_keychain, OLD_KEYCHAIN_SIZE); +} + +static void writeEmptyV512Keychain(const char* testname, const char * path) { + writeFile(path, empty_v512, EMPTY_V512_SIZE); +} + +static void writeFullV512Keychain(const char* testname, const char * path) { + writeFile(path, full_v512, FULL_V512_SIZE); +} + +static void writeFullV512Keyfile(const char* testname, const char * path) { + writeFile(path, full_v512_keyfile, FULL_V512_KEYFILE_SIZE); } #else diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara.c b/OSX/libsecurity_keychain/regressions/kc-30-xara.c index 469aab65..ffbfd0b9 100644 --- a/OSX/libsecurity_keychain/regressions/kc-30-xara.c +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include "kc-30-xara-item-helpers.h" #include "kc-30-xara-key-helpers.h" @@ -54,7 +57,7 @@ static CSSM_API_MEMORY_FUNCS memFuncs = { cssmMalloc, cssmFree, cssmRealloc, css static CSSM_DL_DB_HANDLE initializeDL() { CSSM_VERSION version = { 2, 0 }; - CSSM_DL_DB_HANDLE dldbHandle; + CSSM_DL_DB_HANDLE dldbHandle = { 0, 0 }; CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } }; CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; @@ -121,48 +124,59 @@ static void modifyAttributeInKeychain(char * name, CSSM_DL_DB_HANDLE dldbHandle, static void testAttackItem(CSSM_DL_DB_HANDLE dldbHandle) { char * name = "testAttackItem"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); makeItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + CFReleaseNull(item); CFReleaseNull(kc); char * modification = "evil_application"; - modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification)); + modifyAttributeInKeychain(name, dldbHandle, keychainDbFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification)); kc = openKeychain(name); - checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + readPasswordContentsWithResult(item, errSecInvalidItemRef, NULL); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } -#define testAttackItemTests (newKeychainTests + checkNTests + makeItemWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1) +#define testAttackItemTests (newKeychainTests + checkNTests + makeItemWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + readPasswordContentsWithResultTests + 1) static void testAttackKey(CSSM_DL_DB_HANDLE dldbHandle) { char * name = "testAttackKey"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); makeKeyWithIntegrity(name, kc, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + + checkKeyUse((SecKeyRef) item, errSecSuccess); + + CFReleaseNull(item); CFReleaseNull(kc); char * modification = "evil_application"; - modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "Label", modification, strlen(modification)); + modifyAttributeInKeychain(name, dldbHandle, keychainDbFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "Label", modification, strlen(modification)); kc = openKeychain(name); - checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + checkKeyUse((SecKeyRef) item, errSecInvalidItemRef); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } -#define testAttackKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1) +#define testAttackKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + checkKeyUseTests + modifyAttributeInKeychainTests \ + + openKeychainTests + checkNTests + checkKeyUseTests + 1) static void testAddAfterCorruptItem(CSSM_DL_DB_HANDLE dldbHandle) { char * name = "testAddAfterCorruptItem"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); @@ -175,22 +189,26 @@ static void testAddAfterCorruptItem(CSSM_DL_DB_HANDLE dldbHandle) { CFReleaseNull(kc); char * modification = "evil_application"; - modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification)); + modifyAttributeInKeychain(name, dldbHandle, keychainDbFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification)); kc = openKeychain(name); + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + deleteItem(item); checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); makeCustomItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("evil_application"), CFSTR("d2aa97b30a1f96f9e61fcade2b00d9f4284976a83a5b68392251ee5ec827f8cc")); checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("evil_application")); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testAddAfterCorruptItemTests (newKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeDuplicateItemTests \ - + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeCustomDuplicateItemTests + 1) + + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + deleteItemTests \ + + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeCustomDuplicateItemTests + 1) static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) { char * name = "testAddAfterCorruptKey"; - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecKeychainRef kc = newKeychain(name); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); @@ -216,13 +234,22 @@ static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) { ok_status(SecKeychainListRemoveKeychain(&kc), "%s: SecKeychainListRemoveKeychain", name); char * modification = "evil_application"; - modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "PrintName", modification, strlen(modification)); - modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_PUBLIC_KEY, "PrintName", modification, strlen(modification)); - modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_PRIVATE_KEY, "PrintName", modification, strlen(modification)); + modifyAttributeInKeychain(name, dldbHandle, keychainDbFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "PrintName", modification, strlen(modification)); + modifyAttributeInKeychain(name, dldbHandle, keychainDbFile, CSSM_DL_DB_RECORD_PUBLIC_KEY, "PrintName", modification, strlen(modification)); + modifyAttributeInKeychain(name, dldbHandle, keychainDbFile, CSSM_DL_DB_RECORD_PRIVATE_KEY, "PrintName", modification, strlen(modification)); kc = openKeychain(name); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + deleteItem(item); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + deleteItem(item); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + deleteItem(item); checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); makeCustomKeyWithIntegrity(name, kc, CFSTR("evil_application"), CFSTR("ca6d90a0b053113e43bbb67f64030230c96537f77601f66bdf821d8684431dfc")); @@ -238,6 +265,7 @@ static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) { CFReleaseNull(item); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testAddAfterCorruptKeyTests (newKeychainTests \ + checkNTests + checkNTests + checkNTests \ @@ -248,76 +276,459 @@ static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) { + modifyAttributeInKeychainTests \ + modifyAttributeInKeychainTests \ + openKeychainTests \ - + checkNTests + checkNTests + checkNTests \ + + checkNTests + deleteItemTests + checkNTests \ + + checkNTests + deleteItemTests + checkNTests \ + + checkNTests + deleteItemTests + checkNTests \ + makeCustomKeyWithIntegrityTests + checkNTests \ + makeCustomDuplicateKeyTests \ + makeCustomKeyPairTests + checkNTests + checkNTests \ + 1) +// These constants are in CommonBlob, but we're in C and can't access them +#define version_MacOS_10_0 0x00000100 +#define version_partition 0x00000200 + static void testKeychainUpgrade() { char name[100]; sprintf(name, "testKeychainUpgrade"); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); + UInt32 version; + char* path = malloc(sizeof(char) * 400); + UInt32 len = 400; + + // To test multi-threading, we want the upgrade to take a while. Add a bunch of passwords... + char oldkcFile[100]; + sprintf(oldkcFile, "%s/Library/test.keychain", getenv("HOME")); + unlink(oldkcFile); + writeOldKeychain(name, oldkcFile); + + SecKeychainRef kc = openCustomKeychain(name, oldkcFile, "password"); + + for(int i = 0; i < 200; i++) { + CFTypeRef result = NULL; + CFStringRef cflabel = CFStringCreateWithFormat(NULL, NULL, CFSTR("item%d"), i); + CFMutableDictionaryRef query = makeAddCustomItemDictionaryWithService(kc, kSecClassInternetPassword, cflabel, cflabel, CFSTR("no service")); + SecItemAdd(query, &result); // don't particuluarly care if this fails... + CFReleaseNull(query); + CFReleaseNull(cflabel); + CFReleaseNull(result); + } - writeOldKeychain(name, keychainFile); - SecKeychainRef kc = openCustomKeychain(name, "test.keychain", "password"); + CFReleaseNull(kc); + + ok_status(copyfile(oldkcFile, keychainFile, NULL, COPYFILE_UNLINK | COPYFILE_ALL), "%s: copyfile", name); + unlink(oldkcFile); + unlink(keychainDbFile); + static dispatch_once_t onceToken = 0; + static dispatch_queue_t release_queue = NULL; + dispatch_once(&onceToken, ^{ + release_queue = dispatch_queue_create("com.apple.security.keychain-upgrade-queue", DISPATCH_QUEUE_CONCURRENT); + }); + + dispatch_group_t g = dispatch_group_create(); SecKeychainItemRef item; + char* __block blockName = NULL; + asprintf(&blockName, "%s", name); + + kc = openCustomKeychain(name, keychainName, "password"); + + // Directly after an upgrade, no items should have partition ID lists + dispatch_group_async(g, release_queue, ^() { + secerror("beginning 1\n"); + SecKeychainRef blockKc; + SecKeychainOpen(keychainName, &blockKc); + SecKeychainItemRef item = checkN(blockName, makeQueryItemDictionary(blockKc, kSecClassGenericPassword), 1); + checkIntegrityHash(blockName, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5")); + checkPartitionIDs(blockName, item, 0); + CFReleaseSafe(blockKc); + CFReleaseSafe(item); + secerror("ending 1\n"); + }); + + dispatch_group_async(g, release_queue, ^() { + usleep(0.1 * USEC_PER_SEC); // use different timings to try to find multithreaded upgrade bugs + secerror("beginning 2\n"); + SecKeychainRef blockKc; + SecKeychainOpen(keychainName, &blockKc); + SecKeychainItemRef item = checkN(blockName, makeQueryItemDictionaryWithService(blockKc, kSecClassInternetPassword, CFSTR("test_service")), 1); + checkIntegrityHash(blockName, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03")); + checkPartitionIDs(blockName, item, 0); + CFReleaseSafe(blockKc); + CFReleaseSafe(item); + secerror("ending 2\n"); + }); + + dispatch_group_async(g, release_queue, ^() { + usleep(0.3 * USEC_PER_SEC); + secerror("beginning 3\n"); + SecKeychainRef blockKc; + SecKeychainOpen(keychainName, &blockKc); + SecKeychainItemRef item = checkN(blockName, makeQueryKeyDictionary(blockKc, kSecAttrKeyClassSymmetric), 1); + checkIntegrityHash(blockName, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + checkPartitionIDs(blockName, (SecKeychainItemRef) item, 0); + CFReleaseSafe(blockKc); + CFReleaseSafe(item); + secerror("ending 3\n"); + }); + + dispatch_group_async(g, release_queue, ^() { + usleep(0.5 * USEC_PER_SEC); + secerror("beginning 4\n"); + SecKeychainRef blockKc; + SecKeychainOpen(keychainName, &blockKc); + SecKeychainItemRef item = checkN(blockName, makeQueryKeyDictionary(blockKc, kSecAttrKeyClassPublic), 1); + checkIntegrityHash(blockName, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578")); + checkPartitionIDs(blockName, (SecKeychainItemRef) item, 0); + CFReleaseSafe(blockKc); + CFReleaseSafe(item); + secerror("ending 4\n"); + }); + + dispatch_group_async(g, release_queue, ^() { + usleep(1 * USEC_PER_SEC); + secerror("beginning 5\n"); + SecKeychainRef blockKc; + SecKeychainOpen(keychainName, &blockKc); + SecKeychainItemRef item = checkN(blockName, makeQueryKeyDictionary(blockKc, kSecAttrKeyClassPrivate), 1); + checkIntegrityHash(blockName, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d")); + checkPartitionIDs(blockName, (SecKeychainItemRef) item, 0); + CFReleaseSafe(blockKc); + CFReleaseSafe(item); + secerror("ending 5\n"); + }); + + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); + + // @@@ I'm worried that there are still some thread issues in AppleDatabase; if these are run in the blocks above + // you can sometimes get CSSMERR_DL_INVALID_RECORD_UID/errSecInvalidRecord instead of errSecDuplicateItem + // Multi-threading duplicate item creation sometimes returns -67701 + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); + + // Check the keychain's version and path + ok_status(SecKeychainGetKeychainVersion(kc, &version), "%s: SecKeychainGetKeychainVersion", name); + is(version, version_partition, "%s: version of upgraded keychain is incorrect", name); + ok_status(SecKeychainGetPath(kc, &len, path), "%s: SecKeychainGetKeychainPath", name); + eq_stringn(path, len, keychainDbFile, strlen(keychainDbFile), "%s: paths do not match", name); + free(path); + + // Now close the keychain and open it again + CFReleaseNull(kc); + kc = openCustomKeychain(name, keychainName, "password"); + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5")); + checkPartitionIDs(name, item, 0); makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03")); + checkPartitionIDs(name, item, 0); makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + checkPartitionIDs(name, (SecKeychainItemRef) item, 0); item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578")); + checkPartitionIDs(name, (SecKeychainItemRef) item, 0); item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d")); + checkPartitionIDs(name, (SecKeychainItemRef) item, 0); - // Now close the keychain and open it again + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); CFReleaseNull(kc); - kc = openCustomKeychain(name, "test.keychain", "password"); + + // make sure we clean up any files left over + unlink(keychainDbFile); + unlink(keychainFile); + unlink(oldkcFile); +} +#define testKeychainUpgradeTests (openCustomKeychainTests + 1 + openCustomKeychainTests + 4 \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + + openCustomKeychainTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + + checkNTests + checkIntegrityHashTests + checkPartitionIDsTests \ + + 1) + +// tests that SecKeychainCreate over an old .keychain file returns an empty keychain +static void testKeychainCreateOver() { + char name[100]; + sprintf(name, "testKeychainCreateOver"); + secnotice("integrity", "************************************* %s", name); + UInt32 version; + char* path = malloc(sizeof(char) * 400); + UInt32 len = 400; + + writeOldKeychain(name, keychainFile); + unlink(keychainDbFile); + + SecKeychainItemRef item = NULL; + + // Check that we upgrade on SecKeychainOpen + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5")); + + ok_status(SecKeychainDelete(kc)); + CFReleaseNull(kc); + + // the old file should still exist, but the -db file should not. + struct stat filebuf; + is(stat(keychainFile, &filebuf), 0, "%s: check %s exists", name, keychainFile); + isnt(stat(keychainDbFile, &filebuf), 0, "%s: check %s does not exist", name, keychainDbFile); + + // Now create a new keychain over the old remnants. + ok_status(SecKeychainCreate(keychainFile, (UInt32) strlen("password"), "password", false, NULL, &kc), "%s: SecKeychainCreate", name); + + // Directly after creating a keychain, there shouldn't be any items (even though an old keychain exists underneath) + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 0); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); + + // Check the keychain's version and path + ok_status(SecKeychainGetKeychainVersion(kc, &version), "%s: SecKeychainGetKeychainVersion", name); + is(version, version_partition, "%s: version of upgraded keychain is incorrect", name); + ok_status(SecKeychainGetPath(kc, &len, path), "%s: SecKeychainGetKeychainPath", name); + eq_stringn(path, len, keychainDbFile, strlen(keychainDbFile), "%s: paths do not match", name); + free(path); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); + + // final check that the files on-disk are as we expect + is(stat(keychainFile, &filebuf), 0, "%s: check %s exists", name, keychainFile); + isnt(stat(keychainDbFile, &filebuf), 0, "%s: check %s does not exist", name, keychainDbFile); + + // make sure we clean up any files left over + unlink(keychainDbFile); + unlink(keychainFile); +} +#define testKeychainCreateOverTests (openCustomKeychainTests + \ ++ checkNTests + checkIntegrityHashTests \ ++ 1 + 2 + 1 \ ++ checkNTests \ ++ checkNTests \ ++ checkNTests \ ++ checkNTests \ ++ checkNTests \ ++ 4 + 1 + 2) + +static void testKeychainDowngrade() { + char *name = "testKeychainDowngrade"; + secnotice("integrity", "************************************* %s", name); + + // For now, don't worry about filenames + writeFullV512Keychain(name, keychainDbFile); + unlink(keychainFile); + writeFullV512Keyfile(name, keychainTempFile); + + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); + UInt32 version; + + ok_status(SecKeychainGetKeychainVersion(kc, &version), "%s: SecKeychainGetKeychainVersion", name); + is(version, version_partition, "%s: version of initial keychain is incorrect", name); + + SecKeychainItemRef item; + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + checkIntegrityHash(name, item, CFSTR("6ba8d9f77ddba54d9373b11ae5c8f7b55a5e81da27e05e86723eeceb0a9a8e0c")); makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); - checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03")); + checkIntegrityHash(name, item, CFSTR("630a9fe4f0191db8a99d6e8455e7114f628ce8f0f9eb3559efa572a98877a2b2")); makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); - checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("42d29fd5e9935edffcf6d0261eabddb00782ec775caa93716119e8e553ab5578")); + checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("d27ee2be4920d5b6f47f6b19696d09c9a6c1a5d80c6f148f778db27b4ba99d9a")); item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); - checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d")); + checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("4b3f7bd7f9e48dc71006ce670990aed9dba6d5089b84d4113121bab41d0a3228")); + + + + ok_status(SecKeychainAttemptMigrationWithMasterKey(kc, version_MacOS_10_0, keychainTempFile), "%s: SecKeychainAttemptKeychainMigrationWithMasterKey", name); + ok_status(SecKeychainGetKeychainVersion(kc, &version), "%s: SecKeychainGetKeychainVersion", name); + is(version, version_MacOS_10_0, "%s: version of downgraded keychain is incorrect", name); + + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); + + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); + + // make sure we clean up + unlink(keychainTempFile); + unlink(keychainDbFile); + unlink(keychainFile); } -#define testKeychainUpgradeTests (openCustomKeychainTests \ - + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ - + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ - + checkNTests + checkIntegrityHashTests + \ - + checkNTests + checkIntegrityHashTests + \ - + checkNTests + checkIntegrityHashTests + \ - + openCustomKeychainTests \ +#define testKeychainDowngradeTests (openCustomKeychainTests + 2 \ + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ + checkNTests + checkIntegrityHashTests +\ + checkNTests + checkIntegrityHashTests +\ + checkNTests + checkIntegrityHashTests +\ - 1) + + 3 + \ + + checkNTests + makeCustomDuplicateItemTests \ + + checkNTests + makeCustomDuplicateItemTests \ + + checkNTests \ + + checkNTests \ + + checkNTests \ + + 1)\ + +// Test opening and upgrading a v256 keychain at a -db filename. +static void testKeychainWrongFile256() { + char name[100]; + sprintf(name, "testKeychainWrongFile256"); + secnotice("integrity", "************************************* %s", name); + UInt32 version; + + unlink(keychainFile); + writeOldKeychain(name, keychainDbFile); + + // Only keychainDb file should exist + struct stat filebuf; + isnt(stat(keychainFile, &filebuf), 0, "%s: %s exists and shouldn't", name, keychainFile); + is(stat(keychainDbFile, &filebuf), 0, "%s: %s does not exist", name, keychainDbFile); + + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); + + SecKeychainItemRef item; + + // Iterate over the keychain to trigger upgrade + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + + // We should have created keychainFile, check for it + is(stat(keychainFile, &filebuf), 0, "%s: %s does not exist", name, keychainFile); + is(stat(keychainDbFile, &filebuf), 0, "%s: %s does not exist", name, keychainDbFile); + + // Check the keychain's version and path + char path[400]; + UInt32 len = sizeof(path); + + ok_status(SecKeychainGetKeychainVersion(kc, &version), "%s: SecKeychainGetKeychainVersion", name); + is(version, version_partition, "%s: version of re-upgraded keychain is incorrect", name); + ok_status(SecKeychainGetPath(kc, &len, path), "%s: SecKeychainGetPath", name); + eq_stringn(path, len, keychainDbFile, strlen(keychainDbFile), "%s: paths do not match", name); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); + + // make sure we clean up any files left over + unlink(keychainDbFile); + unlink(keychainFile); +} +#define testKeychainWrongFile256Tests (2 + openCustomKeychainTests \ + + checkNTests + makeCustomDuplicateItemTests \ + + 2 + 4 \ + + checkNTests + makeCustomDuplicateItemTests \ + + checkNTests + makeCustomDuplicateItemTests \ + + checkNTests \ + + checkNTests \ + + checkNTests \ + + 1) + +// Test opening and upgrading a v512 keychain at a .keychain filename. +static void testKeychainWrongFile512() { + char name[100]; + sprintf(name, "testKeychainWrongFile512"); + secnotice("integrity", "************************************* %s", name); + UInt32 version; + + writeFullV512Keychain(name, keychainFile); + unlink(keychainDbFile); + + // Only keychain file should exist + struct stat filebuf; + isnt(stat(keychainDbFile, &filebuf), 0, "%s: %s exists and shouldn't", name, keychainFile); + is(stat(keychainFile, &filebuf), 0, "%s: %s does not exist", name, keychainDbFile); + + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); + + SecKeychainItemRef item; + + // Iterate over the keychain to trigger upgrade + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + + // We should have move the keychain to keychainDbFile, check for it + isnt(stat(keychainFile, &filebuf), 0, "%s: %s still exists", name, keychainFile); + is(stat(keychainDbFile, &filebuf), 0, "%s: %s does not exist", name, keychainDbFile); + + // Check the keychain's version and path + char path[400]; + UInt32 len = sizeof(path); + + ok_status(SecKeychainGetKeychainVersion(kc, &version), "%s: SecKeychainGetKeychainVersion", name); + is(version, version_partition, "%s: version of moved keychain is incorrect", name); + ok_status(SecKeychainGetPath(kc, &len, path), "%s: SecKeychainGetPath", name); + eq_stringn(path, len, keychainDbFile, strlen(keychainDbFile), "%s: paths do not match", name); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + makeCustomDuplicateItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); + + // make sure we clean up any files left over + unlink(keychainDbFile); + unlink(keychainFile); +} +#define testKeychainWrongFile512Tests (2 + openCustomKeychainTests \ ++ checkNTests + makeCustomDuplicateItemTests \ ++ 2 + 4 \ ++ checkNTests + makeCustomDuplicateItemTests \ ++ checkNTests + makeCustomDuplicateItemTests \ ++ checkNTests \ ++ checkNTests \ ++ checkNTests \ ++ 1) + + +#undef version_partition +#undef version_MacOS_10_0 static SecAccessRef makeUidAccess(uid_t uid) { @@ -399,7 +810,7 @@ static void checkAccessLength(const char * name, SecAccessRef access, int expect static void testUidAccess() { char name[100]; sprintf(name, "testUidAccess"); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecAccessRef access = makeUidAccess(getuid()); @@ -429,6 +840,7 @@ static void testUidAccess() { checkAccessLength(name, access, 2); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testUidAccessTests (newKeychainTests + 2 + checkNTests + 1 + checkNTests + 1 + checkAccessLengthTests \ + 2 + checkAccessLengthTests + 1) @@ -495,7 +907,7 @@ static SecAccessRef makeMultipleUidAccess(uid_t* uids, uint32 count) static void testMultipleUidAccess() { char name[100]; sprintf(name, "testMultipleUidAccess"); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); uid_t uids[5]; uids[0] = getuid(); @@ -517,13 +929,14 @@ static void testMultipleUidAccess() { checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testMultipleUidAccessTests (newKeychainTests + checkNTests + 3) static void testRootUidAccess() { char name[100]; sprintf(name, "testRootUidAccess"); - secdebugfunc("integrity", "************************************* %s", name); + secnotice("integrity", "************************************* %s", name); SecAccessRef access = SecAccessCreateWithOwnerAndACL(getuid(), 0, (kSecUseOnlyUID | kSecHonorRoot), NULL, NULL); @@ -543,9 +956,97 @@ static void testRootUidAccess() { checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); } #define testRootUidAccessTests (newKeychainTests + checkNTests + 4 + checkNTests) +static void testBadACL() { + char name[100]; + sprintf(name, "testBadACL"); + secnotice("integrity", "************************************* %s", name); + + SecKeychainItemRef item = NULL; + + unlink(keychainFile); + writeFullV512Keychain(name, keychainDbFile); + + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); + + // Check that these exist in this keychain... + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFRelease(kc); + + // Corrupt all the ACLs, by changing the partition id plist entry + uint8_t * fileBuffer = (uint8_t*) malloc(FULL_V512_SIZE); + memcpy(fileBuffer, full_v512, FULL_V512_SIZE); + + void* p; + char * str = "Partitions"; + while( (p = memmem(fileBuffer, FULL_V512_SIZE, (void*) str, strlen(str))) ) { + *(uint8_t*) p = 0; + } + writeFile(keychainDbFile, fileBuffer, FULL_V512_SIZE); + free(fileBuffer); + + kc = openCustomKeychain(name, keychainName, "password"); + + // These items exist in this keychain, but their ACL is corrupted. We should be able to find them, but not fetch data. + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + readPasswordContentsWithResult(item, errSecInvalidItemRef, NULL); // we don't expect to be able to read this + deleteItem(item); + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + readPasswordContentsWithResult(item, errSecInvalidItemRef, NULL); // we don't expect to be able to read this + deleteItem(item); + checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 0); + + // These should work + makeItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + makeItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); + + // And now the items should exist + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + readPasswordContents(item, CFSTR("data")); + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + readPasswordContents(item, CFSTR("data")); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); +} +#define testBadACLTests (openCustomKeychainTests + checkNTests * 2 + 1 + openCustomKeychainTests \ + + 2*(checkNTests + readPasswordContentsWithResultTests + deleteItemTests + checkNTests) \ + + makeItemTests*2 + checkNTests*2 + readPasswordContentsTests*2 + 1) + +static void testIterateLockedKeychain() { + char name[100]; + sprintf(name, "testIterateLockedKeychain"); + secnotice("integrity", "************************************* %s", name); + + SecKeychainItemRef item = NULL; + + unlink(keychainFile); + writeFullV512Keychain(name, keychainDbFile); + + SecKeychainRef kc = openCustomKeychain(name, keychainName, "password"); + + ok_status(SecKeychainLock(kc), "%s: SecKeychainLock", name); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); + CFReleaseNull(kc); +} +#define testIterateLockedKeychainTests (openCustomKeychainTests + 1 + checkNTests*5 + 1) + #define kTestCount (0 \ + testAddItemTests \ + testAddItemTests \ @@ -576,16 +1077,20 @@ static void testRootUidAccess() { + unloadDLTests \ \ + testKeychainUpgradeTests \ + + testKeychainCreateOverTests \ + + testKeychainDowngradeTests \ + + testKeychainWrongFile256Tests \ + + testKeychainWrongFile512Tests \ + testUidAccessTests \ + testMultipleUidAccessTests \ + testRootUidAccessTests \ + + testBadACLTests \ + + testIterateLockedKeychainTests \ ) static void tests(void) { - const char *home_dir = getenv("HOME"); - sprintf(keychainFile, "%s/Library/Keychains/test.keychain", home_dir); - sprintf(keychainName, "test.keychain"); + initializeKeychainTests("kc-30-xara"); testAddItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); testAddItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f")); @@ -627,9 +1132,15 @@ static void tests(void) unloadDL(&dldbHandle); testKeychainUpgrade(); + testKeychainCreateOver(); + testKeychainDowngrade(); + testKeychainWrongFile256(); + testKeychainWrongFile512(); testUidAccess(); testMultipleUidAccess(); testRootUidAccess(); + testBadACL(); + testIterateLockedKeychain(); //makeOldKeychainBlob(); } @@ -653,5 +1164,6 @@ int kc_30_xara(int argc, char *const *argv) tests(); + deleteTestFiles(); return 0; } diff --git a/OSX/libsecurity_keychain/regressions/kc-40-seckey.c b/OSX/libsecurity_keychain/regressions/kc-40-seckey.c deleted file mode 100644 index 289080af..00000000 --- a/OSX/libsecurity_keychain/regressions/kc-40-seckey.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (c) 2007-2009,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 - -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "keychain_regressions.h" -#include "utilities/SecCFRelease.h" - -#if TARGET_OS_IPHONE -static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) { - uint8_t dataToDigest[256]; - size_t dataToDigestLen = sizeof(dataToDigest); - size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize); - uint8_t sig[sigLen]; - - DERItem oid; - oid.length = algId->algorithm.Length; - oid.data = algId->algorithm.Data; - - /* Get the oid in decimal for display purposes. */ - CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid); - char oidBuf[40]; - CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8); - CFRelease(oidStr); - - SKIP: { - OSStatus status; - - /* Time to sign. */ - ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen, - sig, &sigLen), "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8); - - skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess); - - /* Verify the signature we just made. */ - ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, - sig, sigLen), "digest and verify"); - /* Invalidate the signature. */ - sig[0] ^= 0xff; - is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, - sig, sigLen), errSSLCrypto, "digest and verify bad sig"); - sig[0] ^= 0xff; - dataToDigest[0] ^= 0xff; - is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, - sig, sigLen), errSSLCrypto, "digest and verify bad digest"); - } -} - -static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) { - static const SecAsn1Oid *oids[] = { - &CSSMOID_SHA1WithRSA, - &CSSMOID_SHA224WithRSA, - &CSSMOID_SHA256WithRSA, - &CSSMOID_SHA384WithRSA, - &CSSMOID_SHA512WithRSA, -#if 0 - &CSSMOID_SHA1WithRSA_OIW, - &CSSMOID_SHA1WithDSA, // BSAFE - &CSSMOID_SHA1WithDSA_CMS, // X509/CMS - &CSSMOID_SHA1WithDSA_JDK, // JDK 1.1 -#endif - }; - - - uint32_t ix; - SecAsn1AlgId algId = {}; - for (ix = 0; ix < sizeof(oids) / sizeof(*oids); ++ix) { - if (oids[ix]) { - algId.algorithm = *oids[ix]; - } else { - algId.algorithm.Length = 0; - algId.algorithm.Data = NULL; - } - - testdigestandsignalg(privKey, pubKey, &algId); - } -} -#endif - -#if 0 -static void dump_bytes(uint8_t* bytes, size_t amount) -{ - while (amount > 0) { - printf("0x%02x ", *bytes); - ++bytes; - --amount; - } -} -#endif - - -#if !TARGET_OS_IPHONE -#define kEncryptDecryptTestCount 0 -#else -#define kEncryptDecryptTestCount 5 -static void test_encrypt_decrypt(SecKeyRef pubKey, SecKeyRef privKey, uint32_t padding, size_t keySizeInBytes) -{ - SKIP: { - size_t max_len = keySizeInBytes; - switch (padding) { - case kSecPaddingNone: max_len = keySizeInBytes; break; - case kSecPaddingOAEP: max_len = keySizeInBytes - 2 - 2 * CC_SHA1_DIGEST_LENGTH; break; - case kSecPaddingPKCS1: max_len = keySizeInBytes - 11; break; - default: skip("what is the max_len for this padding?", 5, false); - } - - uint8_t secret[max_len + 1], encrypted_secret[keySizeInBytes], decrypted_secret[keySizeInBytes]; - uint8_t *secret_ptr = secret; - size_t secret_len = max_len; - size_t encrypted_secret_len = sizeof(encrypted_secret); - size_t decrypted_secret_len = sizeof(decrypted_secret); - memset(decrypted_secret, 0xff, decrypted_secret_len); - SecRandomCopyBytes(kSecRandomDefault, sizeof(secret), secret); - - // zero pad, no accidental second zero byte - if (padding == kSecPaddingNone) { - secret[0] = 0; - secret[1] = 128; - } - - is_status(SecKeyEncrypt(pubKey, padding, - secret, sizeof(secret), - encrypted_secret, &encrypted_secret_len), errSecParam, "encrypt secret (overflow)"); - ok_status(SecKeyEncrypt(pubKey, padding, - secret, secret_len, - encrypted_secret, &encrypted_secret_len), "encrypt secret"); - - ok_status(SecKeyDecrypt(privKey, padding, - encrypted_secret, encrypted_secret_len, - decrypted_secret, &decrypted_secret_len), "decrypt secret"); - - // zero padding is removed on decode - if (padding == kSecPaddingNone) { - secret_len--; - secret_ptr++; - } - - ok(decrypted_secret_len == secret_len, "correct length"); - ok_status(memcmp(secret_ptr, decrypted_secret, secret_len), "verify secret"); - } -} -#endif - - - -#if !TARGET_OS_IPHONE -/* This is part of Security.framework on iOS */ - -enum { - // kSecKeyKeySizeInBits = 0, // already exists on osx - kSecKeySignatureSize = 101, - kSecKeyEncryptedDataSize = 102, - // More might belong here, but we aren't settled on how - // to take into account padding and/or digest types. -}; - -static -size_t SecKeyGetSize(SecKeyRef key, int whichSize) -{ - size_t result = SecKeyGetBlockSize(key); - - /* This is only RSA */ - if (whichSize == kSecKeyKeySizeInBits) - result *= 8; - - return result; -} -#endif - -#define kKeyGenTestCount (11 + (3*kEncryptDecryptTestCount)) -static void testkeygen(size_t keySizeInBits) { - SecKeyRef pubKey = NULL, privKey = NULL; - size_t keySizeInBytes = (keySizeInBits + 7) / 8; - CFNumberRef kzib; - - kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits); - CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); - CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); - - OSStatus status; - ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), - "Generate %ld bit (%ld byte) RSA keypair", keySizeInBits, - keySizeInBytes); - CFRelease(kzib); - CFRelease(kgp); - - SKIP: { - skip("keygen failed", 8, status == errSecSuccess); - ok(pubKey, "pubkey returned"); - ok(privKey, "privKey returned"); - is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); - is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); - - /* Sign something. */ - uint8_t something[keySizeInBytes]; - size_t something_len = keySizeInBytes - 11; - SecRandomCopyBytes(kSecRandomDefault, sizeof(something), something); - uint8_t sig[keySizeInBytes]; - size_t sigLen = sizeof(sig); -#if TARGET_OS_IPHONE - /* TODO: This is returning another error on OS X */ - is_status(SecKeyRawSign(privKey, kSecPaddingPKCS1, - something, something_len + 1, sig, &sigLen), - errSecParam, "sign overflow"); -#endif - ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1, - something, something_len, sig, &sigLen), "sign something"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1, - something, something_len, sig, sigLen), "verify sig on something"); - - // Torture test ASN.1 encoder by setting high bit to 1. - uint8_t digest[CC_SHA512_DIGEST_LENGTH] = { - 0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - }; -#if TARGET_OS_IPHONE - /* Thoses tests are making sure that MD2 and MD5 are NOT supported, - but they still are on OS X */ - - //CC_MD2(something, sizeof(something), digest); - ok_status(!SecKeyRawSign(privKey, kSecPaddingPKCS1MD2, - digest, CC_MD2_DIGEST_LENGTH, sig, &sigLen), - "don't sign md2 digest"); //FAIL - ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1MD2, - digest, CC_MD2_DIGEST_LENGTH, sig, sigLen), - "verify sig on md2 digest fails"); //FAIL - - //CC_MD5(something, sizeof(something), digest); - sigLen = sizeof(sig); - ok_status(!SecKeyRawSign(privKey, kSecPaddingPKCS1MD5, - digest, CC_MD5_DIGEST_LENGTH, sig, &sigLen), - "don't sign md5 digest"); //FAIL - ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1MD5, - digest, CC_MD5_DIGEST_LENGTH, sig, sigLen), - "verify sig on md5 digest fails"); //FAIL -#endif - - //CCDigest(kCCDigestSHA1, something, sizeof(something), digest); - sigLen = sizeof(sig); - ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA1, - digest, CC_SHA1_DIGEST_LENGTH, sig, &sigLen), - "sign sha1 digest"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA1, - digest, CC_SHA1_DIGEST_LENGTH, sig, sigLen), - "verify sig on sha1 digest"); - -#if TARGET_OS_IPHONE - /* The assumptions in these tests are just wrong on OS X */ - uint8_t signature[keySizeInBytes], *ptr = signature; - size_t signature_len = sizeof(signature); - ok_status(SecKeyEncrypt(pubKey, kSecPaddingNone, sig, sigLen, signature, &signature_len), "inspect signature"); - is(signature_len, keySizeInBytes - 1, "got signature"); // FAIL for 2056 - while(*ptr && ((size_t)(ptr - signature) < signature_len)) ptr++; - is(signature + signature_len - ptr, 16 /* length(\0 || OID_SHA1) */ + CC_SHA1_DIGEST_LENGTH, "successful decode"); -#endif - -#if TARGET_OS_IPHONE - /* Those are not supported on OS X */ - /* PKCS1 padding is 00 01 PAD * 8 or more 00 data. - data is SEQ { SEQ { OID NULL } BIT STRING 00 DIGEST } - So min data + pad overhead is 11 + 9 + oidlen - oidlen = 11 for the sha2 family of oids, so we have 29 bytes; or - 232 bits of minimum overhead. */ - const size_t pkcs1Overhead = 232; - if (keySizeInBits > 224 + pkcs1Overhead) { - //CC_SHA224(something, sizeof(something), digest); - sigLen = sizeof(sig); - ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA224, - digest, CC_SHA224_DIGEST_LENGTH, sig, &sigLen), - "sign sha224 digest"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA224, - digest, CC_SHA224_DIGEST_LENGTH, sig, sigLen), - "verify sig on sha224 digest"); - } - - if (keySizeInBits > 256 + pkcs1Overhead) { - //CC_SHA256(something, sizeof(something), digest); - sigLen = sizeof(sig); - ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA256, - digest, CC_SHA256_DIGEST_LENGTH, sig, &sigLen), - "sign sha256 digest"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA256, - digest, CC_SHA256_DIGEST_LENGTH, sig, sigLen), - "verify sig on sha256 digest"); - } - - if (keySizeInBits > 384 + pkcs1Overhead) { - //CC_SHA384(something, sizeof(something), digest); - sigLen = sizeof(sig); - ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA384, - digest, CC_SHA384_DIGEST_LENGTH, sig, &sigLen), - "sign sha384 digest"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA384, - digest, CC_SHA384_DIGEST_LENGTH, sig, sigLen), - "verify sig on sha384 digest"); - } - - if (keySizeInBits > 512 + pkcs1Overhead) { - //CC_SHA512(something, sizeof(something), digest); - sigLen = sizeof(sig); - ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA512, - digest, CC_SHA512_DIGEST_LENGTH, sig, &sigLen), - "sign sha512 digest"); - ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA512, - digest, CC_SHA512_DIGEST_LENGTH, sig, sigLen), - "verify sig on sha512 digest"); - } - - test_encrypt_decrypt(pubKey, privKey, kSecPaddingNone, keySizeInBytes); - test_encrypt_decrypt(pubKey, privKey, kSecPaddingPKCS1, keySizeInBytes); - test_encrypt_decrypt(pubKey, privKey, kSecPaddingOAEP, keySizeInBytes); - - testdigestandsign(privKey, pubKey); -#endif - - const void *privkeys[] = { - kSecValueRef - }; - const void *privvalues[] = { - privKey - }; - CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, - sizeof(privkeys) / sizeof(*privkeys), NULL, NULL); -#if TARGET_OS_IPHONE - /* OS X: keys are always added to the keychain when generated */ - ok_status(SecItemAdd(privitem, NULL), "add private key"); //FAIL -#endif - ok_status(SecItemDelete(privitem), "delete private key"); - CFReleaseNull(privitem); - - const void *pubkeys[] = { - kSecValueRef - }; - const void *pubvalues[] = { - pubKey - }; - CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, - sizeof(pubkeys) / sizeof(*pubkeys), NULL, NULL); -#if TARGET_OS_IPHONE - /* OS X: keys are always added to the keychain when generated */ - ok_status(SecItemAdd(pubitem, NULL), "add public key"); //FAIL -#endif - ok_status(SecItemDelete(pubitem), "delete public key"); - CFReleaseNull(pubitem); - - /* Cleanup. */ - CFReleaseNull(pubKey); - CFReleaseNull(privKey); - } -} - -#define kKeyGen2TestCount 11 -static void testkeygen2(size_t keySizeInBits) { - SecKeyRef pubKey = NULL, privKey = NULL; - size_t keySizeInBytes = (keySizeInBits + 7) / 8; - CFNumberRef kzib; - - CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); - CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); - CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); - CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); - - CFReleaseNull(ourUUID); - CFReleaseNull(uuidString); - - CFStringAppend(publicName, CFSTR("-Public-40")); - CFStringAppend(privateName, CFSTR("-Private-40")); - CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - - CFDictionaryAddValue(pubd, kSecAttrLabel, publicName); - CFDictionaryAddValue(privd, kSecAttrLabel, privateName); - - kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits); - CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); - CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); - CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue); - CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd); - CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd); - - OSStatus status; - ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), - "Generate %ld bit (%ld byte) persistent RSA keypair", - keySizeInBits, keySizeInBytes); - CFRelease(kzib); - CFRelease(kgp); - - SKIP: { - skip("keygen failed", 8, status == errSecSuccess); - ok(pubKey, "pubkey returned"); - ok(privKey, "privKey returned"); - is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); - is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); - - SecKeyRef pubKey2, privKey2; - CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); - CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(privd, kSecClass, kSecClassKey); - CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); - ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), - "retrieve pub key by label"); - ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), - "retrieve priv key by label and kSecAttrCanSign"); - - /* Sign something. */ - uint8_t something[50] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; - uint8_t sig[keySizeInBytes]; - size_t sigLen = keySizeInBytes; - ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, - something, sizeof(something), sig, &sigLen), "sign something"); - ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, - something, sizeof(something), sig, sigLen), "verify sig on something"); - -#if TARGET_OS_IPHONE - /* SecKeyEncrypt does not return errSecParam on OS X in that case */ - sigLen = keySizeInBytes; - is_status(SecKeyEncrypt(pubKey2, kSecPaddingPKCS1SHA1, - something, sizeof(something), sig, &sigLen), errSecParam, - "encrypt something with invalid padding"); -#endif - - /* Cleanup. */ - CFReleaseNull(pubKey2); - CFReleaseNull(privKey2); - - /* delete from keychain - note: do it before releasing publicName and privateName - because pubd and privd have no retain/release callbacks */ - ok_status(SecItemDelete(pubd), "delete generated pub key"); - ok_status(SecItemDelete(privd), "delete generated priv key"); - } - - /* Cleanup. */ - CFReleaseNull(pubKey); - CFReleaseNull(privKey); - - CFReleaseNull(publicName); - CFReleaseNull(privateName); - - CFRelease(pubd); - CFRelease(privd); -} - - -#if !TARGET_OS_IPHONE -// Only exists currently in MacOSX -typedef struct KDFVector_t { - char *password; - char *salt; - int rounds; - int alg; - int dklen; - char *expectedstr; - int expected_failure; -} KDFVector; - -static KDFVector kdfv[] = { - // Test Case PBKDF2 - HMACSHA1 http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-00 - { "password", "salt", 1, 1, 160, "0c60c80f961f0e71f3a9b524af6012062fe037a6", 0 }, - { "password", "salt", 2, 1, 160, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", 0 }, - { "password", "salt", 4096, 1, 160, "4b007901b765489abead49d926f721d065a429c1", 0 }, - { "password", "salt", 1, 0, 160, NULL, -1} // This crashed -}; - -static size_t kdfvLen = sizeof(kdfv) / sizeof(KDFVector); - -static int testSecKDF(CFStringRef password, CFDataRef salt, CFNumberRef rounds, CFStringRef alg, CFNumberRef dklen, CFDataRef expected, int expected_failure) { - CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - int retval = 0; - - CFDictionaryAddValue(parameters, kSecAttrSalt, salt); - CFDictionaryAddValue(parameters, kSecAttrKeySizeInBits, dklen); - CFDictionaryAddValue(parameters, kSecAttrPRF, alg); - CFDictionaryAddValue(parameters, kSecAttrRounds, rounds); - - SecKeyRef derivedKey = SecKeyDeriveFromPassword(password, parameters, NULL); - if(derivedKey == NULL && expected_failure) { - ok(1, "Correctly failed to produce a key"); - goto errOut; - } else if(derivedKey == NULL) { - ok(0, "Could not generate a key when we should have"); - goto errOut; - } - ok(1, "Made a new key"); - retval = 1; - // NEEDS Fix -- ok(status = expectedEqualsComputed(expected, derivedKey), "Derived key is as expected"); -errOut: - if(parameters) CFRelease(parameters); - if(derivedKey) CFRelease(derivedKey); - return retval; -} - -static CFDataRef CFDataCreateFromHexBytes(char *s) { - if(!s) return NULL; - size_t len = strlen(s); - if(len%2) return NULL; - len /= 2; - uint8_t buf[len]; - for(size_t i=0; iexpectedstr); - CFStringRef password = CFStringCreateWithCString(NULL, kdfvec->password, kCFStringEncodingUTF8); - CFDataRef salt = CFDataCreate(NULL, (const UInt8 *)kdfvec->salt, strlen(kdfvec->salt)); - CFNumberRef rounds = CFNumberCreate(NULL, kCFNumberIntType, &kdfvec->rounds); - CFNumberRef dklen = CFNumberCreate(NULL, kCFNumberIntType, &kdfvec->dklen); - int status = 1; - - ok(testSecKDF(password, salt, rounds, kSecAttrPRFHmacAlgSHA1, dklen, expectedBytes, kdfvec->expected_failure), "Test SecKeyDeriveFromPassword PBKDF2"); - - if(expectedBytes) CFRelease(expectedBytes); - return status; -} - - -static void testkeyderivation() { - for(size_t testcase = 0; testcase < kdfvLen; testcase++) { - // diag("Test %lu\n", testcase + 1); - ok(PBKDF2Test(&kdfv[testcase]), "Successful full test of KDF Vector"); - } -} - -#else -static size_t kdfvLen = 0; // no kdf functions in Sec for iphone -#endif /* !TARGET_OS_IPHONE */ - - -/* Test basic add delete update copy matching stuff. */ -#define kTestCount ((2 * kKeyGenTestCount) + kKeyGen2TestCount + (int) (kdfvLen*3)) -static void tests(void) -{ - /* Comment out lines below for testing generating all common key sizes, - disabled now for speed reasons. */ - //testkeygen(512); - //testkeygen(768); - testkeygen(1024); - testkeygen(2056); // Stranged sized for edge cases in padding. - //testkeygen(2048); - //testkeygen(4096); - - testkeygen2(1024); // lots of FAIL! -#if !TARGET_OS_IPHONE - testkeyderivation(); -#endif -} - -int kc_40_seckey(int argc, char *const *argv) -{ - plan_tests(kTestCount); - - tests(); - - return 0; -} diff --git a/OSX/libsecurity_keychain/regressions/kc-40-seckey.m b/OSX/libsecurity_keychain/regressions/kc-40-seckey.m new file mode 100644 index 00000000..bfe25496 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-40-seckey.m @@ -0,0 +1,1415 @@ +/* + * Copyright (c) 2007-2009,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 "keychain_regressions.h" +#include "utilities/SecCFRelease.h" +#include "utilities/array_size.h" + +#if TARGET_OS_IPHONE +static void testdigestandsignalg(SecKeyRef privKey, SecKeyRef pubKey, const SecAsn1AlgId *algId) { + uint8_t dataToDigest[256]; + size_t dataToDigestLen = sizeof(dataToDigest); + size_t sigLen = SecKeyGetSize(privKey, kSecKeySignatureSize); + uint8_t sig[sigLen]; + + DERItem oid; + oid.length = algId->algorithm.Length; + oid.data = algId->algorithm.Data; + + /* Get the oid in decimal for display purposes. */ + CFStringRef oidStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, &oid); + char oidBuf[40]; + CFStringGetCString(oidStr, oidBuf, sizeof(oidBuf), kCFStringEncodingUTF8); + CFRelease(oidStr); + + SKIP: { + OSStatus status; + + /* Time to sign. */ + ok_status(status = SecKeyDigestAndSign(privKey, algId, dataToDigest, dataToDigestLen, + sig, &sigLen), "digest and sign %s with %ld bit RSA key", oidBuf, sigLen * 8); + + skip("SecKeyDigestAndSign failed", 3, status == errSecSuccess); + + /* Verify the signature we just made. */ + ok_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, + sig, sigLen), "digest and verify"); + /* Invalidate the signature. */ + sig[0] ^= 0xff; + is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, + sig, sigLen), errSSLCrypto, "digest and verify bad sig"); + sig[0] ^= 0xff; + dataToDigest[0] ^= 0xff; + is_status(SecKeyDigestAndVerify(pubKey, algId, dataToDigest, dataToDigestLen, + sig, sigLen), errSSLCrypto, "digest and verify bad digest"); + } +} + +static void testdigestandsign(SecKeyRef privKey, SecKeyRef pubKey) { + static const SecAsn1Oid *oids[] = { + &CSSMOID_SHA1WithRSA, + &CSSMOID_SHA224WithRSA, + &CSSMOID_SHA256WithRSA, + &CSSMOID_SHA384WithRSA, + &CSSMOID_SHA512WithRSA, +#if 0 + &CSSMOID_SHA1WithRSA_OIW, + &CSSMOID_SHA1WithDSA, // BSAFE + &CSSMOID_SHA1WithDSA_CMS, // X509/CMS + &CSSMOID_SHA1WithDSA_JDK, // JDK 1.1 +#endif + }; + + + uint32_t ix; + SecAsn1AlgId algId = {}; + for (ix = 0; ix < sizeof(oids) / sizeof(*oids); ++ix) { + if (oids[ix]) { + algId.algorithm = *oids[ix]; + } else { + algId.algorithm.Length = 0; + algId.algorithm.Data = NULL; + } + + testdigestandsignalg(privKey, pubKey, &algId); + } +} +#endif + +#if 0 +static void dump_bytes(uint8_t* bytes, size_t amount) +{ + while (amount > 0) { + printf("0x%02x ", *bytes); + ++bytes; + --amount; + } +} +#endif + + +#if !TARGET_OS_IPHONE +#define kEncryptDecryptTestCount 0 +#else +#define kEncryptDecryptTestCount 6 +static void test_encrypt_decrypt(SecKeyRef pubKey, SecKeyRef privKey, uint32_t padding, size_t keySizeInBytes) +{ + SKIP: { + size_t max_len = keySizeInBytes; + switch (padding) { + case kSecPaddingNone: max_len = keySizeInBytes; break; + case kSecPaddingOAEP: max_len = keySizeInBytes - 2 - 2 * CC_SHA1_DIGEST_LENGTH; break; + case kSecPaddingPKCS1: max_len = keySizeInBytes - 11; break; + default: skip("what is the max_len for this padding?", 5, false); + } + + uint8_t secret[max_len + 1], encrypted_secret[keySizeInBytes], decrypted_secret[keySizeInBytes]; + uint8_t *secret_ptr = secret; + size_t secret_len = max_len; + size_t encrypted_secret_len = sizeof(encrypted_secret); + size_t decrypted_secret_len = sizeof(decrypted_secret); + memset(decrypted_secret, 0xff, decrypted_secret_len); + ok_status(SecRandomCopyBytes(kSecRandomDefault, sizeof(secret), secret),"rng"); + + // zero pad, no accidental second zero byte + if (padding == kSecPaddingNone) { + secret[0] = 0; + secret[1] = 128; + } + + is_status(SecKeyEncrypt(pubKey, padding, + secret, sizeof(secret), + encrypted_secret, &encrypted_secret_len), errSecParam, "encrypt secret (overflow)"); + ok_status(SecKeyEncrypt(pubKey, padding, + secret, secret_len, + encrypted_secret, &encrypted_secret_len), "encrypt secret"); + + ok_status(SecKeyDecrypt(privKey, padding, + encrypted_secret, encrypted_secret_len, + decrypted_secret, &decrypted_secret_len), "decrypt secret"); + + // zero padding is removed on decode + if (padding == kSecPaddingNone) { + secret_len--; + secret_ptr++; + } + + ok(decrypted_secret_len == secret_len, "correct length"); + ok_status(memcmp(secret_ptr, decrypted_secret, secret_len), "verify secret"); + } +} +#endif + +#define kKeyGenTestCount (12 + (3*kEncryptDecryptTestCount)) +static void testkeygen(size_t keySizeInBits) { + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) RSA keypair", keySizeInBits, + keySizeInBytes); + CFRelease(kzib); + CFRelease(kgp); + + SKIP: { + skip("keygen failed", 8, status == errSecSuccess); + ok(pubKey, "pubkey returned"); + ok(privKey, "privKey returned"); + is(SecKeyGetBlockSize(pubKey) * 8, (size_t) keySizeInBits, "public key size is ok"); + is(SecKeyGetBlockSize(privKey) * 8, (size_t) keySizeInBits, "private key size is ok"); + + /* Sign something. */ + uint8_t something[keySizeInBytes]; + size_t something_len = keySizeInBytes - 11; + ok_status(SecRandomCopyBytes(kSecRandomDefault, sizeof(something), something), "rng"); + uint8_t sig[keySizeInBytes]; + size_t sigLen = sizeof(sig); +#if TARGET_OS_IPHONE + /* TODO: This is returning another error on OS X */ + is_status(SecKeyRawSign(privKey, kSecPaddingPKCS1, + something, something_len + 1, sig, &sigLen), + errSecParam, "sign overflow"); +#endif + ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1, + something, something_len, sig, &sigLen), "sign something"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1, + something, something_len, sig, sigLen), "verify sig on something"); + + // Torture test ASN.1 encoder by setting high bit to 1. + uint8_t digest[CC_SHA512_DIGEST_LENGTH] = { + 0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + }; +#if TARGET_OS_IPHONE + /* Thoses tests are making sure that MD2 and MD5 are NOT supported, + but they still are on OS X */ + + //CC_MD2(something, sizeof(something), digest); + ok_status(!SecKeyRawSign(privKey, kSecPaddingPKCS1MD2, + digest, CC_MD2_DIGEST_LENGTH, sig, &sigLen), + "don't sign md2 digest"); //FAIL + ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1MD2, + digest, CC_MD2_DIGEST_LENGTH, sig, sigLen), + "verify sig on md2 digest fails"); //FAIL + + //CC_MD5(something, sizeof(something), digest); + sigLen = sizeof(sig); + ok_status(!SecKeyRawSign(privKey, kSecPaddingPKCS1MD5, + digest, CC_MD5_DIGEST_LENGTH, sig, &sigLen), + "don't sign md5 digest"); //FAIL + ok_status(!SecKeyRawVerify(pubKey, kSecPaddingPKCS1MD5, + digest, CC_MD5_DIGEST_LENGTH, sig, sigLen), + "verify sig on md5 digest fails"); //FAIL +#endif + + //CCDigest(kCCDigestSHA1, something, sizeof(something), digest); + sigLen = sizeof(sig); + ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA1, + digest, CC_SHA1_DIGEST_LENGTH, sig, &sigLen), + "sign sha1 digest"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA1, + digest, CC_SHA1_DIGEST_LENGTH, sig, sigLen), + "verify sig on sha1 digest"); + +#if TARGET_OS_IPHONE + /* The assumptions in these tests are just wrong on OS X */ + uint8_t signature[keySizeInBytes], *ptr = signature; + size_t signature_len = sizeof(signature); + ok_status(SecKeyEncrypt(pubKey, kSecPaddingNone, sig, sigLen, signature, &signature_len), "inspect signature"); + is(signature_len, keySizeInBytes - 1, "got signature"); // FAIL for 2056 + while(*ptr && ((size_t)(ptr - signature) < signature_len)) ptr++; + is(signature + signature_len - ptr, 16 /* length(\0 || OID_SHA1) */ + CC_SHA1_DIGEST_LENGTH, "successful decode"); +#endif + +#if TARGET_OS_IPHONE + /* Those are not supported on OS X */ + /* PKCS1 padding is 00 01 PAD * 8 or more 00 data. + data is SEQ { SEQ { OID NULL } BIT STRING 00 DIGEST } + So min data + pad overhead is 11 + 9 + oidlen + oidlen = 11 for the sha2 family of oids, so we have 29 bytes; or + 232 bits of minimum overhead. */ + const size_t pkcs1Overhead = 232; + if (keySizeInBits > 224 + pkcs1Overhead) { + //CC_SHA224(something, sizeof(something), digest); + sigLen = sizeof(sig); + ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA224, + digest, CC_SHA224_DIGEST_LENGTH, sig, &sigLen), + "sign sha224 digest"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA224, + digest, CC_SHA224_DIGEST_LENGTH, sig, sigLen), + "verify sig on sha224 digest"); + } + + if (keySizeInBits > 256 + pkcs1Overhead) { + //CC_SHA256(something, sizeof(something), digest); + sigLen = sizeof(sig); + ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA256, + digest, CC_SHA256_DIGEST_LENGTH, sig, &sigLen), + "sign sha256 digest"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA256, + digest, CC_SHA256_DIGEST_LENGTH, sig, sigLen), + "verify sig on sha256 digest"); + } + + if (keySizeInBits > 384 + pkcs1Overhead) { + //CC_SHA384(something, sizeof(something), digest); + sigLen = sizeof(sig); + ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA384, + digest, CC_SHA384_DIGEST_LENGTH, sig, &sigLen), + "sign sha384 digest"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA384, + digest, CC_SHA384_DIGEST_LENGTH, sig, sigLen), + "verify sig on sha384 digest"); + } + + if (keySizeInBits > 512 + pkcs1Overhead) { + //CC_SHA512(something, sizeof(something), digest); + sigLen = sizeof(sig); + ok_status(SecKeyRawSign(privKey, kSecPaddingPKCS1SHA512, + digest, CC_SHA512_DIGEST_LENGTH, sig, &sigLen), + "sign sha512 digest"); + ok_status(SecKeyRawVerify(pubKey, kSecPaddingPKCS1SHA512, + digest, CC_SHA512_DIGEST_LENGTH, sig, sigLen), + "verify sig on sha512 digest"); + } + + test_encrypt_decrypt(pubKey, privKey, kSecPaddingNone, keySizeInBytes); + test_encrypt_decrypt(pubKey, privKey, kSecPaddingPKCS1, keySizeInBytes); + test_encrypt_decrypt(pubKey, privKey, kSecPaddingOAEP, keySizeInBytes); + + testdigestandsign(privKey, pubKey); +#endif + + const void *privkeys[] = { + kSecValueRef + }; + const void *privvalues[] = { + privKey + }; + CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, + sizeof(privkeys) / sizeof(*privkeys), NULL, NULL); +#if TARGET_OS_IPHONE + /* OS X: keys are always added to the keychain when generated */ + ok_status(SecItemAdd(privitem, NULL), "add private key"); //FAIL +#endif + ok_status(SecItemDelete(privitem), "delete private key"); + CFReleaseNull(privitem); + + const void *pubkeys[] = { + kSecValueRef + }; + const void *pubvalues[] = { + pubKey + }; + CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, + sizeof(pubkeys) / sizeof(*pubkeys), NULL, NULL); +#if TARGET_OS_IPHONE + /* OS X: keys are always added to the keychain when generated */ + ok_status(SecItemAdd(pubitem, NULL), "add public key"); //FAIL +#endif + ok_status(SecItemDelete(pubitem), "delete public key"); + CFReleaseNull(pubitem); + + /* Cleanup. */ + CFReleaseNull(pubKey); + CFReleaseNull(privKey); + } +} + +#define kKeyGen2TestCount 11 +static void testkeygen2(size_t keySizeInBits) { + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + + CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); + CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); + CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); + CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); + + CFReleaseNull(ourUUID); + CFReleaseNull(uuidString); + + CFStringAppend(publicName, CFSTR("-Public-40")); + CFStringAppend(privateName, CFSTR("-Private-40")); + CFMutableDictionaryRef pubd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFMutableDictionaryRef privd = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + + CFDictionaryAddValue(pubd, kSecAttrLabel, publicName); + CFDictionaryAddValue(privd, kSecAttrLabel, privateName); + + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keySizeInBits); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionaryAddValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue); + CFDictionaryAddValue(kgp, kSecPublicKeyAttrs, pubd); + CFDictionaryAddValue(kgp, kSecPrivateKeyAttrs, privd); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) persistent RSA keypair", + keySizeInBits, keySizeInBytes); + CFRelease(kzib); + CFRelease(kgp); + + SKIP: { + skip("keygen failed", 8, status == errSecSuccess); + ok(pubKey, "pubkey returned"); + ok(privKey, "privKey returned"); + is(SecKeyGetBlockSize(pubKey) * 8, (size_t) keySizeInBits, "public key size is ok"); + is(SecKeyGetBlockSize(privKey) * 8, (size_t) keySizeInBits, "private key size is ok"); + + SecKeyRef pubKey2, privKey2; + CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); + CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(privd, kSecClass, kSecClassKey); + CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); + ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), + "retrieve pub key by label"); + ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), + "retrieve priv key by label and kSecAttrCanSign"); + + /* Sign something. */ + uint8_t something[50] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; + uint8_t sig[keySizeInBytes]; + size_t sigLen = keySizeInBytes; + ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, + something, sizeof(something), sig, &sigLen), "sign something"); + ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, + something, sizeof(something), sig, sigLen), "verify sig on something"); + +#if TARGET_OS_IPHONE + /* SecKeyEncrypt does not return errSecParam on OS X in that case */ + sigLen = keySizeInBytes; + is_status(SecKeyEncrypt(pubKey2, kSecPaddingPKCS1SHA1, + something, sizeof(something), sig, &sigLen), errSecParam, + "encrypt something with invalid padding"); +#endif + + /* Cleanup. */ + CFReleaseNull(pubKey2); + CFReleaseNull(privKey2); + + /* delete from keychain - note: do it before releasing publicName and privateName + because pubd and privd have no retain/release callbacks */ + ok_status(SecItemDelete(pubd), "delete generated pub key"); + ok_status(SecItemDelete(privd), "delete generated priv key"); + } + + /* Cleanup. */ + CFReleaseNull(pubKey); + CFReleaseNull(privKey); + + CFReleaseNull(publicName); + CFReleaseNull(privateName); + + CFRelease(pubd); + CFRelease(privd); +} + + +#if !TARGET_OS_IPHONE +// Only exists currently in MacOSX +typedef struct KDFVector_t { + char *password; + char *salt; + int rounds; + int alg; + int dklen; + char *expectedstr; + int expected_failure; +} KDFVector; + +static KDFVector kdfv[] = { + // Test Case PBKDF2 - HMACSHA1 http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-00 + { "password", "salt", 1, 1, 160, "0c60c80f961f0e71f3a9b524af6012062fe037a6", 0 }, + { "password", "salt", 2, 1, 160, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", 0 }, + { "password", "salt", 4096, 1, 160, "4b007901b765489abead49d926f721d065a429c1", 0 }, + { "password", "salt", 1, 0, 160, NULL, -1} // This crashed +}; + +static size_t kdfvLen = sizeof(kdfv) / sizeof(KDFVector); + +static int testSecKDF(CFStringRef password, CFDataRef salt, CFNumberRef rounds, CFStringRef alg, CFNumberRef dklen, CFDataRef expected, int expected_failure) { + CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + int retval = 0; + + CFDictionaryAddValue(parameters, kSecAttrSalt, salt); + CFDictionaryAddValue(parameters, kSecAttrKeySizeInBits, dklen); + CFDictionaryAddValue(parameters, kSecAttrPRF, alg); + CFDictionaryAddValue(parameters, kSecAttrRounds, rounds); + + SecKeyRef derivedKey = SecKeyDeriveFromPassword(password, parameters, NULL); + if(derivedKey == NULL && expected_failure) { + ok(1, "Correctly failed to produce a key"); + goto errOut; + } else if(derivedKey == NULL) { + ok(0, "Could not generate a key when we should have"); + goto errOut; + } + ok(1, "Made a new key"); + retval = 1; + // NEEDS Fix -- ok(status = expectedEqualsComputed(expected, derivedKey), "Derived key is as expected"); +errOut: + if(parameters) CFRelease(parameters); + if(derivedKey) CFRelease(derivedKey); + return retval; +} + +static CFDataRef CFDataCreateFromHexBytes(char *s) { + if(!s) return NULL; + size_t len = strlen(s); + if(len%2) return NULL; + len /= 2; + uint8_t buf[len]; + for(size_t i=0; iexpectedstr); + CFStringRef password = CFStringCreateWithCString(NULL, kdfvec->password, kCFStringEncodingUTF8); + CFDataRef salt = CFDataCreate(NULL, (const UInt8 *)kdfvec->salt, strlen(kdfvec->salt)); + CFNumberRef rounds = CFNumberCreate(NULL, kCFNumberIntType, &kdfvec->rounds); + CFNumberRef dklen = CFNumberCreate(NULL, kCFNumberIntType, &kdfvec->dklen); + int status = 1; + + ok(testSecKDF(password, salt, rounds, kSecAttrPRFHmacAlgSHA1, dklen, expectedBytes, kdfvec->expected_failure), "Test SecKeyDeriveFromPassword PBKDF2"); + + if(expectedBytes) CFRelease(expectedBytes); + return status; +} + + +static void testkeyderivation() { + for(size_t testcase = 0; testcase < kdfvLen; testcase++) { + // diag("Test %lu\n", testcase + 1); + ok(PBKDF2Test(&kdfv[testcase]), "Successful full test of KDF Vector"); + } +} + +#else +static size_t kdfvLen = 0; // no kdf functions in Sec for iphone +#endif /* !TARGET_OS_IPHONE */ + +static void delete_key(SecKeyRef *key) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(query, kSecValueRef, *key); + SecItemDelete(query); + CFReleaseNull(query); + CFReleaseNull(*key); +} + +static const int kTestSupportedCount = 3 + (4 * 12) + 2 + (4 * 10) + 2; +static void testsupportedalgos(size_t keySizeInBits) +{ + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + + int32_t iKeySizeInBits = (int32_t) keySizeInBits; + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) persistent RSA keypair", + keySizeInBits, keySizeInBytes); + CFRelease(kzib); + CFRelease(kgp); + + is(SecKeyGetBlockSize(pubKey) * 8, (size_t) keySizeInBits, "public key size is ok"); + is(SecKeyGetBlockSize(privKey) * 8, (size_t) keySizeInBits, "private key size is ok"); + + const SecKeyAlgorithm sign[] = { + kSecKeyAlgorithmRSASignatureRaw, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, + }; + + for (size_t i = 0; i < array_size(sign); i++) { + SecKeyAlgorithm algorithm = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), sign[i]); + ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeSign, algorithm), + "privKey supports sign algorithm %@", algorithm); + ok(SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeVerify, algorithm), + "pubKey supports verify algorithm %@", algorithm); + // Since private key supports RSA decryption, our verify adapters happily accepts it. + ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeVerify, algorithm), + "privKey supports verify algorithm %@", algorithm); + ok(!SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeSign, algorithm), + "pubKey doesn't support sign algorithm %@", algorithm); + CFReleaseNull(algorithm); + } + ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeSign, kSecKeyAlgorithmECDSASignatureDigestX962), + "RSA privKey does not support ECDSA algorithm"); + ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeVerify, kSecKeyAlgorithmECDSASignatureDigestX962), + "RSA pubKey does not support ECDSA algorithm"); + + const SecKeyAlgorithm crypt[] = { + kSecKeyAlgorithmRSAEncryptionRaw, + kSecKeyAlgorithmRSAEncryptionPKCS1, + kSecKeyAlgorithmRSAEncryptionOAEPSHA1, + kSecKeyAlgorithmRSAEncryptionOAEPSHA224, + kSecKeyAlgorithmRSAEncryptionOAEPSHA256, + kSecKeyAlgorithmRSAEncryptionOAEPSHA384, + kSecKeyAlgorithmRSAEncryptionOAEPSHA1AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA224AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA256AESGCM, + kSecKeyAlgorithmRSAEncryptionOAEPSHA384AESGCM, +// kSecKeyAlgorithmRSAEncryptionOAEPSHA512, + }; + for (size_t i = 0; i < array_size(crypt); i++) { + SecKeyAlgorithm algorithm = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), crypt[i]); + ok(SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeDecrypt, algorithm), + "privKey supports decrypt algorithm %@", algorithm); + ok(SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeEncrypt, algorithm), + "pubKey supports encrypt algorithm %@", algorithm); + ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeEncrypt, algorithm), + "privKey doesn't supports encrypt algorithm %@", algorithm); + ok(!SecKeyIsAlgorithmSupported(pubKey, kSecKeyOperationTypeDecrypt, algorithm), + "pubKey doesn't support decrypt algorithm %@", algorithm); + CFReleaseNull(algorithm); + } + ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeDecrypt, kSecKeyAlgorithmRSAEncryptionOAEPSHA512), + "privKey doesn't support decrypt algorithm %@", kSecKeyAlgorithmRSAEncryptionOAEPSHA512); + ok(!SecKeyIsAlgorithmSupported(privKey, kSecKeyOperationTypeDecrypt, kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM), + "privKey doesn't support decrypt algorithm %@", kSecKeyAlgorithmRSAEncryptionOAEPSHA512AESGCM); + + /* Cleanup. */ + delete_key(&pubKey); + delete_key(&privKey); +} + +#if 0 +#define kTestSupportedCount 15 +static void testsupportedalgos(size_t keySizeInBits) +{ + SecKeyRef pubKey = NULL, privKey = NULL; + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + CFNumberRef kzib; + + int32_t iKeySizeInBits = (int32_t) keySizeInBits; + kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &iKeySizeInBits); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); + CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionaryAddValue(kgp, kSecAttrLabel, CFSTR("sectests:testsupportedalgos")); + + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) persistent RSA keypair", + keySizeInBits, keySizeInBytes); + CFRelease(kzib); + CFRelease(kgp); + + is(SecKeyGetBlockSize(pubKey) * 8, (size_t) keySizeInBits, "public key size is ok"); + is(SecKeyGetBlockSize(privKey) * 8, (size_t) keySizeInBits, "private key size is ok"); + + CFSetRef keySet, expectedSet; + + CFIndex value = kSecKeyAlgorithmECDSASignatureDigestX962; + CFNumberRef ECDSAX962 = CFNumberCreate(NULL, kCFNumberCFIndexType, &value); + value = kSecKeyAlgorithmRSAEncryptionRaw; + CFNumberRef RSARaw = CFNumberCreate(NULL, kCFNumberCFIndexType, &value); + + { // privkey + keySet = SecKeyCopySupportedAlgorithms(privKey, kSecKeyOperationTypeSign); + const SecKeyAlgorithm sign[] = { + kSecKeyAlgorithmRSASignatureRaw, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, + }; + expectedSet = createAlgorithmSet(sign, array_size(sign)); + ok(CFSetIsSubset(expectedSet, keySet), "privkey contains expecting algos for signing"); + ok(!CFSetContainsValue(keySet, ECDSAX962)); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + + keySet = SecKeyCopySupportedAlgorithms(privKey, kSecKeyOperationTypeVerify); + expectedSet = createAlgorithmSet(sign, array_size(sign)); + ok(CFSetIsSubset(expectedSet, keySet), "privkey contains expecting algos for verification"); + ok(!CFSetContainsValue(keySet, ECDSAX962)); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + + keySet = SecKeyCopySupportedAlgorithms(privKey, kSecKeyOperationTypeDecrypt); + const SecKeyAlgorithm decrypt[] = { + kSecKeyAlgorithmRSAEncryptionRaw, + kSecKeyAlgorithmRSAEncryptionPKCS1, + kSecKeyAlgorithmRSAEncryptionOAEPSHA1, + kSecKeyAlgorithmRSAEncryptionOAEPSHA224, + kSecKeyAlgorithmRSAEncryptionOAEPSHA256, + kSecKeyAlgorithmRSAEncryptionOAEPSHA384, + kSecKeyAlgorithmRSAEncryptionOAEPSHA512, + }; + expectedSet = createAlgorithmSet(decrypt, array_size(decrypt)); + ok(CFSetIsSubset(expectedSet, keySet), "privkey contains expecting algos for decryption"); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + + keySet = SecKeyCopySupportedAlgorithms(privKey, kSecKeyOperationTypeEncrypt); + expectedSet = CFSetCreate(NULL, NULL, 0, &kCFTypeSetCallBacks); + is(CFSetGetCount(keySet), 0, "privkey contains no algos for encryption"); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + } + + { // pubkey + keySet = SecKeyCopySupportedAlgorithms(pubKey, kSecKeyOperationTypeVerify); + const SecKeyAlgorithm verify[] = { + kSecKeyAlgorithmRSASignatureRaw, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, + }; + expectedSet = createAlgorithmSet(verify, array_size(verify)); + ok(CFSetIsSubset(expectedSet, keySet), "pubkey contains expecting algos for verification"); + ok(!CFSetContainsValue(keySet, ECDSAX962), + "pubkey does not contain ECDSA algorithms for verification"); + ok(!CFSetContainsValue(keySet, RSARaw), + "pubkey does not contain encryption-specific algorithm for verification"); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + + keySet = SecKeyCopySupportedAlgorithms(pubKey, kSecKeyOperationTypeSign); + expectedSet = CFSetCreate(NULL, NULL, 0, &kCFTypeSetCallBacks); + is(CFSetGetCount(keySet), 0, "pubkey contains no algos for signing"); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + + const SecKeyAlgorithm crypt[] = { + kSecKeyAlgorithmRSAEncryptionRaw, + kSecKeyAlgorithmRSAEncryptionPKCS1, + kSecKeyAlgorithmRSAEncryptionOAEPSHA1, + kSecKeyAlgorithmRSAEncryptionOAEPSHA224, + kSecKeyAlgorithmRSAEncryptionOAEPSHA256, + kSecKeyAlgorithmRSAEncryptionOAEPSHA384, + kSecKeyAlgorithmRSAEncryptionOAEPSHA512, + }; + expectedSet = createAlgorithmSet(crypt, array_size(crypt)); + keySet = SecKeyCopySupportedAlgorithms(pubKey, kSecKeyOperationTypeDecrypt); +#if TARGET_OS_IPHONE + ok(CFSetIsSubset(expectedSet, keySet), "pubkey contains expecting algos for decryption"); +#else + ok(CFSetGetCount(keySet) == 0, "pubkey cannot decrypt"); +#endif + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + + keySet = SecKeyCopySupportedAlgorithms(pubKey, kSecKeyOperationTypeEncrypt); + expectedSet = createAlgorithmSet(crypt, array_size(crypt)); + ok(CFSetIsSubset(expectedSet, keySet), "pubkey contains expecting algos for encryption"); + CFReleaseNull(keySet); + CFReleaseNull(expectedSet); + } + + /* Cleanup. */ + CFReleaseNull(RSARaw); + CFReleaseNull(ECDSAX962); + delete_key(&pubKey); + delete_key(&privKey); +} +#endif + +#if !TARGET_OS_IPHONE +static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right) +{ + if (left == NULL || right == NULL) + return left == right; + else + return CFEqual(left, right); +} +#endif + +#define kCreateWithDataTestCount 13 +static void testcreatewithdata(unsigned long keySizeInBits) +{ + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionarySetValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionarySetValue(kgp, kSecAttrIsPermanent, kCFBooleanFalse); + CFDictionarySetValue(kgp, kSecAttrLabel, CFSTR("sectests:createwithdata")); + + SecKeyRef pubKey = NULL, privKey = NULL; + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) RSA keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + CFReleaseNull(kgp); + + CFMutableDictionaryRef kcwd = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks);; + CFDictionarySetValue(kcwd, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionarySetValue(kcwd, kSecAttrKeySizeInBits, kzib); + CFDictionarySetValue(kcwd, kSecAttrIsPermanent, kCFBooleanFalse); + CFReleaseNull(kzib); + + CFErrorRef error = NULL; + CFDataRef privExternalData = NULL, pubExternalData = NULL; + SecKeyRef dataKey = NULL; + + { // privKey + privExternalData = SecKeyCopyExternalRepresentation(privKey, &error); + ok(privExternalData && CFGetTypeID(privExternalData) == CFDataGetTypeID(), + "priv key SecKeyCopyExternalRepresentation failed"); + CFReleaseNull(error); + + SKIP: { + skip("invalid priv key external data", 4, privExternalData); + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error); + ok(dataKey, "priv key SecKeyCreateWithData failed"); + CFReleaseNull(error); + + eq_cf(privExternalData, SecKeyCopyExternalRepresentation(dataKey, NULL), "priv keys differ"); + CFReleaseNull(dataKey); + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); + dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error); + ok(!dataKey, "priv key SecKeyCreateWithData succeeded with invalid kSecAttrKeyClass"); + CFReleaseNull(error); + CFReleaseNull(dataKey); + + CFMutableDataRef modifiedExternalData = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, privExternalData); + *CFDataGetMutableBytePtr(modifiedExternalData) ^= 0xff; + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + dataKey = SecKeyCreateWithData(modifiedExternalData, kcwd, &error); + ok(!dataKey, "priv key SecKeyCreateWithData succeeded with invalid external data"); + CFReleaseNull(error); + CFReleaseNull(dataKey); + + CFReleaseNull(modifiedExternalData); + } + } + + { // pubKey + pubExternalData = SecKeyCopyExternalRepresentation(pubKey, &error); + ok(pubExternalData && CFGetTypeID(pubExternalData) == CFDataGetTypeID(), + "pub key SecKeyCopyExternalRepresentation failed"); + CFReleaseNull(error); + + SKIP: { + skip("invalid pub key external data", 4, pubExternalData); + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); + dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error); + ok(dataKey, "pub key SecKeyCreateWithData failed"); + CFReleaseNull(error); + + eq_cf(pubExternalData, SecKeyCopyExternalRepresentation(dataKey, NULL), "pub keys differ"); + CFReleaseNull(dataKey); + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error); + ok(!dataKey, "pub key SecKeyCreateWithData succeeded with invalid kSecAttrKeyClass"); + CFReleaseNull(error); + CFReleaseNull(dataKey); + + CFMutableDataRef modifiedExternalData = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, pubExternalData); + *CFDataGetMutableBytePtr(modifiedExternalData) ^= 0xff; + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); + dataKey = SecKeyCreateWithData(modifiedExternalData, kcwd, &error); + ok(!dataKey, "pub key SecKeyCreateWithData succeeded with invalid external data"); + CFReleaseNull(error); + CFReleaseNull(dataKey); + + CFReleaseNull(modifiedExternalData); + } + } + +SKIP: { + skip("invalid pub key external data", 1, pubExternalData); + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPrivate); + dataKey = SecKeyCreateWithData(pubExternalData, kcwd, &error); + ok(!dataKey, "priv key SecKeyCreateWithData succeeded with public external data"); + CFReleaseNull(error); + CFReleaseNull(dataKey); + + CFReleaseNull(pubExternalData); +} + +SKIP: { + skip("invalid priv key external data", 1, privExternalData); + + CFDictionarySetValue(kcwd, kSecAttrKeyClass, kSecAttrKeyClassPublic); + dataKey = SecKeyCreateWithData(privExternalData, kcwd, &error); + ok(!dataKey, "pub key SecKeyCreateWithData succeeded with private external data"); + CFReleaseNull(error); + CFReleaseNull(dataKey); + + CFReleaseNull(privExternalData); +} + + CFReleaseNull(kcwd); + delete_key(&pubKey); + delete_key(&privKey); +} + +#define kCopyAttributesTestCount 20 +static void testcopyattributes(unsigned long keySizeInBits, bool extractable) +{ + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionarySetValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionarySetValue(kgp, kSecAttrIsExtractable, extractable ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(kgp, kSecAttrLabel, CFSTR("sectests:copyattributes")); + SecKeyRef pubKey = NULL, privKey = NULL; + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) RSA keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + CFReleaseNull(kgp); + + CFDictionaryRef attributes; + CFTypeRef attrValue = NULL, privAppLabel = NULL, pubAppLabel = NULL; + + { // privKey + attributes = SecKeyCopyAttributes(privKey); + ok(attributes && CFGetTypeID(attributes) == CFDictionaryGetTypeID(), + "priv key SecKeyCopyAttributes failed"); + + SKIP: { + skip("invalid attributes", 8, attributes); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanEncrypt); + eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanEncrypt"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDecrypt); + eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanDecrypt"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDerive); + eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanDerive"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanSign); + eq_cf(attrValue, kCFBooleanTrue, "invalid priv key kSecAttrCanSign"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanVerify); + eq_cf(attrValue, kCFBooleanFalse, "invalid priv key kSecAttrCanVerify"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyClass); + eq_cf(attrValue, kSecAttrKeyClassPrivate, "priv key invalid kSecAttrKeyClass"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyType); + eq_cf(attrValue, kSecAttrKeyTypeRSA, "invalid priv key kSecAttrKeyType"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits); + eq_cf(attrValue, kzib, "invalid priv key kSecAttrKeySizeInBits"); + + privAppLabel = CFDictionaryGetValue(attributes, kSecAttrApplicationLabel); + CFRetainSafe(privAppLabel); + + CFReleaseNull(attributes); + } + } + + { // pubKey + attributes = SecKeyCopyAttributes(pubKey); + ok(attributes && CFGetTypeID(attributes) == CFDictionaryGetTypeID(), + "pub key SecKeyCopyAttributes failed"); + + SKIP: { + skip("invalid attributes", 8, attributes); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanEncrypt); + eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanEncrypt"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDecrypt); + eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanDecrypt"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanDerive); + eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanDerive"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanSign); + eq_cf(attrValue, kCFBooleanFalse, "pub key invalid kSecAttrCanSign"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrCanVerify); + eq_cf(attrValue, kCFBooleanTrue, "pub key invalid kSecAttrCanVerify"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyClass); + eq_cf(attrValue, kSecAttrKeyClassPublic, "pub key invalid kSecAttrKeyClass"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrKeyType); + eq_cf(attrValue, kSecAttrKeyTypeRSA, "pub key invalid kSecAttrKeyType"); + + attrValue = CFDictionaryGetValue(attributes, kSecAttrKeySizeInBits); + eq_cf(attrValue, kzib, "pub key invalid kSecAttrKeySizeInBits"); + + pubAppLabel = CFDictionaryGetValue(attributes, kSecAttrApplicationLabel); + CFRetainSafe(pubAppLabel); + + CFReleaseNull(attributes); + } + } + + eq_cf(privAppLabel, pubAppLabel, "priv key and pub key kSecAttrApplicationLabel differ"); + + CFReleaseNull(privAppLabel); + CFReleaseNull(pubAppLabel); + CFReleaseNull(kzib); + delete_key(&pubKey); + delete_key(&privKey); +} + +#define kCopyPublicKeyTestCount 5 +static void testcopypublickey(unsigned long keySizeInBits, bool extractable, bool permanent) { + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionarySetValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionarySetValue(kgp, kSecAttrIsPermanent, permanent ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(kgp, kSecAttrIsExtractable, extractable ? kCFBooleanTrue : kCFBooleanFalse); + CFDictionarySetValue(kgp, kSecAttrLabel, CFSTR("sectests:copypublickey")); + SecKeyRef pubKey = NULL, privKey = NULL; + OSStatus status; + if (permanent) { + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) RSA keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + } else { + NSError *error = nil; + privKey = SecKeyCreateRandomKey(kgp, (void *)&error); + pubKey = SecKeyCopyPublicKey(privKey); + ok(privKey != NULL && pubKey != NULL, "Generate %ld bit (%ld byte) RSA keypair (error %@)", + keySizeInBits, keySizeInBytes, error); + } + CFReleaseNull(kgp); + CFReleaseNull(kzib); + + CFDataRef pubKeyData = SecKeyCopyExternalRepresentation(pubKey, NULL); + + SecKeyRef pubKeyCopy = NULL; + + { // privKey + pubKeyCopy = SecKeyCopyPublicKey(privKey); + ok(pubKeyCopy, "priv key SecKeyCopyPublicKey failed"); + CFDataRef pubKeyCopyData = SecKeyCopyExternalRepresentation(pubKeyCopy, NULL); + eq_cf(pubKeyCopyData, pubKeyData, "pub key from priv key SecKeyCopyPublicKey and pub key differ"); + CFReleaseNull(pubKeyCopy); + CFReleaseNull(pubKeyCopyData); + } + + { // pubKey + pubKeyCopy = SecKeyCopyPublicKey(pubKey); + ok(pubKeyCopy, "pub key SecKeyCopyPublicKey failed"); + CFDataRef pubKeyCopyData = SecKeyCopyExternalRepresentation(pubKeyCopy, NULL); + eq_cf(pubKeyCopyData, pubKeyData, "pub key from pub key SecKeyCopyPublicKey and pub key differ"); + CFReleaseNull(pubKeyCopy); + CFReleaseNull(pubKeyCopyData); + } + + CFReleaseNull(pubKeyData); + if (permanent) { + delete_key(&pubKey); + delete_key(&privKey); + } else { + CFReleaseSafe(pubKey); + CFReleaseSafe(privKey); + } +} + +static const char *kCertWithPubK = "\ +MIIELjCCAxagAwIBAgIJALJlcYRBqZlZMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYDVQQGEwJVUzELMAkG\ +A1UECBMCQ0ExEjAQBgNVBAcTCUN1cGVydGlubzETMBEGA1UEChMKQXBwbGUgSW5jLjEPMA0GA1UECxMG\ +Q29yZU9TMRwwGgYDVQQDExNBcHBsZSBUZXN0IENBMSBDZXJ0MSAwHgYJKoZIhvcNAQkBFhF2a3V6ZWxh\ +QGFwcGxlLmNvbTAeFw0xNTA0MjkwODMyMDBaFw0yNTA0MjYwODMyMDBaMIGPMQswCQYDVQQGEwJVUzEL\ +MAkGA1UECBMCQ0ExEjAQBgNVBAcTCUN1cGVydGlubzETMBEGA1UEChMKQXBwbGUgSW5jLjEQMA4GA1UE\ +CxMHQ29yZSBPUzEWMBQGA1UEAxMNRmlsaXAgU3Rva2xhczEgMB4GCSqGSIb3DQEJARYRc3Rva2xhc0Bh\ +cHBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZcPMvjpu7i/2SkNDCrSC4Wa8m\ +j3r6Lgn0crL4AgU+g3apptyy1eFf4RpNRJTGJ9ZMApbRZ0b7wX87Dq6UlCJUI9RJPOy+/TW0FM6mUVaF\ +VSY+P+KMdRYGIOMLVI+LR6lRTf8MWbxZ238cqAIVnLHaE9HrXjyIrgX2IufJjt69WhwsJZuan7jmeXJS\ +0AnESB31wS5NOn0tFDtzNAAQmoP8N8q6ZNC85tPVWBM61YLNjwSYl74y14QfX401P2pQRvwxTortRImk\ +xjN4DBprG23e59UW2IBxYsqUA61jhA0yVy8gxYpCGa4bEBslhrnkAoSv+Zlyk7u2GyO13AC1dfRxAgMB\ +AAGjgYUwgYIwPwYDVR0RBDgwNqAhBgorBgEEAYI3FAIDoBMMEXN0b2tsYXNAYXBwbGUuY29tgRFzdG9r\ +bGFzQGFwcGxlLmNvbTA/BgNVHREEODA2oCEGCisGAQQBgjcUAgOgEwwRc3Rva2xhc0BhcHBsZS5jb22B\ +EXN0b2tsYXNAYXBwbGUuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQB87bZdl4XEDFA7UdPouhR3dKRl6evS\ +MfC9/0jVcdB+P1mNJ/vIZdOZMY0asieOXhsI91nEcHUjbBCnu18mu2jR6SGiJsS/zr6enkpQMcztulMU\ +kcjuSjT1hEzRv0LvEgWPOK+VpVqk6N0ZhybBQYVH2ECf7OU48CkFQFg9eLv6VaSK9+FqcBWpq8fXyOa7\ +bL58bO5A3URHcmMWibv9/j+lpVeQBxt1UUwqBZT7DSLPw3QCj/zXfAGEu3izvEYaWwsQDhItwQJ6g6pp\ +DLO741C7K8eKgvGs8ptna4RSosQda9bdnhZwT+g0UcorsVTUo+sR9+LW7INJ1zovRCL7NXit"; + +static const char *kPubK = "\ +MIIBCgKCAQEA2XDzL46bu4v9kpDQwq0guFmvJo96+i4J9HKy+AIFPoN2qabcstXhX+EaTUSUxifWTAKW\ +0WdG+8F/Ow6ulJQiVCPUSTzsvv01tBTOplFWhVUmPj/ijHUWBiDjC1SPi0epUU3/DFm8Wdt/HKgCFZyx\ +2hPR6148iK4F9iLnyY7evVocLCWbmp+45nlyUtAJxEgd9cEuTTp9LRQ7czQAEJqD/DfKumTQvObT1VgT\ +OtWCzY8EmJe+MteEH1+NNT9qUEb8MU6K7USJpMYzeAwaaxtt3ufVFtiAcWLKlAOtY4QNMlcvIMWKQhmu\ +GxAbJYa55AKEr/mZcpO7thsjtdwAtXX0cQIDAQAB"; + +static const int kTestCountCopyPubKFromCert = 2; +static void testcopypubkfromcert() { + NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:kCertWithPubK] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + NSData *pubKData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:kPubK] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData); + SecKeyRef pubKey = NULL; + ok_status(SecCertificateCopyPublicKey(cert, &pubKey), "export public key from certificate"); + NSData *pubKeyData = (NSData *)SecKeyCopyExternalRepresentation(pubKey, NULL); + eq_cf(pubKeyData, pubKData, "public key exports itself into expected data"); + CFReleaseNull(pubKey); + CFReleaseNull(cert); +} + +static inline CFDataRef CFDataCreateWithHash(CFAllocatorRef allocator, const struct ccdigest_info *di, const uint8_t *buffer, const uint8_t length) { + CFMutableDataRef result = CFDataCreateMutable(allocator, di->output_size); + CFDataSetLength(result, di->output_size); + + ccdigest(di, length, buffer, CFDataGetMutableBytePtr(result)); + + return result; +} + +#define kSignAndVerifyTestCount 130 +static void testsignverify(unsigned long keySizeInBits) +{ + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionarySetValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionarySetValue(kgp, kSecAttrIsPermanent, kCFBooleanFalse); + CFDictionarySetValue(kgp, kSecAttrLabel, CFSTR("sectests:signverify")); + SecKeyRef pubKey = NULL, privKey = NULL, pubKeyIOS = NULL, privKeyIOS = NULL; + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) RSA keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + CFReleaseNull(kgp); + CFReleaseNull(kzib); + + CFDataRef privKeyData = SecKeyCopyExternalRepresentation(privKey, NULL); + CFDictionaryRef privKeyAttrs = SecKeyCopyAttributes(privKey); + privKeyIOS = SecKeyCreateWithData(privKeyData, privKeyAttrs, NULL); + CFReleaseNull(privKeyData); + CFReleaseNull(privKeyAttrs); + ok(privKeyIOS, "create IOS version of the private key"); + + CFDataRef pubKeyData = SecKeyCopyExternalRepresentation(pubKey, NULL); + CFDictionaryRef pubKeyAttrs = SecKeyCopyAttributes(pubKey); + pubKeyIOS = SecKeyCreateWithData(pubKeyData, pubKeyAttrs, NULL); + CFReleaseNull(pubKeyData); + CFReleaseNull(pubKeyAttrs); + ok(pubKeyIOS, "create IOS version of the public key"); + + SecKeyAlgorithm algorithms[] = { + kSecKeyAlgorithmRSASignatureRaw, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA224, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384, + kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, + }; + + CFDataRef testData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, CFSTR("test"), kCFStringEncodingUTF8, 0); + ok(testData, "creating test data failed"); + +SKIP: { + skip("invalid test data", 71, testData); + + CFErrorRef error = NULL; + + for (uint32_t ix = 0; ix < array_size(algorithms); ++ix) { + SecKeyAlgorithm algorithm = algorithms[ix]; + SecKeyAlgorithm incompatibleAlgorithm = (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureRaw)) ? + kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 : kSecKeyAlgorithmRSASignatureRaw; + + CFDataRef dataToSign = NULL; + if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1)) { + dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha1_di(), + CFDataGetBytePtr(testData), CFDataGetLength(testData)); + ok(dataToSign, "creating digest failed for algorithm %@", algorithm); + } + else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA224)) { + dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha224_di(), + CFDataGetBytePtr(testData), CFDataGetLength(testData)); + ok(dataToSign, "creating digest failed for algorithm %@", algorithm); + } + else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256)) { + dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha256_di(), + CFDataGetBytePtr(testData), CFDataGetLength(testData)); + ok(dataToSign, "creating digest failed for algorithm %@", algorithm); + } + else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384)) { + dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha384_di(), + CFDataGetBytePtr(testData), CFDataGetLength(testData)); + ok(dataToSign, "creating digest failed for algorithm %@", algorithm); + } + else if (CFEqual(algorithm, kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512)) { + dataToSign = CFDataCreateWithHash(kCFAllocatorDefault, ccsha512_di(), + CFDataGetBytePtr(testData), CFDataGetLength(testData)); + ok(dataToSign, "creating digest failed for algorithm %@", algorithm); + } + else { + CFRetainAssign(dataToSign, testData); + } + CFReleaseNull(error); + + SKIP: { + skip("invalid data to sign", 7, dataToSign); + + CFDataRef signature = SecKeyCreateSignature(pubKey, algorithm, dataToSign, &error); + ok(!signature, "SecKeyCopySignature succeeded with pub key for algorithm %@", algorithm); + CFReleaseNull(error); + CFReleaseNull(signature); + + signature = SecKeyCreateSignature(privKey, algorithm, dataToSign, &error); + ok(signature, "SecKeyCopySignature failed for algorithm %@", algorithm); + CFReleaseNull(error); + + CFDataRef iosSignature = SecKeyCreateSignature(privKeyIOS, algorithm, dataToSign, &error); + ok(iosSignature, "SecKeyCopySignature(ios) failed for algorithm %@", algorithm); + CFReleaseNull(error); + + SKIP: { + skip("invalid signature", 4, signature); + + ok(!SecKeyVerifySignature(privKey, algorithm, dataToSign, signature, &error), + "SecKeyVerifySignature succeeded with priv key for algorithm %@", algorithm); + CFReleaseNull(error); + + ok(!SecKeyVerifySignature(pubKey, incompatibleAlgorithm, dataToSign, signature, &error), + "SecKeyVerifySignature succeeded with wrong algorithm for algorithm %@", algorithm); + CFReleaseNull(error); + + ok(SecKeyVerifySignature(pubKey, algorithm, dataToSign, signature, &error), + "SecKeyVerifySignature(osx) failed osx-signature for algorithm %@", algorithm); + CFReleaseNull(error); + + ok(SecKeyVerifySignature(pubKeyIOS, algorithm, dataToSign, signature, &error), + "SecKeyVerifySignature(ios) failed for osx-signature for algorithm %@", algorithm); + + ok(SecKeyVerifySignature(pubKey, algorithm, dataToSign, iosSignature, &error), + "SecKeyVerifySignature(osx) failed for ios-signature for algorithm %@", algorithm); + CFReleaseNull(error); + + ok(SecKeyVerifySignature(pubKeyIOS, algorithm, dataToSign, iosSignature, &error), + "SecKeyVerifySignature(ios) failed for ios-signature for algorithm %@", algorithm); + + CFMutableDataRef modifiedSignature = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, signature); + *CFDataGetMutableBytePtr(modifiedSignature) ^= 0xff; + + ok(!SecKeyVerifySignature(pubKey, algorithm, dataToSign, modifiedSignature, &error), + "SecKeyVerifySignature succeeded with bad signature for algorithm %@", algorithm); + CFReleaseNull(error); + + CFMutableDataRef modifiedDataToSign = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, dataToSign); + *CFDataGetMutableBytePtr(modifiedDataToSign) ^= 0xff; + + ok(!SecKeyVerifySignature(pubKey, algorithm, modifiedDataToSign, signature, &error), + "SecKeyVerifySignature succeeded with bad data for algorithm %@", algorithm); + CFReleaseNull(error); + + CFReleaseNull(modifiedDataToSign); + CFReleaseNull(modifiedSignature); + CFReleaseNull(signature); + CFReleaseNull(iosSignature); + } + CFReleaseNull(dataToSign); + } + } + CFReleaseNull(testData); +} + + delete_key(&pubKey); + delete_key(&privKey); + CFReleaseNull(pubKeyIOS); + CFReleaseNull(privKeyIOS); +} + +#define kNonExtractableTestCount 6 +static void testnonextractable(unsigned long keySizeInBits) +{ + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + int32_t keysz32 = (int32_t)keySizeInBits; + + CFNumberRef kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); + CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeRSA); + CFDictionarySetValue(kgp, kSecAttrKeySizeInBits, kzib); + CFDictionarySetValue(kgp, kSecAttrIsPermanent, kCFBooleanTrue); + CFDictionarySetValue(kgp, kSecAttrIsExtractable, kCFBooleanFalse); + CFStringRef label = CFSTR("sectests:nonextractable"); + CFDictionarySetValue(kgp, kSecAttrLabel, label); + SecKeyRef pubKey = NULL, privKey = NULL; + OSStatus status; + ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), + "Generate %ld bit (%ld byte) RSA keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + CFReleaseNull(kgp); + CFReleaseNull(kzib); + + // Get attributes, verify that ApplicationLabel is set and equals for both keys. + CFDictionaryRef privAttrs = SecKeyCopyAttributes(privKey); + CFDictionaryRef pubAttrs = SecKeyCopyAttributes(pubKey); + + ok(privAttrs, "able to get private key attributes"); + ok(pubAttrs, "able to get public key attributes"); + + CFDataRef privLabel = CFDictionaryGetValue(privAttrs, kSecAttrApplicationLabel); + CFDataRef pubLabel = CFDictionaryGetValue(pubAttrs, kSecAttrApplicationLabel); + + ok(privLabel && CFGetTypeID(privLabel) == CFDataGetTypeID() && CFDataGetLength(privLabel) == 20, + "priv appLabel is present and of correct type"); + ok(pubLabel && CFGetTypeID(pubLabel) == CFDataGetTypeID() && CFDataGetLength(pubLabel) == 20, + "priv appLabel is present and of correct type"); + eq_cf(privLabel, pubLabel, "applabels of pub and priv keys are equal"); + + CFReleaseNull(pubAttrs); + CFReleaseNull(privAttrs); + + delete_key(&pubKey); + delete_key(&privKey); +} + +#define kTestCount ((2 * kKeyGenTestCount) + kKeyGen2TestCount + (int) (kdfvLen*3)) + \ + kTestSupportedCount + kCreateWithDataTestCount + (kCopyAttributesTestCount * 2) + (kCopyPublicKeyTestCount * 4) + \ + kSignAndVerifyTestCount + kNonExtractableTestCount + \ + kTestCountCopyPubKFromCert + +static void tests(void) +{ + /* Comment out lines below for testing generating all common key sizes, + disabled now for speed reasons. */ + //testkeygen(512); + //testkeygen(768); + testkeygen(1024); + testkeygen(2056); // Stranged sized for edge cases in padding. + //testkeygen(2048); + //testkeygen(4096); + + testkeygen2(1024); // lots of FAIL! + + testsupportedalgos(1024); + testcreatewithdata(1024); + testcopyattributes(1024, true); + testcopyattributes(1024, false); + testcopypublickey(1024, true, true); + testcopypublickey(1024, false, true); + testcopypublickey(1024, true, false); + testcopypublickey(1024, false, false); + testsignverify(1024); + testnonextractable(1024); + +#if !TARGET_OS_IPHONE + testkeyderivation(); +#endif + + testcopypubkfromcert(); +} + +int kc_40_seckey(int argc, char *const *argv) +{ + plan_tests(kTestCount); + + tests(); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-41-sececkey.c b/OSX/libsecurity_keychain/regressions/kc-41-sececkey.m similarity index 83% rename from OSX/libsecurity_keychain/regressions/kc-41-sececkey.c rename to OSX/libsecurity_keychain/regressions/kc-41-sececkey.m index d51554ae..c82f0a6d 100644 --- a/OSX/libsecurity_keychain/regressions/kc-41-sececkey.c +++ b/OSX/libsecurity_keychain/regressions/kc-41-sececkey.m @@ -29,10 +29,20 @@ * Copyright (c) 2007-2009,2013-2014 Apple Inc. All Rights Reserved. * */ + +/* + * This is to fool os services to not provide the Keychain manager + * interface that doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 +#import + #include #include #include #include +#include #include #include @@ -56,6 +66,7 @@ #include "keychain_regressions.h" #include "utilities/SecCFRelease.h" +#include "utilities/array_size.h" #if TARGET_OS_IPHONE @@ -486,6 +497,97 @@ static void testsignformat(void) CFReleaseNull(KeyArrayPriv); } +#if !TARGET_OS_IPHONE +static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right) +{ + if (left == NULL || right == NULL) + return left == right; + else + return CFEqual(left, right); +} +#endif + +static void testkeyexchange(unsigned long keySizeInBits) +{ + size_t keySizeInBytes = (keySizeInBits + 7) / 8; + OSStatus status; + + SecKeyRef pubKey1 = NULL, privKey1 = NULL; + NSDictionary *kgp1 = @{ + (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC, + (id)kSecAttrKeySizeInBits: @(keySizeInBits), + (id)kSecAttrIsPermanent: @NO, + (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange", + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp1, &pubKey1, &privKey1), + "Generate %ld bit (%ld byte) EC keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + + SecKeyRef pubKey2 = NULL, privKey2 = NULL; + NSDictionary *kgp2 = @{ + (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC, + (id)kSecAttrKeySizeInBits: @(keySizeInBits), + (id)kSecAttrIsPermanent: @NO, + (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange", + (id)kSecAttrNoLegacy: @NO, + }; + ok_status(status = SecKeyGeneratePair((CFDictionaryRef)kgp2, &pubKey2, &privKey2), + "Generate %ld bit (%ld byte) EC keypair (status = %d)", + keySizeInBits, keySizeInBytes, (int)status); + + const SecKeyAlgorithm algos[] = { + kSecKeyAlgorithmECDHKeyExchangeStandard, + kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1, + kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA224, + kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256, + kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA384, + kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA512, + kSecKeyAlgorithmECDHKeyExchangeCofactor, + kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA1, + kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA224, + kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA256, + kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA384, + kSecKeyAlgorithmECDHKeyExchangeCofactorX963SHA512, + }; + + // Strange size to test borderline conditions. + const CFIndex requestedSize = 273; + NSDictionary *params = @{ + (id)kSecKeyKeyExchangeParameterRequestedSize: @(requestedSize), + (id)kSecKeyKeyExchangeParameterSharedInfo: [NSData dataWithBytes:"shared" length:5], + }; + + for (size_t ix = 0; ix < array_size(algos); ++ix) { + CFErrorRef error = NULL; + + NSData *secret1 = (NSData *)SecKeyCopyKeyExchangeResult(privKey1, algos[ix], pubKey2, (CFDictionaryRef)params, &error); + ok(secret1 != NULL && CFGetTypeID(secret1) == CFDataGetTypeID()); + CFReleaseNull(error); + + NSData *secret2 = (NSData *)SecKeyCopyKeyExchangeResult(privKey2, algos[ix], pubKey1, (CFDictionaryRef)params, &error); + ok(secret2 != NULL && CFGetTypeID(secret2) == CFDataGetTypeID()); + CFReleaseNull(error); + + eq_cf(secret1, secret2, "results of key exchange are equal"); + if (algos[ix] != kSecKeyAlgorithmECDHKeyExchangeCofactor && algos[ix] != kSecKeyAlgorithmECDHKeyExchangeStandard) { + is(secret1.length, requestedSize, "generated response has expected length"); + } + + CFReleaseNull(secret1); + CFReleaseNull(secret2); + } + + CFReleaseNull(privKey1); + CFReleaseNull(pubKey1); + CFReleaseNull(privKey2); + CFReleaseNull(pubKey2); + + SecItemDelete((CFDictionaryRef)@{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:kc-41-sececkey:testkeyexchange", + }); +} /* Test basic add delete update copy matching stuff. */ static void tests(void) @@ -508,15 +610,14 @@ static void tests(void) testkeygen2(384); testkeygen2(521); + testkeyexchange(256); + testkeyexchange(384); + testkeyexchange(521); } int kc_41_sececkey(int argc, char *const *argv) { -#if TARGET_OS_IPHONE - plan_tests(141); -#else - plan_tests(101); -#endif + plan_tests(245); tests(); diff --git a/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c b/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c index 77f288fb..522ee277 100644 --- a/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c +++ b/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Apple Inc. All Rights Reserved. + * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -29,6 +29,12 @@ #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" +// TBD: ensure that this symbol is defined in every build context. +// Currently forcing this to be enabled if we do not have it defined. +#ifndef SECTRUST_OSX +#define SECTRUST_OSX 1 +#endif + /* s:/jurisdictionC=US/jurisdictionST=Delaware/businessCategory=Private Organization/serialNumber=3014267/C=US/postalCode=95131-2021/ST=California/L=San Jose/street=2211 N 1st St/O=PayPal, Inc./OU=CDN Support/CN=www.paypal.com */ /* i:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 EV SSL CA - G3 */ /* SHA1 Fingerprint=A5:AF:1D:73:96:A7:74:F8:8B:B7:43:FD:07:7A:97:47:D3:FA:EF:2F */ @@ -513,21 +519,20 @@ static void tests(void) /* * 1) Test explicit revocation with no OCSP/CRL - * Side note: cache is stored in /var/db/crls/ocspcache.db crlcache.db etc... */ OSStatus status; - SecPolicyRef policy_default = SecPolicyCreateBasicX509(); - SecPolicyRef policy_revoc = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); + SecPolicyRef policy_ssl_default = SecPolicyCreateSSL(true, CFSTR("www.paypal.com")); + SecPolicyRef policy_revoc_disabled = SecPolicyCreateRevocation(kSecRevocationNetworkAccessDisabled); // Default Policies - CFMutableArrayRef DefaultPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(DefaultPolicy, policy_default); + CFMutableArrayRef DefaultSSLPolicy = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(DefaultSSLPolicy, policy_ssl_default); - // Default Policies + explicit revocation - CFMutableArrayRef DefaultPolicyWithRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(DefaultPolicyWithRevocation, policy_default); - CFArrayAppendValue(DefaultPolicyWithRevocation, policy_revoc); + // Default Policies + explicit revocation disabled + CFMutableArrayRef DefaultSSLPolicyWithNoRevocation = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(DefaultSSLPolicyWithNoRevocation, policy_ssl_default); + CFArrayAppendValue(DefaultSSLPolicyWithNoRevocation, policy_revoc_disabled); // Valid chain of Cert (leaf + CA) CFMutableArrayRef CertFullChain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -541,8 +546,8 @@ static void tests(void) // Free Resources since all are in arrays CFReleaseSafe(leaf_cert); CFReleaseSafe(CA_cert); - CFReleaseSafe(policy_default); - CFReleaseSafe(policy_revoc); + CFReleaseSafe(policy_ssl_default); + CFReleaseSafe(policy_revoc_disabled); // a) First evaluate an entire EV certificate chain with default policy // OCSP/CRL performed (online/from cache) @@ -553,7 +558,7 @@ static void tests(void) SecTrustResultType trust_result; // Proceed to trust evaluation in two steps - ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultPolicy, &trust), + ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultSSLPolicy, &trust), "SecTrustCreateWithCertificates"); ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); @@ -568,7 +573,7 @@ static void tests(void) CFReleaseNull(trust); } - // b) Set explicit revocation policy to disable network access + // b) Set explicit revocation policy to disable revocation checking, // and now expect EV marker to be dropped. // Network packet logging can be used to confirm no OCSP/CRL message is sent. { @@ -576,7 +581,7 @@ static void tests(void) SecTrustResultType trust_result; // Proceed to trust evaluation in two steps - ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultPolicyWithRevocation, &trust), + ok_status(status = SecTrustCreateWithCertificates(CertFullChain, DefaultSSLPolicyWithNoRevocation, &trust), "SecTrustCreateWithCertificates"); ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); @@ -585,7 +590,16 @@ static void tests(void) CFDictionaryRef TrustResultsDict = SecTrustCopyResult(trust); CFBooleanRef ev = (CFBooleanRef)CFDictionaryGetValue(TrustResultsDict, kSecTrustExtendedValidation); +#if SECTRUST_OSX + // With SecTrust Unification, the OCSP response is cached by the previous evaluation. + // FIXME The semantics of the input to SecPolicyCreateRevocation are technically not honored, + // since if neither the OCSP or CRL bits are set, we should not be using either. Unfortunately, + // the iOS implementation treats this as a no-op, which for EV certs means an OCSP check by default. + + ok(ev && CFEqual(kCFBooleanTrue, ev), "Expect success even if unable to use network, due to caching"); +#else ok(!ev || (ev && CFEqual(kCFBooleanFalse, ev)), "Expect no extended validation because of lack of revocation"); +#endif CFReleaseNull(TrustResultsDict); CFReleaseNull(trust); @@ -601,7 +615,7 @@ static void tests(void) SecTrustResultType trust_result; // Proceed to trust evaluation in two steps - ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultPolicy, &trust), + ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultSSLPolicy, &trust), "SecTrustCreateWithCertificates"); ok_status(status = SecTrustSetNetworkFetchAllowed(trust,true), "SecTrustSetNetworkFetchAllowed"); ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); @@ -624,13 +638,21 @@ static void tests(void) SecTrustResultType trust_result; // Proceed to trust evaluation in two steps, forcing no network allowed - ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultPolicy, &trust), + ok_status(status = SecTrustCreateWithCertificates(CertMissingIssuer, DefaultSSLPolicy, &trust), "SecTrustCreateWithCertificates"); ok_status(status = SecTrustSetNetworkFetchAllowed(trust,false), "SecTrustSetNetworkFetchAllowed"); ok_status(status = SecTrustEvaluate(trust, &trust_result), "SecTrustEvaluate"); // Check results - is_status(trust_result, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultProceed"); +#if SECTRUST_OSX + // with SecTrust Unification, the issuing cert may or may not be cached from the previous test + if (trust_result == kSecTrustResultUnspecified) + trust_result = kSecTrustResultRecoverableTrustFailure; + is_status(trust_result, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); +#else + // previously, no automatic caching of intermediates fetched from the network + is_status(trust_result, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); +#endif CFReleaseNull(trust); } @@ -722,8 +744,8 @@ static void tests(void) } // Free remaining resources - CFReleaseSafe(DefaultPolicy); - CFReleaseSafe(DefaultPolicyWithRevocation); + CFReleaseSafe(DefaultSSLPolicy); + CFReleaseSafe(DefaultSSLPolicyWithNoRevocation); CFReleaseSafe(CertFullChain); CFReleaseSafe(CertMissingIssuer); diff --git a/OSX/libsecurity_keychain/regressions/kc-43-seckey-interop.m b/OSX/libsecurity_keychain/regressions/kc-43-seckey-interop.m new file mode 100644 index 00000000..88fbdb72 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-43-seckey-interop.m @@ -0,0 +1,603 @@ +/* + * Copyright (c) 2007-2009,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 "keychain_regressions.h" +#include "utilities/SecCFRelease.h" +#include "utilities/array_size.h" + +#if !TARGET_OS_IPHONE +static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right) +{ + if (left == NULL || right == NULL) + return left == right; + else + return CFEqual(left, right); +} +#endif + +static const int kTestGenerateNoLegacyCount = 11; +static void test_generate_nolegacy() { + NSDictionary *query, *params = @{ + (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, + (id)kSecAttrKeySizeInBits: @1024, + (id)kSecAttrNoLegacy: @YES, + (id)kSecAttrIsPermanent: @YES, + (id)kSecAttrLabel: @"sectests:generate-no-legacy", + }; + + SecKeyRef pubKey = NULL, privKey = NULL, key = NULL; + ok_status(SecKeyGeneratePair((__bridge CFDictionaryRef)params, &pubKey, &privKey)); + + query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:generate-no-legacy", + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic, + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnRef: @YES, + }; + ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key)); + eq_cf(key, pubKey); + CFReleaseNull(key); + + query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:generate-no-legacy", + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate, + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnRef: @YES, + }; + ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key)); + eq_cf(key, privKey); + CFReleaseNull(key); + + query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:generate-no-legacy", + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic, + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnRef: @YES, + }; + ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key)); + eq_cf(key, pubKey); + CFReleaseNull(key); + + query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:generate-no-legacy", + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate, + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnRef: @YES, + }; + ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key)); + eq_cf(key, privKey); + CFReleaseNull(key); + + query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:generate-no-legacy", + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemDelete((__bridge CFDictionaryRef)query)); + is_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); + + CFReleaseNull(privKey); + CFReleaseNull(pubKey); +} + +#if !RC_HIDE_J79 && !RC_HIDE_J80 +static const int kTestGenerateAccessControlCount = 4; +static void test_generate_access_control() { + SecAccessControlRef ac = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleAlways, + 0 /* | kSecAccessControlPrivateKeyUsage */, NULL); + NSDictionary *params = @{ + (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, + (id)kSecAttrKeySizeInBits: @1024, + (id)kSecAttrAccessControl: (id)ac, + (id)kSecAttrIsPermanent: @YES, + (id)kSecAttrLabel: @"sectests:generate-access-control", + }; + + SecKeyRef pubKey, privKey; + ok_status(SecKeyGeneratePair((__bridge CFDictionaryRef)params, &pubKey, &privKey)); + + NSDictionary *query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:generate-access-control", + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL)); + + ok_status(SecItemDelete((__bridge CFDictionaryRef)query)); + + is_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); + + CFReleaseSafe(ac); + CFReleaseSafe(privKey); + CFReleaseSafe(pubKey); +} +#else +static const int kTestGenerateAccessControlCount = 0; +#endif + +static const int kTestAddIOSKeyCount = 6; +static void test_add_ios_key() { + NSDictionary *params = @{ + (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, + (id)kSecAttrKeySizeInBits: @1024, + (id)kSecAttrNoLegacy: @YES, + (id)kSecAttrIsPermanent: @NO, + }; + + SecKeyRef pubKey, privKey; + ok_status(SecKeyGeneratePair((__bridge CFDictionaryRef)params, &pubKey, &privKey)); + + NSDictionary *attrs = @{ + (id)kSecValueRef: (id)privKey, + (id)kSecAttrLabel: @"sectests:add-ios-key", + }; + ok_status(SecItemAdd((__bridge CFDictionaryRef)attrs, NULL)); + + NSDictionary *query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:add-ios-key", + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnRef: @YES, + }; + SecKeyRef key = NULL; + ok_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&key)); + eq_cf(key, privKey); + CFReleaseNull(key); + + query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: @"sectests:add-ios-key", + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemDelete((__bridge CFDictionaryRef)query)); + is_status(SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL), errSecItemNotFound); + + CFReleaseNull(pubKey); + CFReleaseNull(privKey); +} + +static const char *certDataBase64 = "\ +MIIEQjCCAyqgAwIBAgIJAJdFadWqNIfiMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAkNaMQ8wDQYD\ +VQQHEwZQcmFndWUxFTATBgNVBAoTDENvc21vcywgSW5jLjEXMBUGA1UEAxMOc3VuLmNvc21vcy5nb2Qx\ +IzAhBgkqhkiG9w0BCQEWFHRoaW5nQHN1bi5jb3Ntb3MuZ29kMB4XDTE2MDIyNjE0NTQ0OVoXDTE4MTEy\ +MjE0NTQ0OVowczELMAkGA1UEBhMCQ1oxDzANBgNVBAcTBlByYWd1ZTEVMBMGA1UEChMMQ29zbW9zLCBJ\ +bmMuMRcwFQYDVQQDEw5zdW4uY29zbW9zLmdvZDEjMCEGCSqGSIb3DQEJARYUdGhpbmdAc3VuLmNvc21v\ +cy5nb2QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5u9gnYEDzQIVu7yC40VcXTZ01D9CJ\ +oD/mH62tebEHEdfVPLWKeq+uAHnJ6fTIJQvksaISOxwiOosFjtI30mbe6LZ/oK22wYX+OUwKhAYjZQPy\ +RYfuaJe/52F0zmfUSJ+KTbUZrXbVVFma4xPfpg4bptvtGkFJWnufvEEHimOGmO5O69lXA0Hit1yLU0/A\ +MQrIMmZT8gb8LMZGPZearT90KhCbTHAxjcBfswZYeL8q3xuEVHXC7EMs6mq8IgZL7mzSBmrCfmBAIO0V\ +jW2kvmy0NFxkjIeHUShtYb11oYYyfHuz+1vr1y6FIoLmDejKVnwfcuNb545m26o+z/m9Lv9bAgMBAAGj\ +gdgwgdUwHQYDVR0OBBYEFGDdpPELS92xT+Hkh/7lcc+4G56VMIGlBgNVHSMEgZ0wgZqAFGDdpPELS92x\ +T+Hkh/7lcc+4G56VoXekdTBzMQswCQYDVQQGEwJDWjEPMA0GA1UEBxMGUHJhZ3VlMRUwEwYDVQQKEwxD\ +b3Ntb3MsIEluYy4xFzAVBgNVBAMTDnN1bi5jb3Ntb3MuZ29kMSMwIQYJKoZIhvcNAQkBFhR0aGluZ0Bz\ +dW4uY29zbW9zLmdvZIIJAJdFadWqNIfiMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAFYi\ +Zu/dfAMOrD51bYxP88Wu6iDGBe9nMG/0lkKgnX5JQKCxfxFMk875rfa+pljdUMOaPxegOXq1DrYmQB9O\ +/pHI+t7ozuWHRj2zKkVgMWAygNWDPcoqBEus53BdAgA644aPN2JvnE4NEPCllOMKftPoIWbd/5ZjCx3a\ +bCuxBdXq5YSmiEnOdGfKeXjeeEiIDgARb4tLgH5rkOpB1uH/ZCWn1hkiajBhrGhhPhpA0zbkZg2Ug+8g\ +XPlx1yQB1VOJkj2Z8dUEXCaRRijInCJ2eU+pgJvwLV7mxmSED7DEJ+b+opxJKYrsdKBU6RmYpPrDa+KC\ +/Yfu88P9hKKj0LmBiREA\ +"; + +static const char *keyDataBase64 = "\ +MIIEogIBAAKCAQEAubvYJ2BA80CFbu8guNFXF02dNQ/QiaA/5h+trXmxBxHX1Ty1inqvrgB5yen0yCUL\ +5LGiEjscIjqLBY7SN9Jm3ui2f6CttsGF/jlMCoQGI2UD8kWH7miXv+dhdM5n1Eifik21Ga121VRZmuMT\ +36YOG6bb7RpBSVp7n7xBB4pjhpjuTuvZVwNB4rdci1NPwDEKyDJmU/IG/CzGRj2Xmq0/dCoQm0xwMY3A\ +X7MGWHi/Kt8bhFR1wuxDLOpqvCIGS+5s0gZqwn5gQCDtFY1tpL5stDRcZIyHh1EobWG9daGGMnx7s/tb\ +69cuhSKC5g3oylZ8H3LjW+eOZtuqPs/5vS7/WwIDAQABAoIBAGcwmQAPdyZus3OVwa1NCUD2KyB+39KG\ +yNmWwgx+br9Jx4s+RnJghVh8BS4MIKZOBtSRaEUOuCvAMNrupZbD+8leq34vDDRcQpCizr+M6Egj6FRj\ +Ewl+7Mh+yeN2hbMoghL552MTv9D4Iyxteu4nuPDd/JQ3oQwbDFIL6mlBFtiBDUr9ndemmcJ0WKuzor6a\ +3rgsygLs8SPyMefwIKjh5rJZls+iv3AyVEoBdCbHBz0HKgLVE9ZNmY/gWqda2dzAcJxxMdafeNVwHovv\ +BtyyRGnA7Yikx2XT4WLgKfuUsYLnDWs4GdAa738uxPBfiddQNeRjN7jRT1GZIWCk0P29rMECgYEA8jWi\ +g1Dph+4VlESPOffTEt1aCYQQWtHs13Qex95HrXX/L49fs6cOE7pvBh7nVzaKwBnPRh5+3bCPsPmRVb7h\ +k/GreOriCjTZtyt2XGp8eIfstfirofB7c1lNBjT61BhgjJ8Moii5c2ksNIOOZnKtD53n47mf7hiarYkw\ +xFEgU6ECgYEAxE8Js3gIPOBjsSw47XHuvsjP880nZZx/oiQ4IeJb/0rkoDMVJjU69WQu1HTNNAnMg4/u\ +RXo31h+gDZOlE9t9vSXHdrn3at67KAVmoTbRknGxZ+8tYpRJpPj1hyufynBGcKwevv3eHJHnE5eDqbHx\ +ynZFkXemzT9aMy3R4CCFMXsCgYAYyZpnG/m6WohE0zthMFaeoJ6dSLGvyboWVqDrzXjCbMf/4wllRlxv\ +cm34T2NXjpJmlH2c7HQJVg9uiivwfYdyb5If3tHhP4VkdIM5dABnCWoVOWy/NvA7XtE+KF/fItuGqKRP\ +WCGaiRHoEeqZ23SQm5VmvdF7OXNi/R5LiQ3o4QKBgAGX8qg2TTrRR33ksgGbbyi1UJrWC3/TqWWTjbEY\ +uU51OS3jvEQ3ImdjjM3EtPW7LqHSxUhjGZjvYMk7bZefrIGgkOHx2IRRkotcn9ynKURbD+mcE249beuc\ +6cFTJVTrXGcFvqomPWtV895A2JzECQZvt1ja88uuu/i2YoHDQdGJAoGAL2TEgiMXiunb6PzYMMKKa+mx\ +mFnagF0Ek3UJ9ByXKoLz3HFEl7cADIkqyenXFsAER/ifMyCoZp/PDBd6ZkpqLTdH0jQ2Yo4SllLykoiZ\ +fBWMfjRu4iw9E0MbPB3blmtzfv53BtWKy0LUOlN4juvpqryA7TgaUlZkfMT+T1TC7xU=\ +"; + +static const int kTestStoreCertToIOS = 5; +static void test_store_cert_to_ios() { + // Create certificate instance. + NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData); + ok(cert != NULL, "create certificate from data"); + + // Store certificate to modern keychain. + NSDictionary *attrs = @{ + (id)kSecValueRef: (id)cert, + (id)kSecAttrLabel: @"sectests:store_cert_to_ios", + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnPersistentRef: @YES, + }; + id persistentRef; + ok_status(SecItemAdd((CFDictionaryRef)attrs, (void *)&persistentRef), "store certificate into iOS keychain"); + + // Query certificate, without specification of the keychain. + NSDictionary *query = @{ + (id)kSecClass: (id)kSecClassCertificate, + (id)kSecAttrLabel: @"sectests:store_cert_to_ios", + (id)kSecReturnRef: @YES, + }; + SecCertificateRef queriedCert = NULL; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (void *)&queriedCert), "query certificate back"); + eq_cf(cert, queriedCert, "stored and retrieved certificates are the same"); + + ok_status(SecItemDelete((CFDictionaryRef)@{ (id)kSecValuePersistentRef: persistentRef }), + "delete certificate from keychain"); + CFReleaseNull(cert); +} + +static const int kTestStoreIdentityToIOS = 6; +static void test_store_identity_to_ios() { + // Create certificate instance. + NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + SecCertificateRef certificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData); + ok(certificate != NULL, "create certificate from data"); + + // Create private key instance. + NSData *keyData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:keyDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + NSDictionary *keyAttrs = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048, + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate }; + SecKeyRef privateKey = SecKeyCreateWithData((CFDataRef)keyData, (CFDictionaryRef)keyAttrs, NULL); + ok(privateKey != NULL, "create private key from data"); + + // Create identity from certificate and private key. + SecIdentityRef identity = SecIdentityCreate(kCFAllocatorDefault, certificate, privateKey); + + // Store identity to the iOS keychain. + NSDictionary *attrs = @{ + (id)kSecValueRef: (id)identity, + (id)kSecAttrLabel: @"sectests:store_identity_to_ios", + (id)kSecAttrNoLegacy: @YES, + (id)kSecReturnPersistentRef: @YES, + }; + id persistentRef; + ok_status(SecItemAdd((CFDictionaryRef)attrs, (void *)&persistentRef), "store identity into iOS keychain"); + + NSDictionary *query = @{ + (id)kSecClass: (id)kSecClassIdentity, + (id)kSecAttrLabel: @"sectests:store_identity_to_ios", + (id)kSecReturnRef: @YES, + }; + SecIdentityRef queriedIdentity = NULL; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (void *)&queriedIdentity), "query identity from keychain"); + eq_cf(identity, queriedIdentity, "stored and retrieved identities are identical"); + + // Cleanup identity. + ok_status(SecItemDelete((CFDictionaryRef)@{ (id)kSecValuePersistentRef: persistentRef}), + "delete identity from iOS keychain"); + + CFReleaseNull(identity); + CFReleaseNull(privateKey); + CFReleaseNull(certificate); +} + +static const int kTestTransformWithIOSKey = 9; +static void test_transform_with_ioskey() { + // Create private key instance. + NSData *keyData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:keyDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + NSDictionary *keyAttrs = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits: @2048, + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate }; + SecKeyRef privateKey = SecKeyCreateWithData((CFDataRef)keyData, (CFDictionaryRef)keyAttrs, NULL); + ok(privateKey != NULL, "create private key from data"); + + // Create signature transform with private key + NSData *testData = [NSData dataWithBytes:"test" length:4]; + SecTransformRef signer = SecSignTransformCreate(privateKey, NULL); + ok(signer != NULL, "create signing transform"); + ok(SecTransformSetAttribute(signer, kSecTransformInputAttributeName, (CFDataRef)testData, NULL), + "set input data to verify transform"); + NSData *signature = (NSData *)SecTransformExecute(signer, NULL); + ok(signature != nil, "create signature with transform"); + + // Create verify transform with public key. + SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey); + ok(publicKey != NULL, "get public key from private key"); + SecTransformRef verifier = SecVerifyTransformCreate(publicKey, (CFDataRef)signature, NULL); + ok(verifier, "create verification transform"); + ok(SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, (CFDataRef)testData, NULL), + "set input data to verify transform"); + + NSNumber *result = (NSNumber *)SecTransformExecute(verifier, NULL); + ok(result != nil, "transform execution succeeded"); + ok(result.boolValue, "transform verified signature"); + + CFReleaseNull(signer); + CFReleaseNull(verifier); + CFReleaseNull(publicKey); + CFReleaseNull(privateKey); +} + +static const int kTestConvertKeyToPersistentRef = 11; +static void test_convert_key_to_persistent_ref() { + NSString *label = @"sectests:convert-key-to-persistent-ref"; + + // Create + SecKeyRef privKey = NULL; + { + NSDictionary *query = @{ + (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, + (id)kSecAttrKeySizeInBits: @1024, + (id)kSecAttrNoLegacy: @YES, + (id)kSecAttrIsPermanent: @NO, + }; + SecKeyRef pubKey = NULL; + ok_status(SecKeyGeneratePair((CFDictionaryRef)query, &pubKey, &privKey)); + CFReleaseNull(pubKey); + } + + // Store + { + NSDictionary *query = @{ + (id)kSecAttrLabel: label, + (id)kSecValueRef: (id)privKey, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemAdd((CFDictionaryRef)query, NULL)); + } + + // Convert & Compare + CFDataRef queriedPersistentKeyRef = NULL; + SecKeyRef queriedKeyRef = NULL; + { + NSDictionary *query = @{ + (id)kSecValueRef: (id)privKey, + (id)kSecReturnPersistentRef: @YES, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedPersistentKeyRef)); + }{ + NSDictionary *query = @{ + (id)kSecValuePersistentRef: (id)queriedPersistentKeyRef, + (id)kSecReturnRef: @YES, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedKeyRef)); + }{ + CFDataRef persistentKeyRef = NULL; + SecKeychainItemRef keyRef = NULL; + ok_status(SecKeychainItemCreatePersistentReference((SecKeychainItemRef)privKey, &persistentKeyRef)); + ok_status(SecKeychainItemCopyFromPersistentReference(persistentKeyRef, &keyRef)); + eq_cf(privKey, queriedKeyRef); + eq_cf(keyRef, privKey); + eq_cf(persistentKeyRef, queriedPersistentKeyRef); + CFReleaseNull(persistentKeyRef); + CFReleaseNull(keyRef); + } + CFReleaseNull(queriedPersistentKeyRef); + CFReleaseNull(queriedKeyRef); + + // Cleanup + CFReleaseNull(privKey); + { + NSDictionary *query = @{ + (id)kSecClass: (id)kSecClassKey, + (id)kSecAttrLabel: label, + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + }; + ok_status(SecItemDelete((CFDictionaryRef)query)); + is_status(SecItemCopyMatching((CFDictionaryRef)query, NULL), errSecItemNotFound); + } +} + +static const int kTestConvertCertToPersistentRef = 11; +static void test_convert_cert_to_persistent_ref() { + NSString *label = @"sectests:convert-cert-to-persistent-ref"; + + // Create + SecCertificateRef cert = NULL; + { + NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData); + ok(cert); + } + + // Store + { + NSDictionary *query = @{ + (id)kSecAttrLabel: label, + (id)kSecValueRef: (id)cert, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemAdd((CFDictionaryRef)query, NULL)); + } + + // Convert & Compare + CFDataRef queriedPersistentCertRef = NULL; + SecCertificateRef queriedCertRef = NULL; + { + NSDictionary *query = @{ + (id)kSecValueRef: (id)cert, + (id)kSecReturnPersistentRef: @YES, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedPersistentCertRef)); + }{ + NSDictionary *query = @{ + (id)kSecValuePersistentRef: (id)queriedPersistentCertRef, + (id)kSecReturnRef: @YES, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedCertRef)); + }{ + CFDataRef persistentCertRef = NULL; + SecKeychainItemRef certRef = NULL; + ok_status(SecKeychainItemCreatePersistentReference((SecKeychainItemRef)cert, &persistentCertRef)); + ok_status(SecKeychainItemCopyFromPersistentReference(persistentCertRef, &certRef)); + eq_cf(cert, queriedCertRef); + eq_cf(certRef, cert); + eq_cf(persistentCertRef, queriedPersistentCertRef); + CFReleaseNull(persistentCertRef); + CFReleaseNull(certRef); + } + CFReleaseNull(queriedPersistentCertRef); + CFReleaseNull(queriedCertRef); + + // Cleanup + CFReleaseNull(cert); + { + NSDictionary *query = @{ + (id)kSecClass: (id)kSecClassCertificate, + (id)kSecAttrLabel: label, + (id)kSecMatchLimit: (id)kSecMatchLimitAll, + }; + ok_status(SecItemDelete((CFDictionaryRef)query)); + is_status(SecItemCopyMatching((CFDictionaryRef)query, NULL), errSecItemNotFound); + } +} + +static const int kTestConvertIdentityToPersistentRef = 12; +static void test_convert_identity_to_persistent_ref() { + NSString *label = @"sectests:convert-identity-to-persistent-ref"; + + // Create + SecIdentityRef idnt = NULL; + { + NSData *certData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:certDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certData); + ok(cert); + NSData *keyData = [[NSData alloc] initWithBase64EncodedString:[NSString stringWithUTF8String:keyDataBase64] + options:NSDataBase64DecodingIgnoreUnknownCharacters]; + NSDictionary *keyAttrs = @{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, + (id)kSecAttrKeySizeInBits: @2048, + (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate }; + SecKeyRef privKey = SecKeyCreateWithData((CFDataRef)keyData, (CFDictionaryRef)keyAttrs, NULL); + ok(privKey); + idnt = SecIdentityCreate(kCFAllocatorDefault, cert, privKey); + CFReleaseNull(cert); + CFReleaseNull(privKey); + } + + // Store + { + NSDictionary *query = @{ + (id)kSecAttrLabel: label, + (id)kSecValueRef: (id)idnt, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemAdd((CFDictionaryRef)query, NULL)); + } + + // Convert & Compare + CFDataRef queriedPersistentIdntRef = NULL; + SecIdentityRef queriedIdntRef = NULL; + { + NSDictionary *query = @{ + (id)kSecValueRef: (id)idnt, + (id)kSecReturnPersistentRef: @YES, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedPersistentIdntRef)); + }{ + NSDictionary *query = @{ + (id)kSecValuePersistentRef: (id)queriedPersistentIdntRef, + (id)kSecReturnRef: @YES, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&queriedIdntRef)); + }{ + CFDataRef persistentIdntRef = NULL; + SecKeychainItemRef idntRef = NULL; + ok_status(SecKeychainItemCreatePersistentReference((SecKeychainItemRef)idnt, &persistentIdntRef)); + ok_status(SecKeychainItemCopyFromPersistentReference(persistentIdntRef, &idntRef)); + eq_cf(idnt, queriedIdntRef); + eq_cf(idntRef, idnt); + eq_cf(persistentIdntRef, queriedPersistentIdntRef); + CFReleaseNull(persistentIdntRef); + CFReleaseNull(idntRef); + } + CFReleaseNull(queriedPersistentIdntRef); + CFReleaseNull(queriedIdntRef); + + // Cleanup + { + NSDictionary *query = @{ + // identities can't be filtered out using 'label', so we will use directly the ValueRef here: + (id)kSecValueRef: (id)idnt, + (id)kSecAttrNoLegacy: @YES, + }; + ok_status(SecItemDelete((CFDictionaryRef)query)); + is_status(SecItemCopyMatching((CFDictionaryRef)query, NULL), errSecItemNotFound); + } + CFReleaseNull(idnt); +} + +static const int kTestCount = + kTestGenerateNoLegacyCount + + kTestGenerateAccessControlCount + + kTestAddIOSKeyCount + + kTestStoreCertToIOS + + kTestStoreIdentityToIOS + + kTestTransformWithIOSKey + + kTestConvertKeyToPersistentRef + + kTestConvertCertToPersistentRef + + kTestConvertIdentityToPersistentRef; + +int kc_43_seckey_interop(int argc, char *const *argv) { + plan_tests(kTestCount); + + test_generate_nolegacy(); +#if !RC_HIDE_J79 && !RC_HIDE_J80 + test_generate_access_control(); +#endif + test_add_ios_key(); + test_store_cert_to_ios(); + test_store_identity_to_ios(); + test_transform_with_ioskey(); + test_convert_key_to_persistent_ref(); + test_convert_cert_to_persistent_ref(); + test_convert_identity_to_persistent_ref(); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-helpers.h b/OSX/libsecurity_keychain/regressions/kc-helpers.h new file mode 100644 index 00000000..f5402b3e --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-helpers.h @@ -0,0 +1,253 @@ +/* + * 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@ + */ + +#ifndef kc_helpers_h +#define kc_helpers_h + +#include +#include + +#include +#include +#include "utilities/SecCFRelease.h" + +#include "kc-keychain-file-helpers.h" + +/* redefine this since the headers are mixed up */ +static inline bool CFEqualSafe(CFTypeRef left, CFTypeRef right) +{ + if (left == NULL || right == NULL) + return left == right; + else + return CFEqual(left, right); +} + +static char keychainFile[1000]; +static char keychainDbFile[1000]; +static char keychainTempFile[1000]; +static char keychainName[1000]; +static char testName[1000]; +static uint32_t promptAttempts; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +static void startTest(const char* thisTestName) { + strlcpy(testName, thisTestName, sizeof(testName)); +} + +static void initializeKeychainTests(const char* thisTestName) { + const char *home_dir = getenv("HOME"); + sprintf(keychainName, "test-%s.asdf", thisTestName); + sprintf(keychainFile, "%s/Library/Keychains/%s", home_dir, keychainName); + sprintf(keychainDbFile, "%s/Library/Keychains/%s-db", home_dir, keychainName); + sprintf(keychainTempFile, "%s/Library/Keychains/test_temp", home_dir); + + deleteKeychainFiles(keychainFile); + + startTest(thisTestName); + + SecKeychainGetUserPromptAttempts(&promptAttempts); + SecKeychainSetUserInteractionAllowed(FALSE); +} + +// Use this at the bottom of every test to make sure everything is gone +static void deleteTestFiles() { + deleteKeychainFiles(keychainFile); +} + +static SecKeychainRef getPopulatedTestKeychain() { + deleteKeychainFiles(keychainFile); + + writeFile(keychainFile, test_keychain, sizeof(test_keychain)); + + SecKeychainRef kc = NULL; + ok_status(SecKeychainOpen(keychainFile, &kc), "%s: getPopulatedTestKeychain: SecKeychainOpen", testName); + ok_status(SecKeychainUnlock(kc, (UInt32) strlen(test_keychain_password), test_keychain_password, true), "%s: getPopulatedTestKeychain: SecKeychainUnlock", testName); + return kc; +} +#define getPopulatedTestKeychainTests 2 + +static void addToSearchList(SecKeychainRef keychain) { + CFArrayRef searchList = NULL; + SecKeychainCopySearchList(&searchList); + CFMutableArrayRef mutableSearchList = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(searchList) + 1, searchList); + CFArrayAppendValue(mutableSearchList, keychain); + SecKeychainSetSearchList(mutableSearchList); + CFRelease(searchList); + CFRelease(mutableSearchList); +} + + +/* Checks to be sure there are N elements in this search, and returns the first + * if it exists. */ +static SecKeychainItemRef checkN(char* testName, const CFDictionaryRef query, uint32_t n) { + CFArrayRef results = NULL; + if(n > 0) { + ok_status(SecItemCopyMatching(query, (CFTypeRef*) &results), "%s: SecItemCopyMatching", testName); + } else { + is(SecItemCopyMatching(query, (CFTypeRef*) &results), errSecItemNotFound, "%s: SecItemCopyMatching (for no items)", testName); + } + + SecKeychainItemRef item = NULL; + if(results) { + is(CFArrayGetCount(results), n, "%s: Wrong number of results", testName); + if(n >= 1) { + ok(item = (SecKeychainItemRef) CFArrayGetValueAtIndex(results, 0), "%s: Couldn't get item", testName); + } else { + pass("make test numbers match"); + } + } else if((!results) && n == 0) { + pass("%s: no results found (and none expected)", testName); + pass("make test numbers match"); + } else { + fail("%s: no results found (and %d expected)", testName, n); + fflush(stdout); CFShow(query); fflush(stdout); + pass("make test numbers match"); + } + + CFRelease(query); + return item; +} +#define checkNTests 3 + + +static void readPasswordContentsWithResult(SecKeychainItemRef item, OSStatus expectedResult, CFStringRef expectedContents) { + if(!item) { + fail("no item passed to readPasswordContentsWithResult"); + fail("Match test numbers"); + fail("Match test numbers"); + return; + } + + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); + + CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)itemList, item); + CFDictionarySetValue(query, kSecUseItemList, itemList); + + CFTypeRef results = NULL; + if(expectedContents) { + is(SecItemCopyMatching(query, (CFTypeRef*) &results), expectedResult, "%s: readPasswordContents: SecItemCopyMatching", testName); + CFReleaseNull(query); + + if(results) { + ok(CFGetTypeID(results) == CFDataGetTypeID(), "%s: result is not a data", testName); + + CFDataRef data = (CFDataRef) results; + CFStringRef str = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, false); + eq_cf(str, expectedContents, "%s: contents do not match", testName); + CFReleaseNull(str); + CFReleaseNull(results); + } else { + fail("Didn't get any results"); + fail("Match test numbers"); + } + } else { + is(SecItemCopyMatching(query, (CFTypeRef*) &results), expectedResult, "%s: readPasswordContents: expecting error %d", testName, (int) expectedResult); + pass("Match test numbers"); + pass("Match test numbers"); + } +} +#define readPasswordContentsWithResultTests 3 + +static void readPasswordContents(SecKeychainItemRef item, CFStringRef expectedContents) { + return readPasswordContentsWithResult(item, errSecSuccess, expectedContents); +} +#define readPasswordContentsTests readPasswordContentsWithResultTests + +static void changePasswordContents(SecKeychainItemRef item, CFStringRef newPassword) { + if(!item) { + fail("no item passed to changePasswordContents"); + return; + } + + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + + CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)itemList, item); + CFDictionarySetValue(query, kSecUseItemList, itemList); + + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(attrs, kSecValueData, CFDataCreate(NULL, (const UInt8*) CFStringGetCStringPtr(newPassword, kCFStringEncodingUTF8), CFStringGetLength(newPassword))); + + ok_status(SecItemUpdate(query, attrs), "%s: SecItemUpdate", testName); +} +#define changePasswordContentsTests 1 + +static void deleteItem(SecKeychainItemRef item) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)itemList, item); + CFDictionarySetValue(query, kSecUseItemList, itemList); + + ok_status(SecItemDelete(query), "%s: SecItemDelete single item", testName); + CFReleaseNull(query); +} +#define deleteItemTests 1 + +static void deleteItems(CFArrayRef items) { + if(!items) { + fail("no items passed to deleteItems"); + return; + } + + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(query, kSecUseItemList, items); + + size_t count = (size_t) CFArrayGetCount(items); + if(count > 0) { + ok_status(SecItemDelete(query), "%s: SecItemDelete %ld items", testName, count); + } else { + is(SecItemDelete(query), errSecItemNotFound, "%s: SecItemDelete no items", testName); + } + CFReleaseNull(query); +} +#define deleteItemsTests 1 + +/* Checks in with securityd to see how many prompts were generated since the last call to this function, and tests against the number expected. + Returns the number generated since the last call. */ +static uint32_t checkPrompts(uint32_t expectedSinceLastCall, char* explanation) { + uint32_t currentPrompts = UINT_MAX; + uint32_t newPrompts = UINT_MAX; + ok_status(SecKeychainGetUserPromptAttempts(¤tPrompts), "%s: SecKeychainGetUserPromptAttempts", testName); + + newPrompts = currentPrompts - promptAttempts; + + is(newPrompts, expectedSinceLastCall, "%s: wrong number of prompts: %s", testName, explanation); + promptAttempts = currentPrompts; + + return newPrompts; +} +#define checkPromptsTests 2 + +#pragma clang diagnostic pop + +#endif /* kc_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-identity-helpers.h b/OSX/libsecurity_keychain/regressions/kc-identity-helpers.h new file mode 100644 index 00000000..60c14cff --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-identity-helpers.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2015 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 "kc-helpers.h" +#include + +#ifndef kc_identity_helpers_h +#define kc_identity_helpers_h + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +static SecIdentityRef +copyFirstIdentity(SecKeychainRef kc) +{ + // Returns the first SecIdentityRef we can find. + // This should always succeed since we can fall back on the system identity. + // Caller must release the reference. + + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + /* set up the query */ + CFDictionaryAddValue( query, kSecClass, kSecClassIdentity ); + CFDictionaryAddValue( query, kSecMatchLimit, kSecMatchLimitAll ); + CFDictionaryAddValue( query, kSecReturnRef, kCFBooleanTrue ); + + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, kc); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + + CFTypeRef results = NULL; + OSStatus status = SecItemCopyMatching(query, &results); + ok_status(status, "%s: SecItemCopyMatching", testName); + CFRelease(query); + + if (status) { + return NULL; + } + if (results) { + CFArrayRef resultArray = (CFArrayRef)results; + SecIdentityRef identity = (SecIdentityRef)CFArrayGetValueAtIndex(resultArray, 0); + CFRetain(identity); // since we will return it + CFRelease(results); + return identity; + } + return NULL; +} +#define copyFirstIdentityTests 1 + +// findIdentity +// - returns a SecIdentityRef for the first identity in the given keychain +// which matches the provided certificate. +// +static SecIdentityRef +findIdentity(SecKeychainRef keychain, SecCertificateRef cert) +{ + OSStatus status = noErr; + SecIdentitySearchRef searchRef = NULL; + CSSM_DATA certData = { 0, NULL }; + + SecIdentityRef outIdentity = NULL; + + if (!keychain || !cert) { + return NULL; + } + + // note: we should be using CFEqual on certificate references instead of + // comparing the certificate data, but that is currently broken + status = SecCertificateGetData(cert, &certData); + ok_status(status, "%s: findIdentity: SecCertificateGetData", testName); + if (status) { + return NULL; + } + + status = SecIdentitySearchCreate(keychain, (CSSM_KEYUSE)0, &searchRef); + while (!status) { + SecIdentityRef identityRef = NULL; + status = SecIdentitySearchCopyNext(searchRef, &identityRef); + if (!status) { + SecCertificateRef aCert = NULL; + status = SecIdentityCopyCertificate(identityRef, &aCert); + if (!status) { + CSSM_DATA aCertData = { 0, NULL }; + status = SecCertificateGetData(aCert, &aCertData); + if (!status) { + if (aCertData.Length == certData.Length && + !memcmp(aCertData.Data, certData.Data, certData.Length)) { + // we found the identity + CFRelease(aCert); + outIdentity = identityRef; + break; + } + } + } + if (aCert) { + CFRelease(aCert); + } + } + if (identityRef) { + CFRelease(identityRef); + } + } + + ok(outIdentity, "%s: findIdentity: found an identity", testName); + + if (searchRef) { + CFRelease(searchRef); + } + + return outIdentity; +} +#define findIdentityTests 2 + +unsigned char test_import_p12[] = { + 0x30, 0x82, 0x09, 0xbf, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0x86, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x82, 0x09, 0x77, 0x04, 0x82, 0x09, 0x73, 0x30, 0x82, 0x09, 0x6f, 0x30, 0x82, 0x03, 0xff, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x03, 0xf0, 0x30, 0x82, 0x03, 0xec, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x03, 0xe5, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0xcb, 0xa2, 0x8c, 0x60, 0xc2, 0x36, 0x55, + 0x05, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x03, 0xb8, 0x57, 0x1d, 0x4c, 0x1f, 0xc7, 0x4c, 0x00, 0x82, 0xa3, 0xc9, 0x6f, + 0x2e, 0x00, 0x03, 0x1b, 0x55, 0xaa, 0xe5, 0x89, 0x58, 0x18, 0x71, 0xb8, 0xff, 0x40, 0x13, 0xd5, 0xac, 0x7f, 0xf1, 0x48, + 0xb2, 0x7e, 0x6e, 0xeb, 0x6e, 0xde, 0xe8, 0x35, 0x22, 0xa5, 0x45, 0x5a, 0xa6, 0x2e, 0xed, 0x0d, 0xe0, 0x8f, 0x2f, 0x60, + 0x5c, 0xd8, 0x49, 0x89, 0x26, 0x42, 0xd6, 0xe0, 0x24, 0x1c, 0x59, 0x9c, 0xe0, 0xbf, 0x98, 0x0c, 0xc3, 0x81, 0x20, 0x47, + 0x03, 0x03, 0xe2, 0x73, 0x90, 0x13, 0x6e, 0x96, 0x31, 0x68, 0xb7, 0x8f, 0xaa, 0x25, 0x4b, 0x27, 0x95, 0x3f, 0xef, 0xa3, + 0x2b, 0x96, 0x10, 0x85, 0xf3, 0x49, 0x3c, 0x6f, 0x9a, 0x20, 0x02, 0x17, 0x42, 0xe9, 0x9c, 0x5e, 0x5d, 0x4b, 0x3c, 0x88, + 0x65, 0xf5, 0x67, 0x61, 0x3e, 0xa6, 0x1a, 0x0f, 0x5b, 0x1e, 0x35, 0x18, 0x4e, 0xf3, 0x98, 0x93, 0x7e, 0x76, 0x77, 0x31, + 0x3b, 0x00, 0x78, 0x8c, 0x50, 0x28, 0x76, 0xca, 0xc8, 0x39, 0xc5, 0xf5, 0x79, 0x23, 0x4a, 0xea, 0x9a, 0xf0, 0xb5, 0xb6, + 0x50, 0x8d, 0x16, 0xd9, 0x39, 0x74, 0x36, 0x1d, 0x26, 0xcb, 0xbf, 0xb7, 0x72, 0x5e, 0x77, 0xf5, 0xb8, 0x35, 0xfc, 0x66, + 0x4d, 0xdc, 0xd6, 0x20, 0x50, 0x70, 0xc6, 0xf7, 0x13, 0x55, 0xb1, 0x97, 0x7e, 0x1d, 0x6a, 0x7d, 0x73, 0xc2, 0x71, 0x49, + 0xd1, 0x15, 0xe7, 0x30, 0xa7, 0x52, 0x1f, 0x24, 0xe8, 0x7b, 0xd7, 0x81, 0x53, 0x27, 0x94, 0xd0, 0x31, 0xe5, 0x11, 0xe4, + 0x90, 0x8a, 0x02, 0x46, 0x70, 0x82, 0xe7, 0xc4, 0xfe, 0xb5, 0xed, 0xb0, 0x1b, 0xcb, 0xa2, 0x23, 0x5c, 0xd2, 0x95, 0xe6, + 0x2c, 0x5f, 0x2d, 0x07, 0xb1, 0xd8, 0xe8, 0xa0, 0x39, 0xe7, 0xdd, 0x2e, 0x36, 0xac, 0x38, 0xfc, 0x65, 0x99, 0x2c, 0xda, + 0x3d, 0x26, 0x5d, 0x1e, 0x2f, 0xbc, 0x31, 0x36, 0x3e, 0x87, 0x55, 0x5f, 0x40, 0xf1, 0x77, 0x7a, 0x15, 0xa2, 0xc3, 0xe4, + 0x21, 0xc0, 0xe1, 0x11, 0x15, 0x31, 0xf4, 0x7a, 0x51, 0xc3, 0x78, 0x70, 0xfc, 0x3b, 0xed, 0x04, 0x7f, 0x5c, 0xaf, 0x22, + 0x37, 0x1c, 0x80, 0xb6, 0x7b, 0xdf, 0x11, 0x90, 0x52, 0xc1, 0x0d, 0xfb, 0xaa, 0xd0, 0x43, 0x47, 0xe9, 0xdb, 0x31, 0xb7, + 0xfc, 0x35, 0xbf, 0xce, 0x00, 0x15, 0x0d, 0x51, 0xb1, 0x78, 0x99, 0x55, 0x91, 0x1f, 0xf1, 0x4c, 0x36, 0xfa, 0xc1, 0xa0, + 0xce, 0x86, 0xc9, 0x79, 0x60, 0x07, 0x58, 0xa7, 0xe5, 0x28, 0x28, 0x84, 0x92, 0x03, 0x2c, 0x43, 0xda, 0x69, 0xce, 0x75, + 0x25, 0x01, 0x51, 0x37, 0xd4, 0xfd, 0xa2, 0xc4, 0x09, 0xfb, 0xa0, 0xf5, 0x1f, 0x23, 0x7b, 0xd6, 0x63, 0xd1, 0xb5, 0x5b, + 0xc5, 0xd9, 0xbc, 0xe7, 0xd4, 0x5e, 0x8b, 0x62, 0xee, 0xdb, 0xb7, 0x1e, 0xd2, 0x8b, 0x6e, 0xe4, 0x8c, 0xfd, 0x11, 0x25, + 0xda, 0xac, 0x2a, 0x7a, 0x9a, 0xad, 0x6c, 0x29, 0xe1, 0x1c, 0x68, 0x4f, 0xb3, 0x99, 0x06, 0xb4, 0x72, 0x2a, 0x5a, 0x70, + 0xd6, 0xf6, 0x7c, 0x22, 0x0f, 0x85, 0xf1, 0xc4, 0x30, 0x9f, 0x32, 0x53, 0xa1, 0xb2, 0x1a, 0x41, 0x01, 0xa2, 0x92, 0x58, + 0xa2, 0x27, 0xe8, 0x09, 0xed, 0x75, 0x84, 0x41, 0xcd, 0x19, 0x46, 0x47, 0x86, 0x7d, 0xa0, 0x49, 0xc4, 0x72, 0x94, 0x9f, + 0x43, 0xf2, 0x09, 0x3a, 0x59, 0x56, 0x7c, 0x3b, 0x34, 0x79, 0x1b, 0x58, 0x82, 0xc7, 0x64, 0x19, 0x7c, 0x32, 0x7b, 0x42, + 0x66, 0x9f, 0x32, 0xef, 0x48, 0xb4, 0xf7, 0xd0, 0x74, 0x1f, 0x1c, 0xbe, 0xd4, 0x7a, 0x2a, 0x02, 0xb2, 0x3d, 0x47, 0x15, + 0x40, 0xa8, 0xd5, 0x57, 0xc8, 0xe7, 0x7d, 0x8d, 0xa6, 0xea, 0xe5, 0x21, 0x6a, 0xbe, 0x39, 0x8c, 0xfd, 0x78, 0x26, 0xaf, + 0x31, 0x93, 0x0f, 0x94, 0x07, 0x87, 0x6c, 0xa8, 0x56, 0xd8, 0xc6, 0x79, 0xcf, 0x1d, 0x36, 0xee, 0xab, 0x33, 0x5b, 0x63, + 0xe8, 0x34, 0x00, 0x0c, 0x95, 0x48, 0x34, 0xac, 0xe2, 0xda, 0x61, 0x7a, 0x97, 0x3e, 0x41, 0xe4, 0xb7, 0x30, 0xb0, 0xb3, + 0x96, 0xed, 0x91, 0xb8, 0x5b, 0x20, 0x30, 0xfa, 0xf0, 0xfa, 0xc7, 0xc2, 0x97, 0x14, 0x9b, 0x81, 0xa9, 0x70, 0x8a, 0x10, + 0xf1, 0x75, 0xe4, 0xec, 0x54, 0x3e, 0xd9, 0xa8, 0x94, 0xcd, 0x3a, 0x82, 0xf7, 0xe3, 0xb8, 0x75, 0xd7, 0x49, 0x6c, 0x80, + 0x97, 0xd8, 0xdf, 0x56, 0x66, 0x93, 0xe6, 0xef, 0xa3, 0xc3, 0xd6, 0x34, 0xb7, 0x6f, 0x9b, 0x51, 0xaa, 0x7c, 0x1e, 0x16, + 0x8f, 0x21, 0x8a, 0x0a, 0x9f, 0x0e, 0xbe, 0x6b, 0x96, 0x8b, 0x95, 0x95, 0x5d, 0x11, 0x39, 0x15, 0x8c, 0xca, 0x9d, 0xec, + 0x26, 0x39, 0x49, 0x1e, 0xf6, 0x16, 0x09, 0x36, 0x95, 0xae, 0xa0, 0x55, 0xbf, 0x94, 0xf2, 0x6f, 0x1b, 0x74, 0x93, 0x97, + 0x6d, 0xd8, 0x00, 0x0c, 0xf0, 0x9e, 0x24, 0xb9, 0xfe, 0x04, 0xfa, 0x30, 0x63, 0x90, 0x28, 0xcb, 0x0d, 0x8e, 0xe8, 0xf0, + 0x7f, 0x9a, 0x69, 0x54, 0xf2, 0xbc, 0x9f, 0x24, 0x0b, 0xd1, 0xda, 0x2f, 0x22, 0x81, 0x22, 0x31, 0x03, 0xc2, 0x60, 0x41, + 0x2e, 0xe0, 0xc6, 0x52, 0x7b, 0x5a, 0x35, 0xbc, 0x00, 0xfd, 0x71, 0x00, 0x19, 0xd3, 0xa4, 0xa8, 0x5b, 0xbc, 0xfc, 0xae, + 0x24, 0x10, 0xb4, 0x21, 0x8c, 0x3c, 0x15, 0xad, 0x2d, 0x1e, 0x33, 0x09, 0x58, 0x93, 0xb4, 0x29, 0x3a, 0xbc, 0x6f, 0x7d, + 0x51, 0x3b, 0x5b, 0x97, 0xfe, 0x67, 0xe1, 0x9e, 0xff, 0x6b, 0xdc, 0xf2, 0xb0, 0x6f, 0xa1, 0x4e, 0x4b, 0xf2, 0xdf, 0xd6, + 0xa4, 0xec, 0x8d, 0x19, 0x6d, 0x30, 0x67, 0xde, 0x04, 0x5e, 0xaf, 0xd7, 0xd4, 0x42, 0xf8, 0xbc, 0xca, 0xfc, 0x49, 0xc0, + 0xe7, 0xcd, 0xfc, 0xab, 0xca, 0x3f, 0x67, 0xff, 0xfb, 0x41, 0xc0, 0xe4, 0xe8, 0x0c, 0xe8, 0x2e, 0xca, 0x43, 0xfb, 0xec, + 0xe0, 0xeb, 0xea, 0x30, 0x14, 0xca, 0x30, 0x8d, 0x49, 0xaa, 0x99, 0x71, 0xcb, 0x85, 0xa4, 0x68, 0xda, 0xd1, 0xbe, 0xa9, + 0xc6, 0xee, 0x26, 0xdf, 0x3f, 0xde, 0x39, 0x29, 0x6c, 0x45, 0x9e, 0x41, 0x88, 0x63, 0xd8, 0x31, 0x47, 0x8e, 0xdc, 0xc8, + 0xe4, 0x28, 0x25, 0x75, 0x11, 0x99, 0xdd, 0x28, 0x25, 0xa7, 0x5e, 0xac, 0x7f, 0x0c, 0xb5, 0x2b, 0x62, 0x9d, 0xe0, 0xda, + 0xe3, 0xc2, 0xd8, 0x8d, 0xc6, 0x25, 0x5f, 0x08, 0x6e, 0xfc, 0xcd, 0xae, 0x4c, 0x99, 0x41, 0xc4, 0x75, 0x3e, 0x5e, 0x51, + 0xa1, 0x76, 0x47, 0x93, 0x4a, 0x83, 0x51, 0x91, 0xf3, 0x92, 0xd0, 0x29, 0xa6, 0x44, 0x3c, 0x2a, 0x91, 0x3f, 0x01, 0x75, + 0xeb, 0x6f, 0xf3, 0x3c, 0x04, 0xd3, 0x74, 0x7a, 0xfc, 0x7a, 0x39, 0x70, 0xc8, 0x3a, 0x89, 0x93, 0xbd, 0xfd, 0xd7, 0x41, + 0x2c, 0xb0, 0xd3, 0xef, 0xd0, 0xd5, 0x75, 0x24, 0xb1, 0x0e, 0x3d, 0x89, 0x8e, 0xde, 0xa7, 0x40, 0x80, 0xd2, 0x05, 0xe5, + 0x18, 0xa2, 0xf3, 0x30, 0x22, 0x56, 0x0b, 0xbc, 0x05, 0xb0, 0x48, 0x9a, 0x42, 0xb7, 0xe1, 0x32, 0xba, 0x52, 0x99, 0x22, + 0xf6, 0x30, 0x82, 0x05, 0x68, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x59, + 0x04, 0x82, 0x05, 0x55, 0x30, 0x82, 0x05, 0x51, 0x30, 0x82, 0x05, 0x4d, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0x8e, 0x7e, 0x90, 0x94, 0xaf, 0x09, 0xc5, 0xbc, 0x02, + 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0x0c, 0x7c, 0x7f, 0x58, 0x8b, 0x41, 0x9a, 0xb8, 0x70, 0xbf, 0x6c, 0x4c, 0xb8, + 0x7d, 0x72, 0xa5, 0x50, 0xe6, 0xc4, 0xaf, 0x74, 0x0e, 0x88, 0xbf, 0x83, 0x51, 0xbc, 0xe1, 0x66, 0x8a, 0x9f, 0x42, 0x11, + 0x2b, 0x3d, 0x8c, 0x10, 0xa3, 0xc2, 0xdf, 0xb9, 0x36, 0x74, 0xc1, 0x18, 0x23, 0x1e, 0x9a, 0xbf, 0x8d, 0x0a, 0x4b, 0x63, + 0xd5, 0x20, 0x1b, 0xae, 0xb0, 0x64, 0xfc, 0xe1, 0x5c, 0xe7, 0xde, 0xa3, 0x6f, 0x8e, 0xe3, 0xc9, 0x8d, 0x18, 0x63, 0x7f, + 0x26, 0x4a, 0x3d, 0x41, 0x76, 0xa6, 0xaa, 0x3f, 0x27, 0x75, 0xec, 0x2f, 0x78, 0xd2, 0x40, 0x28, 0xe7, 0xf5, 0xee, 0x61, + 0x6d, 0x49, 0xe0, 0x64, 0x33, 0xc9, 0x9e, 0xf6, 0xda, 0x86, 0x3a, 0xad, 0x47, 0x13, 0xe2, 0x8a, 0x0b, 0x98, 0xe7, 0x73, + 0xea, 0x08, 0x59, 0xfe, 0x74, 0x6f, 0x10, 0x7d, 0xbc, 0x0b, 0xb9, 0xcf, 0xe7, 0xe7, 0x28, 0xe8, 0xfe, 0x20, 0x8a, 0x98, + 0x40, 0x00, 0x52, 0xa0, 0x0c, 0x5c, 0xfa, 0x48, 0x5b, 0xf4, 0x3c, 0x76, 0x5d, 0xf4, 0x33, 0x53, 0xd4, 0x51, 0x43, 0x47, + 0x29, 0xda, 0xff, 0xbd, 0xfe, 0x71, 0x5b, 0x50, 0xa1, 0xa5, 0x25, 0xe9, 0xcc, 0x68, 0x74, 0x9f, 0x7f, 0x39, 0x65, 0x5e, + 0xb9, 0x71, 0x8f, 0x25, 0x68, 0xe6, 0x71, 0x06, 0x10, 0xa2, 0xfb, 0x08, 0x54, 0x21, 0xca, 0x28, 0xfc, 0xf1, 0x89, 0xb9, + 0x29, 0x11, 0x67, 0x00, 0x19, 0xdd, 0x00, 0xd8, 0x48, 0x89, 0x46, 0x0d, 0x39, 0x0c, 0x7e, 0x94, 0x02, 0x80, 0x37, 0xa0, + 0x01, 0x45, 0x25, 0xbd, 0x8b, 0x44, 0xcc, 0xdf, 0x43, 0xa1, 0x1d, 0xf5, 0x59, 0x4b, 0x07, 0xe6, 0xab, 0x15, 0x93, 0x3d, + 0xea, 0x7d, 0xd6, 0xaa, 0xb0, 0x97, 0xed, 0x1d, 0x5e, 0xc2, 0xf0, 0xea, 0x1b, 0xc2, 0xcc, 0x88, 0x47, 0x3e, 0xe4, 0x54, + 0xc3, 0x02, 0xac, 0x5e, 0x88, 0xb9, 0x2f, 0x82, 0xd4, 0xd0, 0x5d, 0xb2, 0x2a, 0xee, 0x94, 0x3d, 0xdb, 0x82, 0x93, 0xc6, + 0x69, 0x5f, 0x40, 0x83, 0xf0, 0x07, 0x8d, 0x9f, 0x7f, 0x29, 0x3f, 0x4d, 0x3b, 0x08, 0xd9, 0x29, 0xf5, 0x1c, 0x0f, 0x18, + 0x42, 0x4b, 0xd9, 0x01, 0xda, 0x71, 0x92, 0xa8, 0x32, 0xa7, 0x53, 0x6f, 0xd0, 0x74, 0x4a, 0xee, 0x39, 0x04, 0xf1, 0x2d, + 0xee, 0x50, 0xbe, 0x48, 0xb1, 0x90, 0x21, 0x24, 0x28, 0x40, 0xa9, 0x85, 0xe1, 0x81, 0x77, 0x37, 0xa8, 0x86, 0x15, 0x7d, + 0x16, 0xb2, 0xe7, 0xcc, 0xe0, 0xa2, 0x7e, 0x58, 0xb3, 0xdc, 0xf9, 0x41, 0xae, 0x36, 0xba, 0x55, 0x87, 0x64, 0x01, 0xfd, + 0xc9, 0x0e, 0xa1, 0xfe, 0x55, 0xc3, 0x2a, 0x66, 0xd5, 0x83, 0x39, 0x7e, 0x5a, 0xe8, 0x28, 0x76, 0x36, 0xbb, 0x39, 0xa9, + 0xb7, 0xc6, 0xcf, 0x99, 0x56, 0xe5, 0xbf, 0x4d, 0xb2, 0xa0, 0xac, 0x64, 0x00, 0xc9, 0x42, 0x79, 0x47, 0x46, 0xd7, 0x9c, + 0x4a, 0x33, 0x03, 0x55, 0x07, 0x7f, 0x05, 0x23, 0xe3, 0x51, 0x35, 0xa9, 0x32, 0xe9, 0xa6, 0xf2, 0xe2, 0x42, 0x4d, 0x00, + 0xbb, 0xdb, 0xc3, 0x85, 0x05, 0xcb, 0xe4, 0xb1, 0x0a, 0x03, 0xf4, 0xe5, 0x27, 0x28, 0x12, 0xec, 0x1e, 0xd4, 0xd7, 0x43, + 0xe3, 0x05, 0xc7, 0x92, 0xd2, 0x8e, 0xf7, 0xae, 0x55, 0x1a, 0x50, 0x88, 0x2f, 0x91, 0x05, 0x65, 0x4b, 0xe3, 0xba, 0xc0, + 0x42, 0x86, 0x19, 0x2b, 0x64, 0xfc, 0x46, 0x31, 0x9b, 0xd2, 0x88, 0x32, 0xf8, 0x4d, 0x91, 0xd4, 0xc6, 0x77, 0xcb, 0x29, + 0x00, 0x5e, 0xd2, 0x48, 0x99, 0x0e, 0x3f, 0x2d, 0x4f, 0xdb, 0x9b, 0x05, 0xea, 0xa1, 0x3d, 0x9f, 0x21, 0x83, 0x6f, 0xcf, + 0xe9, 0x1c, 0x65, 0x40, 0x3c, 0x8b, 0x2a, 0x38, 0x8f, 0x1b, 0x5a, 0x3c, 0x73, 0x7a, 0xfc, 0x81, 0x69, 0xb3, 0xff, 0xb6, + 0x25, 0x12, 0x3f, 0xda, 0x50, 0xe7, 0xde, 0xfe, 0xd3, 0x31, 0x2f, 0xb4, 0x99, 0x87, 0xae, 0x17, 0xaf, 0xe4, 0xb8, 0x35, + 0xf7, 0x3c, 0xc0, 0x99, 0x0e, 0x75, 0x72, 0xb6, 0x46, 0xa1, 0x55, 0xef, 0xff, 0x48, 0x3b, 0x5c, 0x85, 0xf7, 0xc3, 0x03, + 0x0a, 0x49, 0x0f, 0x11, 0x48, 0x13, 0x8b, 0x90, 0x73, 0x33, 0xb6, 0x22, 0x35, 0x45, 0x07, 0x80, 0x1a, 0xf9, 0x91, 0x80, + 0x9d, 0x8b, 0xc7, 0x8e, 0xcc, 0x3a, 0x52, 0x93, 0x8f, 0xf6, 0x59, 0x3c, 0x69, 0xf7, 0x52, 0x9a, 0x8d, 0x8e, 0xfe, 0x8a, + 0x41, 0xb0, 0x43, 0x74, 0x04, 0xe8, 0x0e, 0xf5, 0xc1, 0x4c, 0xa3, 0x8d, 0xe3, 0x98, 0x25, 0xf6, 0xd5, 0x0d, 0xa9, 0x2d, + 0xb7, 0x6f, 0x52, 0x22, 0x43, 0x59, 0x30, 0x6d, 0x54, 0xb6, 0xad, 0x73, 0xa1, 0xe8, 0xee, 0x10, 0xbd, 0x55, 0xa4, 0x7f, + 0xc3, 0x1d, 0xad, 0x8e, 0x72, 0xf1, 0x26, 0x6d, 0xa1, 0xaf, 0xda, 0x82, 0x37, 0xa1, 0x6d, 0xfe, 0x78, 0xd1, 0x88, 0x65, + 0x6a, 0xb2, 0x33, 0x23, 0xcd, 0xba, 0xbe, 0x09, 0x66, 0x61, 0x33, 0xdc, 0x69, 0xed, 0x4f, 0xe6, 0xfb, 0x2f, 0x7d, 0xd0, + 0xfd, 0x7a, 0x21, 0x69, 0x2d, 0x1f, 0xd4, 0xc4, 0x93, 0x7c, 0x34, 0x7d, 0x67, 0x2c, 0xe9, 0x2a, 0x9a, 0x53, 0xc2, 0xbf, + 0xf9, 0x06, 0x10, 0xa6, 0xa8, 0x60, 0xe3, 0x01, 0xcb, 0x2b, 0x03, 0xdb, 0xb7, 0x27, 0xe9, 0x86, 0xe8, 0x7d, 0x75, 0xce, + 0x80, 0xdb, 0xaf, 0xe9, 0x7e, 0x75, 0xad, 0xe3, 0xd4, 0xc4, 0xf3, 0x10, 0x89, 0x16, 0xcb, 0xc6, 0x23, 0x5a, 0x58, 0x66, + 0xb6, 0x2a, 0xd7, 0xc9, 0x69, 0xd3, 0x7f, 0xa2, 0x9a, 0x5c, 0x1c, 0xd4, 0xf8, 0xe3, 0xe0, 0x63, 0x01, 0x88, 0x14, 0xb3, + 0x20, 0xe3, 0x22, 0x45, 0x3d, 0xae, 0xaf, 0x0b, 0x55, 0xa1, 0x65, 0xec, 0x16, 0x0b, 0x35, 0x37, 0x6f, 0x12, 0x5f, 0x29, + 0x47, 0xee, 0xdd, 0xbb, 0xcf, 0x9f, 0x87, 0xaf, 0x7d, 0xaa, 0xf4, 0x01, 0x45, 0xea, 0x5f, 0x00, 0x87, 0x1e, 0xeb, 0x2f, + 0x77, 0x2b, 0x92, 0x42, 0x04, 0x45, 0x33, 0xf2, 0xfb, 0x6b, 0xac, 0xca, 0x98, 0x79, 0x56, 0x6f, 0xe7, 0x5b, 0xbd, 0x63, + 0xc7, 0x3a, 0x8c, 0xfd, 0x93, 0xb1, 0x13, 0x4e, 0xc2, 0x05, 0x7f, 0xde, 0x44, 0xa8, 0xb7, 0xc4, 0x9c, 0xba, 0x57, 0x58, + 0x3b, 0xba, 0xb5, 0x74, 0x73, 0x97, 0x20, 0x53, 0x70, 0x70, 0x65, 0xf1, 0x81, 0xea, 0x07, 0xc2, 0xbe, 0x57, 0x71, 0x62, + 0x3b, 0xc0, 0x3c, 0x07, 0x65, 0xf4, 0x22, 0xfb, 0xd3, 0xf9, 0x2d, 0xb3, 0x20, 0xdd, 0x66, 0x51, 0x89, 0x54, 0x57, 0xcd, + 0xd7, 0xc7, 0x1a, 0xd9, 0xfe, 0xe0, 0x13, 0x9d, 0x7d, 0xe7, 0xe3, 0x2f, 0x65, 0x3e, 0xf0, 0xb2, 0xd9, 0x0c, 0x1a, 0xa9, + 0xaa, 0xba, 0x3b, 0x79, 0x86, 0xed, 0x6c, 0xbf, 0x9e, 0x9b, 0xb5, 0x78, 0xd8, 0x9e, 0x2f, 0x95, 0xcc, 0x31, 0xb4, 0x5f, + 0xd3, 0x63, 0xff, 0xb9, 0x62, 0x34, 0xfd, 0x78, 0x1f, 0xac, 0xe7, 0xbd, 0x29, 0x09, 0x2a, 0x1c, 0x94, 0xc5, 0x28, 0x6c, + 0x04, 0x59, 0xeb, 0xd6, 0x7c, 0x0d, 0x45, 0x07, 0xd9, 0xde, 0x89, 0xa1, 0xd8, 0x38, 0x8a, 0x2b, 0x9f, 0xc3, 0xdb, 0x55, + 0x89, 0x90, 0xc6, 0x75, 0xd0, 0x2f, 0x85, 0x9b, 0x0a, 0x5e, 0x04, 0xa1, 0xf9, 0xf7, 0x16, 0x35, 0x9d, 0x97, 0xfe, 0x7c, + 0x4b, 0x27, 0x4c, 0xc3, 0x8a, 0x2a, 0x56, 0x6a, 0x41, 0xe5, 0xd3, 0x82, 0xeb, 0xd2, 0x62, 0x4e, 0x11, 0x1e, 0x4e, 0xae, + 0xa4, 0x79, 0x89, 0x20, 0x82, 0x6e, 0x39, 0x7d, 0x70, 0xf8, 0x17, 0xd6, 0xe3, 0x67, 0x9a, 0x14, 0xd7, 0xc8, 0x80, 0xbe, + 0x62, 0x52, 0xe7, 0x69, 0xab, 0x98, 0xa9, 0x14, 0x98, 0xbd, 0x30, 0xf4, 0xab, 0x2c, 0x22, 0x6b, 0x5f, 0xee, 0x58, 0xf3, + 0x6f, 0x15, 0xea, 0xce, 0xd3, 0x1b, 0x07, 0xfa, 0xe6, 0x4c, 0xeb, 0xeb, 0x30, 0xa6, 0xff, 0x03, 0xc9, 0x75, 0x94, 0xa5, + 0x5b, 0x68, 0xd3, 0x42, 0x85, 0x3f, 0xa4, 0x87, 0xee, 0x3f, 0x14, 0x63, 0x16, 0x52, 0x26, 0x3b, 0x1a, 0xee, 0x48, 0x77, + 0x6e, 0x4a, 0x56, 0x01, 0x53, 0x54, 0x1b, 0xa6, 0xd7, 0x72, 0x98, 0x89, 0xd5, 0xf7, 0x11, 0x3a, 0x86, 0xac, 0x64, 0xe6, + 0x59, 0xba, 0x07, 0xea, 0x23, 0x21, 0x05, 0xd6, 0x14, 0xed, 0x88, 0x2e, 0x96, 0xb3, 0x90, 0xc3, 0xb7, 0xc4, 0x5b, 0x8f, + 0x0e, 0xcd, 0x56, 0xba, 0xb8, 0x4b, 0x7b, 0xfd, 0xd4, 0x7d, 0x0c, 0xcb, 0xe1, 0xff, 0xaf, 0x3e, 0x2a, 0x7c, 0x1a, 0xe5, + 0x66, 0x65, 0x59, 0x42, 0xd7, 0x3b, 0xd2, 0x2e, 0x89, 0x1d, 0x64, 0xc0, 0xbd, 0xec, 0x8c, 0xaa, 0x06, 0xb8, 0x5a, 0x7c, + 0xb8, 0xd0, 0xa5, 0xef, 0x5a, 0xf3, 0x92, 0x4c, 0x2f, 0x60, 0x98, 0x34, 0x73, 0x49, 0x92, 0x7a, 0x5d, 0x7c, 0x2c, 0xcd, + 0x0b, 0xfb, 0x28, 0xd9, 0x3e, 0xfa, 0xbd, 0x76, 0x0f, 0xaa, 0x71, 0xfa, 0x98, 0x36, 0x94, 0x97, 0xaa, 0x97, 0x1f, 0x34, + 0x21, 0x72, 0xc6, 0x19, 0xb4, 0xe3, 0xaa, 0x05, 0x16, 0xda, 0xaa, 0x92, 0x04, 0x49, 0xc7, 0x97, 0x42, 0x58, 0xd0, 0x80, + 0xdc, 0x9e, 0xcf, 0xfa, 0x5f, 0x4b, 0xbc, 0x78, 0xff, 0x95, 0x39, 0x31, 0x4c, 0x30, 0x25, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x18, 0x1e, 0x16, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x5f, + 0x00, 0x69, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x74, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0xf6, 0x4d, 0x65, 0x40, 0x9d, 0xff, 0x26, 0x84, 0x3f, 0x6e, 0x6b, + 0x99, 0x75, 0xb0, 0xae, 0x60, 0x01, 0x8c, 0xf0, 0xf9, 0x30, 0x30, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, + 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x3d, 0xbb, 0x58, 0x44, 0x6c, 0xa3, 0x3c, 0x48, 0xaa, 0x52, 0x76, 0xd1, 0xef, 0x3a, + 0xe2, 0xa4, 0x23, 0xcc, 0x4d, 0x38, 0x04, 0x08, 0x11, 0xa4, 0xda, 0x79, 0x3e, 0xdd, 0xba, 0xfa, 0x02, 0x01, 0x01 +}; +unsigned int test_import_p12_len = 2499; + +// test_import_p12's password: "password" + +#pragma clang diagnostic pop + +#endif /* kc_identity_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-item-helpers.h b/OSX/libsecurity_keychain/regressions/kc-item-helpers.h new file mode 100644 index 00000000..1a4c901e --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-item-helpers.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015 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 "kc-helpers.h" +#include "utilities/SecCFRelease.h" + +#ifndef kc_item_helpers_h +#define kc_item_helpers_h + +#if TARGET_OS_MAC + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +static CFMutableDictionaryRef makeBaseDictionary(CFStringRef itemclass) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); + CFDictionarySetValue(query, kSecClass, itemclass); + + return query; +} + +static CFMutableDictionaryRef convertToQuery(CFMutableDictionaryRef query, SecKeychainRef kc) { + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, kc); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); + + return query; +} + +static CFMutableDictionaryRef addLabel(CFMutableDictionaryRef query, CFStringRef label) { + CFDictionarySetValue(query, kSecAttrLabel, label); + return query; +} + +static CFMutableDictionaryRef makeBaseItemDictionary(CFStringRef itemclass, CFStringRef service) { + CFMutableDictionaryRef query = makeBaseDictionary(itemclass); + + if(CFEqual(itemclass, kSecClassInternetPassword)) { + CFDictionarySetValue(query, kSecAttrServer, service == NULL ? CFSTR("test_service") : service); + CFDictionarySetValue(query, kSecAttrAuthenticationType, CFSTR("dflt")); // Default, I guess? + } else { + // Generic passwords have services + CFDictionarySetValue(query, kSecAttrService, service == NULL ? CFSTR("test_service") : service); + } + return query; +} + +static CFMutableDictionaryRef makeQueryItemDictionaryWithService(SecKeychainRef kc, CFStringRef itemclass, CFStringRef service) { + return convertToQuery(makeBaseItemDictionary(itemclass, service), kc); +} +static CFMutableDictionaryRef makeQueryItemDictionary(SecKeychainRef kc, CFStringRef itemclass) { + return makeQueryItemDictionaryWithService(kc, itemclass, NULL); +} + +static CFMutableDictionaryRef makeBaseQueryDictionary(SecKeychainRef kc, CFStringRef itemclass) { + return convertToQuery(makeBaseDictionary(itemclass), kc); +} + +static CFMutableDictionaryRef makeQueryCustomItemDictionaryWithService(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label, CFStringRef service) { + CFMutableDictionaryRef query = makeQueryItemDictionaryWithService(kc, itemclass, service); + CFDictionarySetValue(query, kSecAttrLabel, label); + return query; +} +static CFMutableDictionaryRef makeQueryCustomItemDictionary(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { + return makeQueryCustomItemDictionaryWithService(kc, itemclass, label, NULL); +} + +static CFMutableDictionaryRef makeAddCustomItemDictionaryWithService(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label, CFStringRef account, CFStringRef service) { + CFMutableDictionaryRef query = makeBaseItemDictionary(itemclass, service); + + CFDictionaryAddValue(query, kSecUseKeychain, kc); + CFDictionarySetValue(query, kSecAttrAccount, account); + CFDictionarySetValue(query, kSecAttrComment, CFSTR("a comment")); + CFDictionarySetValue(query, kSecAttrLabel, label); + CFDictionarySetValue(query, kSecValueData, CFDataCreate(NULL, (void*)"data", 4)); + return query; +} +static CFMutableDictionaryRef makeAddCustomItemDictionary(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label, CFStringRef account) { + return makeAddCustomItemDictionaryWithService(kc, itemclass, label, account, NULL); +} + +static CFMutableDictionaryRef makeAddItemDictionary(SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { + return makeAddCustomItemDictionary(kc, itemclass, label, CFSTR("test_account")); +} + +static SecKeychainItemRef makeCustomItem(const char* name, SecKeychainRef kc, CFDictionaryRef addDictionary) { + CFTypeRef result = NULL; + ok_status(SecItemAdd(addDictionary, &result), "%s: SecItemAdd", name); + ok(result != NULL, "%s: SecItemAdd returned a result", name); + + SecKeychainItemRef item = (SecKeychainItemRef) result; + ok(item != NULL, "%s: Couldn't convert into SecKeychainItemRef", name); + + return item; +} +#define makeCustomItemTests 3 + +static SecKeychainItemRef makeItem(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { + CFMutableDictionaryRef query = makeAddItemDictionary(kc, itemclass, label); + + SecKeychainItemRef item = makeCustomItem(name, kc, query); + + CFReleaseNull(query); + return item; +} +#define makeItemTests makeCustomItemTests + +static void makeCustomDuplicateItem(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef label) { + CFMutableDictionaryRef query = makeAddItemDictionary(kc, itemclass, label); + + CFTypeRef result = NULL; + is(SecItemAdd(query, &result), errSecDuplicateItem, "%s: SecItemAdd (duplicate)", name); + + CFReleaseNull(query); +} +#define makeCustomDuplicateItemTests 1 + +static void makeDuplicateItem(const char* name, SecKeychainRef kc, CFStringRef itemclass) { + return makeCustomDuplicateItem(name, kc, itemclass, CFSTR("test_label")); +} +#define makeDuplicateItemTests makeCustomDuplicateItemTests + + +#pragma clang pop +#else + +#endif /* TARGET_OS_MAC */ + +#endif /* kc_item_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-key-helpers.h b/OSX/libsecurity_keychain/regressions/kc-key-helpers.h new file mode 100644 index 00000000..08095c8a --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-key-helpers.h @@ -0,0 +1,283 @@ +/* + * 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@ + */ + +#ifndef kc_key_helpers_h +#define kc_key_helpers_h + +#include "kc-helpers.h" +#include "utilities/SecCFRelease.h" + +#if TARGET_OS_MAC + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +static CFMutableDictionaryRef makeBaseKeyDictionary() { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(query, kSecClass, kSecClassKey); + return query; +} + +static CFMutableDictionaryRef makeQueryKeyDictionary(SecKeychainRef kc, CFStringRef keyClass) { + CFMutableDictionaryRef query = makeBaseKeyDictionary(); + + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, kc); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + + CFDictionarySetValue(query, kSecAttrKeyClass, keyClass); + + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); + return query; +} + +static CFMutableDictionaryRef makeQueryKeyDictionaryWithLabel(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) { + CFMutableDictionaryRef query = makeQueryKeyDictionary(kc, keyClass); + CFDictionarySetValue(query, kSecAttrLabel, label); + return query; +} + +static CFMutableDictionaryRef makeAddKeyDictionaryWithApplicationLabel(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label, CFStringRef applicationLabel) { + CFMutableDictionaryRef query = makeBaseKeyDictionary(); + CFDictionaryAddValue(query, kSecUseKeychain, kc); + + CFDictionarySetValue(query, kSecAttrLabel, label); + if(applicationLabel) { + CFDictionarySetValue(query, kSecAttrApplicationLabel, applicationLabel); + } else { + CFDictionarySetValue(query, kSecAttrApplicationLabel, CFSTR("test_application")); // without setting this, it uses the current datetime. + } + + int32_t n = 0; + if(CFEqual(keyClass, kSecAttrKeyClassSymmetric)) { + CFDictionarySetValue(query, kSecAttrKeyType, kSecAttrKeyTypeAES); + n = 128; + } else if(CFEqual(keyClass, kSecAttrKeyClassPublic) || + CFEqual(keyClass, kSecAttrKeyClassPrivate)) { + CFDictionarySetValue(query, kSecAttrKeyType, kSecAttrKeyTypeRSA); + n = 1024; + } + CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &n); + CFDictionarySetValue(query, kSecAttrKeySizeInBits, num); + + return query; +} +static CFMutableDictionaryRef makeAddKeyDictionary(SecKeychainRef kc, CFStringRef keyClass, CFStringRef label) { + return makeAddKeyDictionaryWithApplicationLabel(kc, keyClass, label, NULL); +} + +static SecKeyRef makeCustomKeyWithApplicationLabel(const char* name, SecKeychainRef kc, CFStringRef label, CFStringRef applicationLabel) { + CFMutableDictionaryRef query = makeAddKeyDictionaryWithApplicationLabel(kc, kSecAttrKeyClassSymmetric, label, applicationLabel); + + CFErrorRef error = NULL; + SecKeyRef item = SecKeyGenerateSymmetric(query, &error); + ok(item != NULL, "%s: SecKeyGenerateSymmetric: %ld", name, error ? CFErrorGetCode(error) : 0); + + CFReleaseNull(query); + return item; +} +#define makeCustomKeyWithApplicationLabelTests 1 + +static SecKeyRef makeCustomKey(const char* name, SecKeychainRef kc, CFStringRef label) { + return makeCustomKeyWithApplicationLabel(name, kc, label, NULL); +} +#define makeCustomKeyTests makeCustomKeyWithApplicationLabelTests + +static SecKeyRef makeKey(const char* name, SecKeychainRef kc) { + return makeCustomKey(name, kc, CFSTR("test_key")); +} +#define makeKeyTests makeCustomKeyTests + +static void makeCustomKeyPair(const char* name, SecKeychainRef kc, CFStringRef label, SecKeyRef* aPub, SecKeyRef* aPriv) { + CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassPublic, label); + + SecKeyRef pub; + SecKeyRef priv; + ok_status(SecKeyGeneratePair(query, &pub, &priv), "%s: SecKeyGeneratePair returned a result", name); + + if(aPub) { + *aPub = pub; + } + if(aPriv) { + *aPriv = priv; + } + + CFReleaseNull(query); +} +#define makeCustomKeyPairTests 1 + +static void makeKeyPair(const char* name, SecKeychainRef kc, SecKeyRef* aPub, SecKeyRef* aPriv) { + makeCustomKeyPair(name, kc, CFSTR("test_key"), aPub, aPriv); +} +#define makeKeyPairTests makeCustomKeyPairTests + +// This only works for symmetric keys; key pairs cannot ever generate a duplicate (due to setting kSecKeyLabel to the hash of the public key) +static void makeCustomDuplicateKey(const char* name, SecKeychainRef kc, CFStringRef label) { + CFMutableDictionaryRef query; + + query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); + CFErrorRef error = NULL; + CFReleaseSafe(SecKeyGenerateSymmetric(query, &error)); + is(CFErrorGetCode(error), errSecDuplicateItem, "%s: SecKeyGenerateSymmetric (duplicate) errored: %ld", name, error ? CFErrorGetCode(error) : -1); + + CFReleaseNull(query); +} +#define makeCustomDuplicateKeyTests 1 + +static void makeDuplicateKey(const char* name, SecKeychainRef kc) { + makeCustomDuplicateKey(name, kc, CFSTR("test_key")); +} +#define makeDuplicateKeyTests makeCustomDuplicateKeyTests + +static SecKeyRef makeCustomFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) { + SecKeyRef symkey; + + ok_status(SecKeyGenerate( + NULL, + CSSM_ALGID_AES, 128, + 0, /* contextHandle */ + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, /* initialAccess */ + &symkey), "%s: SecKeyGenerate", name);; + + CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); + + CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)itemList, symkey); + + CFDictionarySetValue(query, kSecUseItemList, itemList); + + CFTypeRef result = NULL; + ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name); + ok(result != NULL, "%s: SecItemAdd returned a result", name); + CFReleaseNull(symkey); + return (SecKeyRef) result; +} +#define makeCustomFreeKeyTests 3 + +static SecKeyRef makeFreeKey(const char* name, SecKeychainRef kc) { + return makeCustomFreeKey(name, kc, CFSTR("test_free_key")); +} +#define makeFreeKeyTests makeCustomFreeKeyTests + +static SecKeyRef makeCustomDuplicateFreeKey(const char* name, SecKeychainRef kc, CFStringRef label) { + SecKeyRef symkey; + + ok_status(SecKeyGenerate( + NULL, + CSSM_ALGID_AES, 128, + 0, /* contextHandle */ + CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, + CSSM_KEYATTR_EXTRACTABLE, + NULL, /* initialAccess */ + &symkey), "%s: SecKeyGenerate", name);; + + CFMutableDictionaryRef query = makeAddKeyDictionary(kc, kSecAttrKeyClassSymmetric, label); + + CFMutableArrayRef itemList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)itemList, symkey); + + CFDictionarySetValue(query, kSecUseItemList, itemList); + + CFTypeRef result = NULL; + is(SecItemAdd(query, &result), errSecDuplicateItem, "%s: SecItemAdd (duplicate)", name); + CFReleaseNull(symkey); + return (SecKeyRef) result; +} +#define makeCustomDuplicateFreeKeyTests 2 + +static SecKeyRef makeDuplicateFreeKey(const char* name, SecKeychainRef kc) { + return makeCustomFreeKey(name, kc, CFSTR("test_free_key")); +} +#define makeDuplicateFreeKeyTests makeCustomDuplicateFreeKeyTests + +#define checkKeyUseTests 4 +static void checkKeyUse(SecKeyRef key, OSStatus expectedStatus) { + CFStringRef plaintext = CFSTR("A short story: the string goes into the encryptor, and returns unrecognizable. The decryptor reverses."); + CFDataRef plaintextData = CFDataCreate(NULL, (uint8_t*) CFStringGetCStringPtr(plaintext, kCFStringEncodingUTF8), CFStringGetLength(plaintext)); + + /* encrypt first */ + SecTransformRef transform = SecEncryptTransformCreate(key, NULL); + SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, NULL); + SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL); + SecTransformSetAttribute(transform, kSecTransformInputAttributeName, plaintextData, NULL); + + CFErrorRef error = NULL; + CFDataRef ciphertextData = SecTransformExecute(transform, &error); + + 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); + + if(expectedStatus != errSecSuccess) { + // make test numbers match and quit + for(int i = 1; i < checkKeyUseTests; i++) { + pass("test numbers match"); + } + return; + } + + } else { + pass("%s: transform executed", testName); + } + + CFReleaseSafe(transform); + + /* and now decrypt */ + transform = SecDecryptTransformCreate(key, NULL); + SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, NULL); + SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, NULL); + SecTransformSetAttribute(transform, kSecTransformInputAttributeName, ciphertextData, NULL); + + CFDataRef 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); + } else { + pass("%s: make test numbers match", testName); + } + + CFReleaseSafe(transform); + + eq_cf(plaintextData, roundtripData, "%s: checkKeyUse: roundtripped data is input data", testName); + + CFReleaseSafe(plaintext); + CFReleaseSafe(plaintextData); + CFReleaseSafe(ciphertextData); + CFReleaseSafe(roundtripData); +} + + + +#pragma clang diagnostic pop + +#else + +#endif /* TARGET_OS_MAC */ + + +#endif /* kc_key_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-keychain-file-helpers.h b/OSX/libsecurity_keychain/regressions/kc-keychain-file-helpers.h new file mode 100644 index 00000000..f6d99a41 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-keychain-file-helpers.h @@ -0,0 +1,2384 @@ +/* + * 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@ + */ + +#ifndef kc_file_helpers_h +#define kc_file_helpers_h + +#include +#include + + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +/* Deletes any keychain files that might exist at this location, and ignore any errors */ +static void deleteKeychainFiles(const char* basename) { + // remove the keychain if it exists, but ignore any errors + unlink(basename); + char * dbFilename = NULL; + asprintf(&dbFilename, "%s-db", basename); + unlink(dbFilename); + free(dbFilename); +} + +static SecKeychainRef createNewKeychainAt(const char * filename, const char * password) { + deleteKeychainFiles(filename); + + SecKeychainRef keychain = NULL; + ok_status(SecKeychainCreate(filename, (UInt32) strlen(password), password, FALSE, NULL, &keychain), "SecKeychainCreate"); + return keychain; +} + +static SecKeychainRef createNewKeychain(const char * name, const char * password) { + const char *home_dir = getenv("HOME"); + char * filename; + + asprintf(&filename, "%s/Library/Keychains/%s", home_dir, name); + SecKeychainRef keychain = createNewKeychainAt(filename, password); + free(filename); + return keychain; +} + +static void writeFile(const char* path, uint8_t* buf, size_t len) { + FILE * fp = fopen(path, "w+"); + fwrite(buf, sizeof(uint8_t), len, fp); + fclose(fp); +} + +// The following keychain includes: +// +// security add-internet-password -s test_service_restrictive_acl -a test_account -j "a useful comment" -r "htps" -t dflt -w test_password test.keychain +// security add-internet-password -s test_service -a test_account -j "a useful comment" -r "htps" -t dflt -w test_password -A test.keychain +// security add-generic-password -a test_account -s test_service -j "another useful comment" -w test_password -A test.keychain +// security add-generic-password -a test_account -s test_service_restrictive_acl -j "another useful comment" -w test_password test.keychain + +// With certificate assistant, added a: +// Code Signing identity +// S/MIME identity + +const char * test_keychain_password = "password"; + +unsigned char test_keychain[] = { + 0x6b, 0x79, 0x63, 0x68, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb3, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x03, 0x64, 0x00, 0x00, 0x1b, 0x70, + 0x00, 0x00, 0x4d, 0xe8, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0x57, 0xe0, 0x00, 0x00, 0x6c, 0x88, 0x00, 0x00, 0x8b, 0x44, + 0x00, 0x00, 0x91, 0x20, 0x00, 0x00, 0x96, 0x4c, 0x00, 0x00, 0x97, 0x0c, 0x00, 0x00, 0xb2, 0x28, 0x00, 0x00, 0x03, 0x2c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x03, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x01, 0x14, + 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x01, 0xac, 0x00, 0x00, 0x01, 0xd4, 0x00, 0x00, 0x02, 0x04, + 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x02, 0xd8, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, + 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x43, 0x53, 0x53, 0x4d, + 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x41, 0x54, 0x54, 0x52, 0x49, 0x42, + 0x55, 0x54, 0x45, 0x53, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x19, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, + 0x41, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x45, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, + 0x44, 0x42, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x4d, 0x41, 0x5f, 0x50, 0x41, 0x52, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x4f, + 0x44, 0x55, 0x4c, 0x45, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x44, 0x42, 0x42, 0x6c, 0x6f, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1c, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, + 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d, + 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, 0x50, 0x52, + 0x49, 0x56, 0x41, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1f, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, + 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, 0x53, 0x59, 0x4d, 0x4d, 0x45, 0x54, 0x52, 0x49, 0x43, 0x5f, + 0x4b, 0x45, 0x59, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x25, 0x80, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x22, 0x43, 0x53, 0x53, 0x4d, 0x5f, 0x44, 0x4c, 0x5f, 0x44, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, + 0x44, 0x5f, 0x58, 0x35, 0x30, 0x39, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5a, + 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x01, 0x84, + 0x00, 0x00, 0x01, 0xc4, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x02, 0xc4, + 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x03, 0xc4, 0x00, 0x00, 0x04, 0x04, + 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x04, 0x84, 0x00, 0x00, 0x04, 0xc4, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x05, 0x44, + 0x00, 0x00, 0x05, 0x84, 0x00, 0x00, 0x05, 0xc4, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x06, 0x84, + 0x00, 0x00, 0x06, 0xc4, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x84, 0x00, 0x00, 0x07, 0xc4, + 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x08, 0x44, 0x00, 0x00, 0x08, 0x84, 0x00, 0x00, 0x08, 0xc4, 0x00, 0x00, 0x09, 0x04, + 0x00, 0x00, 0x09, 0x44, 0x00, 0x00, 0x09, 0x84, 0x00, 0x00, 0x09, 0xc4, 0x00, 0x00, 0x0a, 0x04, 0x00, 0x00, 0x0a, 0x44, + 0x00, 0x00, 0x0a, 0x84, 0x00, 0x00, 0x0a, 0xc4, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x0b, 0x44, 0x00, 0x00, 0x0b, 0x84, + 0x00, 0x00, 0x0b, 0xc4, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x0c, 0x84, 0x00, 0x00, 0x0c, 0xc4, + 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0d, 0x44, 0x00, 0x00, 0x0d, 0x84, 0x00, 0x00, 0x0d, 0xc4, 0x00, 0x00, 0x0e, 0x04, + 0x00, 0x00, 0x0e, 0x44, 0x00, 0x00, 0x0e, 0x84, 0x00, 0x00, 0x0e, 0xc4, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0f, 0x44, + 0x00, 0x00, 0x0f, 0x84, 0x00, 0x00, 0x0f, 0xc4, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x10, 0x84, + 0x00, 0x00, 0x10, 0xc4, 0x00, 0x00, 0x11, 0x04, 0x00, 0x00, 0x11, 0x44, 0x00, 0x00, 0x11, 0x84, 0x00, 0x00, 0x11, 0xc4, + 0x00, 0x00, 0x12, 0x04, 0x00, 0x00, 0x12, 0x44, 0x00, 0x00, 0x12, 0x84, 0x00, 0x00, 0x12, 0xc4, 0x00, 0x00, 0x13, 0x04, + 0x00, 0x00, 0x13, 0x44, 0x00, 0x00, 0x13, 0x84, 0x00, 0x00, 0x13, 0xc4, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x14, 0x44, + 0x00, 0x00, 0x14, 0x84, 0x00, 0x00, 0x14, 0xc4, 0x00, 0x00, 0x15, 0x04, 0x00, 0x00, 0x15, 0x44, 0x00, 0x00, 0x15, 0x84, + 0x00, 0x00, 0x15, 0xc4, 0x00, 0x00, 0x16, 0x04, 0x00, 0x00, 0x16, 0x44, 0x00, 0x00, 0x16, 0x84, 0x00, 0x00, 0x16, 0xc4, + 0x00, 0x00, 0x17, 0x04, 0x00, 0x00, 0x17, 0x44, 0x00, 0x00, 0x17, 0x84, 0x00, 0x00, 0x17, 0xc4, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x69, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x73, 0x64, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x72, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x08, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x73, 0x64, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x70, 0x74, 0x63, 0x6c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, + 0x61, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x70, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x27, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x36, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6e, 0x62, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x63, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x61, 0x6c, 0x69, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x03, 0x73, 0x75, 0x62, 0x6a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x73, 0x73, 0x75, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x73, 0x6e, 0x62, 0x72, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x73, 0x6b, 0x69, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x59, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x68, 0x70, 0x6b, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x78, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x02, 0xac, + 0x00, 0x00, 0x32, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x02, 0xac, 0x00, 0x00, 0x02, 0xfc, + 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x03, 0x9c, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x04, 0x98, + 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x05, 0x40, 0x00, 0x00, 0x05, 0x90, 0x00, 0x00, 0x05, 0xdc, 0x00, 0x00, 0x06, 0x2c, + 0x00, 0x00, 0x06, 0x7c, 0x00, 0x00, 0x06, 0xd4, 0x00, 0x00, 0x07, 0x24, 0x00, 0x00, 0x07, 0x74, 0x00, 0x00, 0x07, 0xc0, + 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x58, 0x00, 0x00, 0x08, 0xac, 0x00, 0x00, 0x08, 0xec, 0x00, 0x00, 0x09, 0x2c, + 0x00, 0x00, 0x09, 0x6c, 0x00, 0x00, 0x09, 0xac, 0x00, 0x00, 0x09, 0xec, 0x00, 0x00, 0x0a, 0x2c, 0x00, 0x00, 0x0a, 0x6c, + 0x00, 0x00, 0x0a, 0xbc, 0x00, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x0b, 0x48, 0x00, 0x00, 0x0b, 0x88, 0x00, 0x00, 0x0b, 0xc8, + 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x0c, 0x88, 0x00, 0x00, 0x0c, 0xc8, 0x00, 0x00, 0x0d, 0x08, + 0x00, 0x00, 0x0d, 0x48, 0x00, 0x00, 0x0d, 0x88, 0x00, 0x00, 0x0d, 0xc8, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0e, 0x48, + 0x00, 0x00, 0x0e, 0x88, 0x00, 0x00, 0x0e, 0xd8, 0x00, 0x00, 0x0f, 0x24, 0x00, 0x00, 0x0f, 0x64, 0x00, 0x00, 0x0f, 0xa4, + 0x00, 0x00, 0x0f, 0xe4, 0x00, 0x00, 0x10, 0x24, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x10, 0xa4, 0x00, 0x00, 0x10, 0xe4, + 0x00, 0x00, 0x11, 0x24, 0x00, 0x00, 0x11, 0x64, 0x00, 0x00, 0x11, 0xa4, 0x00, 0x00, 0x11, 0xe4, 0x00, 0x00, 0x12, 0x24, + 0x00, 0x00, 0x12, 0x64, 0x00, 0x00, 0x12, 0xa4, 0x00, 0x00, 0x12, 0xe4, 0x00, 0x00, 0x13, 0x24, 0x00, 0x00, 0x13, 0x64, + 0x00, 0x00, 0x13, 0xb4, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x14, 0xc0, + 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x40, 0x00, 0x00, 0x15, 0x80, 0x00, 0x00, 0x15, 0xc0, 0x00, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x16, 0x40, 0x00, 0x00, 0x16, 0x80, 0x00, 0x00, 0x16, 0xc0, 0x00, 0x00, 0x17, 0x0c, 0x00, 0x00, 0x17, 0x5c, + 0x00, 0x00, 0x17, 0xa8, 0x00, 0x00, 0x17, 0xf8, 0x00, 0x00, 0x18, 0x44, 0x00, 0x00, 0x18, 0x94, 0x00, 0x00, 0x18, 0xe0, + 0x00, 0x00, 0x19, 0x34, 0x00, 0x00, 0x19, 0x84, 0x00, 0x00, 0x19, 0xd0, 0x00, 0x00, 0x1a, 0x24, 0x00, 0x00, 0x1a, 0x78, + 0x00, 0x00, 0x1a, 0xc8, 0x00, 0x00, 0x1b, 0x14, 0x00, 0x00, 0x1b, 0x64, 0x00, 0x00, 0x1b, 0xb8, 0x00, 0x00, 0x1c, 0x08, + 0x00, 0x00, 0x1c, 0x5c, 0x00, 0x00, 0x1c, 0xa8, 0x00, 0x00, 0x1c, 0xf4, 0x00, 0x00, 0x1d, 0x40, 0x00, 0x00, 0x1d, 0x88, + 0x00, 0x00, 0x1d, 0xd4, 0x00, 0x00, 0x1e, 0x24, 0x00, 0x00, 0x1e, 0x78, 0x00, 0x00, 0x1e, 0xc0, 0x00, 0x00, 0x1f, 0x0c, + 0x00, 0x00, 0x1f, 0x58, 0x00, 0x00, 0x1f, 0xa8, 0x00, 0x00, 0x1f, 0xf4, 0x00, 0x00, 0x20, 0x44, 0x00, 0x00, 0x20, 0x90, + 0x00, 0x00, 0x20, 0xe0, 0x00, 0x00, 0x21, 0x2c, 0x00, 0x00, 0x21, 0x80, 0x00, 0x00, 0x21, 0xd0, 0x00, 0x00, 0x22, 0x1c, + 0x00, 0x00, 0x22, 0x70, 0x00, 0x00, 0x22, 0xc4, 0x00, 0x00, 0x23, 0x14, 0x00, 0x00, 0x23, 0x60, 0x00, 0x00, 0x23, 0xb0, + 0x00, 0x00, 0x24, 0x04, 0x00, 0x00, 0x24, 0x54, 0x00, 0x00, 0x24, 0xa8, 0x00, 0x00, 0x24, 0xf4, 0x00, 0x00, 0x25, 0x40, + 0x00, 0x00, 0x25, 0x8c, 0x00, 0x00, 0x25, 0xd4, 0x00, 0x00, 0x26, 0x20, 0x00, 0x00, 0x26, 0x70, 0x00, 0x00, 0x26, 0xc4, + 0x00, 0x00, 0x27, 0x0c, 0x00, 0x00, 0x27, 0x58, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x27, 0xf4, 0x00, 0x00, 0x28, 0x40, + 0x00, 0x00, 0x28, 0x90, 0x00, 0x00, 0x28, 0xdc, 0x00, 0x00, 0x29, 0x2c, 0x00, 0x00, 0x29, 0x78, 0x00, 0x00, 0x29, 0xcc, + 0x00, 0x00, 0x2a, 0x1c, 0x00, 0x00, 0x2a, 0x68, 0x00, 0x00, 0x2a, 0xbc, 0x00, 0x00, 0x2b, 0x10, 0x00, 0x00, 0x2b, 0x60, + 0x00, 0x00, 0x2b, 0xac, 0x00, 0x00, 0x2b, 0xfc, 0x00, 0x00, 0x2c, 0x50, 0x00, 0x00, 0x2c, 0xa0, 0x00, 0x00, 0x2c, 0xf4, + 0x00, 0x00, 0x2d, 0x40, 0x00, 0x00, 0x2d, 0x8c, 0x00, 0x00, 0x2d, 0xd8, 0x00, 0x00, 0x2e, 0x20, 0x00, 0x00, 0x2e, 0x6c, + 0x00, 0x00, 0x2e, 0xbc, 0x00, 0x00, 0x2f, 0x10, 0x00, 0x00, 0x2f, 0x58, 0x00, 0x00, 0x2f, 0xa4, 0x00, 0x00, 0x2f, 0xf0, + 0x00, 0x00, 0x30, 0x40, 0x00, 0x00, 0x30, 0x90, 0x00, 0x00, 0x30, 0xdc, 0x00, 0x00, 0x31, 0x28, 0x00, 0x00, 0x31, 0x74, + 0x00, 0x00, 0x31, 0xc4, 0x00, 0x00, 0x32, 0x1c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x4c, + 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x41, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x4d, 0x6f, 0x64, 0x75, + 0x6c, 0x65, 0x49, 0x44, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x41, 0x64, 0x64, 0x69, 0x6e, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x53, 0x53, 0x49, 0x44, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x63, 0x64, 0x61, 0x74, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x6d, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x69, 0x63, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x63, 0x72, 0x74, 0x72, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x73, 0x63, 0x72, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x69, 0x6e, 0x76, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x6e, 0x65, 0x67, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x63, 0x75, 0x73, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x70, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, 0x61, 0x63, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x00, + 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x00, 0x67, 0x65, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x63, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x6d, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x64, 0x65, 0x73, 0x63, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x69, 0x63, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x27, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x63, 0x72, 0x74, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x73, 0x63, 0x72, 0x70, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x69, 0x6e, 0x76, 0x69, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x6e, 0x65, 0x67, 0x61, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x63, 0x75, 0x73, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x70, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x73, 0x72, 0x76, 0x72, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, + 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x34, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x02, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x02, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x63, 0x64, 0x61, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x6d, 0x64, 0x61, 0x74, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x69, 0x63, 0x6d, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x63, 0x72, 0x74, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x73, 0x63, 0x72, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x69, 0x6e, 0x76, 0x69, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x6e, 0x65, 0x67, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x41, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x63, 0x75, 0x73, 0x69, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x70, 0x72, 0x6f, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x73, 0x64, 0x6d, 0x6e, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, + 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x46, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, + 0x80, 0x00, 0x00, 0x01, 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x61, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x80, 0x00, 0x00, 0x01, 0x70, 0x61, 0x74, 0x68, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x4b, 0x65, 0x79, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, + 0x4b, 0x65, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, + 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x4b, 0x65, 0x79, 0x53, + 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, + 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, + 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, + 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x10, 0x4e, 0x65, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5f, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x53, 0x69, 0x67, 0x6e, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x57, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, + 0x55, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x65, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x4b, 0x65, 0x79, 0x43, + 0x6c, 0x61, 0x73, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x65, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x07, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, + 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x10, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0f, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x4e, 0x65, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x53, 0x69, 0x67, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x57, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x06, 0x55, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, + 0x4b, 0x65, 0x79, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x81, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x72, 0x69, 0x6e, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x82, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, + 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x67, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x65, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0d, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x49, 0x6e, 0x42, 0x69, 0x74, 0x73, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4b, 0x65, 0x79, + 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, + 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, + 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x4e, 0x65, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x92, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x45, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x53, 0x69, 0x67, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x96, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x99, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x57, 0x72, 0x61, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x55, 0x6e, 0x77, 0x72, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x10, 0x00, 0x63, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x08, 0x43, 0x65, 0x72, 0x74, 0x54, 0x79, 0x70, 0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x10, 0x00, 0x63, 0x65, 0x6e, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, + 0x43, 0x65, 0x72, 0x74, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, + 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x10, 0x00, 0x6c, 0x61, 0x62, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, + 0x50, 0x72, 0x69, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x10, 0x00, 0x61, 0x6c, 0x69, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, + 0x41, 0x6c, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x9f, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x80, 0x00, 0x10, 0x00, 0x73, 0x75, 0x62, 0x6a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x53, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x80, 0x00, 0x10, 0x00, + 0x69, 0x73, 0x73, 0x75, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x80, 0x00, 0x10, 0x00, 0x73, 0x6e, 0x62, 0x72, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, + 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x80, 0x00, 0x10, 0x00, 0x73, 0x6b, 0x69, 0x64, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0xa3, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, + 0x80, 0x00, 0x10, 0x00, 0x68, 0x70, 0x6b, 0x79, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x48, 0x61, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x03, 0x20, + 0x00, 0x00, 0x02, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xb2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x02, 0x51, + 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x02, 0x79, + 0x00, 0x00, 0x02, 0xa5, 0x00, 0x00, 0x02, 0xa9, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb1, 0x00, 0x00, 0x02, 0xbd, + 0x00, 0x00, 0x02, 0xc9, 0x00, 0x00, 0x02, 0xcd, 0x00, 0x00, 0x02, 0xd1, 0x00, 0x00, 0x02, 0xd5, 0x00, 0x00, 0x02, 0xd9, + 0x00, 0x00, 0x02, 0xdd, 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0x00, 0x00, 0x02, 0xe9, 0x00, 0x00, 0x02, 0xed, + 0x00, 0x00, 0x02, 0xf1, 0x00, 0x00, 0x02, 0xf5, 0x00, 0x00, 0x02, 0xf9, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x01, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, 0x65, 0x78, 0x74, 0x20, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xb3, 0xaa, 0xa8, 0x77, 0xe7, 0x3e, 0x2d, 0x0c, 0xf4, 0x83, 0x55, 0xc2, 0x9e, 0x50, 0x10, + 0xc9, 0xef, 0xc8, 0x48, 0x38, 0xe4, 0x43, 0x96, 0xfa, 0x93, 0x32, 0xbf, 0x66, 0xad, 0x84, 0xa2, 0x8b, 0x6b, 0x07, 0x8c, + 0xc6, 0x93, 0x8c, 0x4d, 0x65, 0x0f, 0xad, 0x76, 0x73, 0x0c, 0x4d, 0x43, 0xee, 0x35, 0xd4, 0x68, 0x4a, 0x9a, 0x6d, 0x4d, + 0xa5, 0xae, 0x66, 0xcf, 0xfb, 0xbb, 0x93, 0xd3, 0x6a, 0xe3, 0xfc, 0x41, 0x97, 0xae, 0x90, 0xc3, 0xd8, 0x83, 0xfb, 0x8d, + 0x67, 0x84, 0xc1, 0xd5, 0x7d, 0x1d, 0x12, 0xca, 0x0c, 0xb5, 0xae, 0xf0, 0xe3, 0x36, 0x39, 0xf1, 0x68, 0x92, 0x6f, 0xda, + 0x2d, 0x48, 0x87, 0xf0, 0x4b, 0x15, 0x4e, 0x4f, 0x7a, 0x3a, 0x16, 0xb9, 0x02, 0x89, 0x95, 0x98, 0xab, 0xb2, 0x58, 0x5b, + 0x31, 0x7f, 0x49, 0x90, 0x48, 0xfd, 0x8d, 0x8a, 0x37, 0x3a, 0x4e, 0xd8, 0x00, 0x4a, 0xdc, 0xd4, 0x02, 0x9f, 0xcd, 0x4b, + 0xde, 0x75, 0x4a, 0xb2, 0x27, 0x8e, 0xe6, 0x2d, 0xea, 0x35, 0x89, 0x85, 0x8a, 0x37, 0x59, 0xd6, 0xd1, 0xf8, 0x36, 0x7c, + 0x93, 0x9e, 0xd6, 0xd1, 0xc3, 0xd9, 0x75, 0xa4, 0x4f, 0x40, 0x24, 0xe9, 0xc0, 0xde, 0xeb, 0xc0, 0x5e, 0xd6, 0x04, 0xe1, + 0xd0, 0x07, 0x29, 0xc1, 0x9d, 0x6f, 0x78, 0x2d, 0x5a, 0xef, 0xe6, 0xff, 0x25, 0x16, 0xcf, 0x60, 0x77, 0xa2, 0x10, 0x2b, + 0xa4, 0x2a, 0xff, 0x74, 0x3b, 0xe6, 0x4d, 0xc1, 0x13, 0xba, 0x8b, 0xe8, 0x15, 0x8e, 0xc7, 0xc3, 0xd4, 0x31, 0xb0, 0x99, + 0x51, 0x32, 0x30, 0x03, 0x0b, 0x1c, 0xa0, 0x0a, 0x17, 0x15, 0x34, 0x57, 0x38, 0xd3, 0x08, 0x13, 0xc4, 0xd6, 0x7c, 0x24, + 0x16, 0xd0, 0x2f, 0x00, 0x88, 0xd7, 0xd9, 0xca, 0x1e, 0x6b, 0x50, 0x3b, 0x5f, 0xb6, 0x08, 0xb1, 0x29, 0x42, 0x70, 0xf1, + 0x89, 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0a, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, 0x29, 0x26, 0x07, 0x8d, + 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x02, 0x51, + 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x02, 0x79, + 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00, 0x02, 0xa9, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb1, 0x00, 0x00, 0x02, 0xb5, + 0x00, 0x00, 0x02, 0xc1, 0x00, 0x00, 0x02, 0xcd, 0x00, 0x00, 0x02, 0xd1, 0x00, 0x00, 0x02, 0xd5, 0x00, 0x00, 0x02, 0xd9, + 0x00, 0x00, 0x02, 0xdd, 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0x00, 0x00, 0x02, 0xe9, 0x00, 0x00, 0x02, 0xed, + 0x00, 0x00, 0x02, 0xf1, 0x00, 0x00, 0x02, 0xf5, 0x00, 0x00, 0x02, 0xf9, 0x00, 0x00, 0x02, 0xfd, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x01, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x21, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x74, 0x65, 0x78, + 0x74, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x48, 0x39, 0x92, 0x01, 0x00, 0x00, 0x00, + 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb6, 0x07, 0xac, 0x5c, 0xc6, 0xcb, 0xf0, 0xb7, 0x97, 0x0d, 0x43, + 0x1a, 0xe9, 0x61, 0xe7, 0x34, 0x63, 0x6a, 0x26, 0x0d, 0x77, 0xba, 0x25, 0xaa, 0xc8, 0x46, 0xf8, 0xc9, 0xdd, 0x21, 0xb4, + 0x3e, 0x2e, 0x11, 0x8e, 0xb6, 0x72, 0xf2, 0x01, 0x16, 0x07, 0xcf, 0x88, 0x91, 0xc4, 0xc0, 0x48, 0x64, 0x41, 0x91, 0xf7, + 0x63, 0x72, 0xd5, 0x37, 0xef, 0x37, 0x62, 0xed, 0x33, 0xb3, 0xf9, 0x6e, 0x31, 0xd1, 0x68, 0xe7, 0xde, 0x62, 0x9f, 0x82, + 0xb8, 0x9e, 0x11, 0xe7, 0x66, 0x91, 0xc1, 0xbe, 0xe5, 0x5c, 0xd6, 0x71, 0x83, 0x91, 0xbc, 0x0f, 0xa8, 0x06, 0xc3, 0xe9, + 0xb6, 0x76, 0x16, 0xae, 0x69, 0x0a, 0x47, 0xe4, 0x65, 0xaa, 0x13, 0x71, 0x48, 0xb3, 0x5c, 0x25, 0xa5, 0x1a, 0xd0, 0x2a, + 0x57, 0x57, 0xf9, 0xb7, 0x13, 0xbd, 0xf4, 0x13, 0x5a, 0x11, 0x1b, 0xcc, 0xd8, 0x9a, 0x5f, 0x82, 0x3f, 0xa7, 0x6b, 0x64, + 0x47, 0x54, 0xb6, 0x81, 0xaf, 0xcb, 0x4b, 0x94, 0x39, 0x65, 0x15, 0xba, 0x6a, 0x02, 0x7c, 0x71, 0x30, 0x60, 0x21, 0x12, + 0x63, 0x28, 0xe0, 0x85, 0xca, 0xcc, 0x07, 0xb1, 0x13, 0x40, 0x19, 0x72, 0x02, 0x35, 0x0e, 0x2d, 0x4b, 0x8a, 0xcd, 0x1d, + 0x09, 0x65, 0xb0, 0x81, 0x49, 0xea, 0x70, 0x15, 0x92, 0x19, 0x7b, 0xfe, 0x15, 0xf7, 0x4a, 0x3f, 0x1e, 0x3c, 0x63, 0x7a, + 0x0f, 0x17, 0x32, 0x1a, 0xb7, 0x26, 0xa1, 0xa0, 0x9b, 0x3f, 0x4e, 0x7c, 0x38, 0xe6, 0x27, 0xbf, 0xa8, 0x1b, 0xf7, 0xbd, + 0x2d, 0xfd, 0x9b, 0x05, 0x0c, 0xaa, 0x81, 0xb8, 0x09, 0xd4, 0xe2, 0xe3, 0xbd, 0x6c, 0x70, 0xc0, 0x7e, 0x95, 0xd4, 0x0b, + 0x13, 0xab, 0xb8, 0xdd, 0x3d, 0x4c, 0x59, 0xf0, 0xc7, 0x8e, 0x47, 0xb5, 0xd8, 0x31, 0x78, 0x80, 0xd2, 0x5f, 0x0c, 0x0b, + 0xae, 0x22, 0xe7, 0x9e, 0xd3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xc7, 0xc5, 0x36, 0xbc, + 0xce, 0x8e, 0x86, 0xa8, 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, 0x20, 0x1e, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, + 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, + 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xb0, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x06, 0x54, 0x00, 0x00, 0x07, 0x78, 0x00, 0x00, 0x07, 0xd8, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x48, + 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x08, 0xb8, 0x00, 0x00, 0x08, 0xf0, 0x00, 0x00, 0x09, 0x28, 0x00, 0x00, 0x09, 0x60, + 0x00, 0x00, 0x09, 0x98, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x98, + 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, + 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, 0x20, 0x1e, 0x00, 0x7c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, + 0x29, 0x26, 0x07, 0x8d, 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, + 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x07, 0xbc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x14, 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, + 0x20, 0x1e, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, + 0x29, 0x26, 0x07, 0x8d, 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x38, 0x00, 0x00, 0x08, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x08, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0xa8, 0x00, 0x00, 0x08, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x08, 0xe0, 0x00, 0x00, 0x08, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x09, 0x18, + 0x00, 0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x09, 0x50, 0x00, 0x00, 0x09, 0x58, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x09, 0x88, 0x00, 0x00, 0x09, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x09, 0xc0, 0x00, 0x00, 0x09, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0xa8, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x10, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x06, 0xc4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, + 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, 0x15, 0x00, 0x00, 0x06, 0x19, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x00, 0x06, 0x21, + 0x00, 0x00, 0x06, 0x25, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x06, 0x41, 0x00, 0x00, 0x06, 0x6d, 0x00, 0x00, 0x06, 0x71, + 0x00, 0x00, 0x06, 0x75, 0x00, 0x00, 0x06, 0x79, 0x00, 0x00, 0x06, 0x85, 0x00, 0x00, 0x06, 0x91, 0x00, 0x00, 0x06, 0x95, + 0x00, 0x00, 0x06, 0x99, 0x00, 0x00, 0x06, 0x9d, 0x00, 0x00, 0x06, 0xa1, 0x00, 0x00, 0x06, 0xa5, 0x00, 0x00, 0x06, 0xa9, + 0x00, 0x00, 0x06, 0xad, 0x00, 0x00, 0x06, 0xb1, 0x00, 0x00, 0x06, 0xb5, 0x00, 0x00, 0x06, 0xb9, 0x00, 0x00, 0x06, 0xbd, + 0x00, 0x00, 0x06, 0xc1, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x05, 0x7c, + 0xce, 0x5e, 0x64, 0x56, 0xc9, 0x2c, 0x8c, 0xbb, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, + 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, + 0x39, 0xf9, 0x47, 0x1e, 0xec, 0x0d, 0xb8, 0x07, 0x55, 0xbc, 0xbf, 0x6e, 0xd7, 0xa7, 0xc4, 0x53, 0x73, 0x06, 0xa9, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0xc0, 0x79, 0x0d, 0x4e, 0xd3, 0x15, 0x14, 0x9a, 0x46, 0xeb, 0x6d, + 0x81, 0xe0, 0xa8, 0x43, 0x02, 0x74, 0x53, 0x4b, 0x3a, 0x23, 0xf7, 0x6d, 0x16, 0x6f, 0x5d, 0x5a, 0xa9, 0x97, 0x54, 0x37, + 0xd0, 0x44, 0xd1, 0x9c, 0x15, 0x33, 0x05, 0xdb, 0x6b, 0xcb, 0x5c, 0xcd, 0x23, 0xc9, 0x65, 0x07, 0x79, 0x1b, 0x60, 0x2d, + 0xd6, 0x17, 0x2b, 0x45, 0x20, 0x8f, 0xb6, 0x31, 0x91, 0xc0, 0x59, 0x53, 0x87, 0xa0, 0x3c, 0xd1, 0x77, 0x97, 0x91, 0xd8, + 0x9c, 0xfc, 0x51, 0x4f, 0xfd, 0x21, 0x6a, 0x71, 0x12, 0x5a, 0x6e, 0x10, 0xd1, 0x5c, 0xe9, 0x7e, 0x24, 0xb8, 0xf3, 0x5d, + 0xab, 0x51, 0x2f, 0x67, 0xa7, 0x65, 0x5c, 0x27, 0xb8, 0xe2, 0x06, 0x98, 0xd2, 0x57, 0xb8, 0xc7, 0x4e, 0xea, 0x28, 0x23, + 0x6e, 0x90, 0x25, 0x2e, 0xb6, 0xf3, 0x5c, 0x18, 0xe8, 0x94, 0xa5, 0x7c, 0x55, 0xbf, 0x22, 0x94, 0xfc, 0x0e, 0xe7, 0x15, + 0xde, 0xe3, 0x72, 0x80, 0xe7, 0xf1, 0xfd, 0xd4, 0x0e, 0x2a, 0xda, 0x53, 0x56, 0xcb, 0xdb, 0xe3, 0x71, 0xc7, 0xc5, 0xd7, + 0x35, 0x95, 0x39, 0xf8, 0xee, 0x16, 0x22, 0x3c, 0x19, 0x3e, 0xd4, 0x03, 0x49, 0xe7, 0xf6, 0xb9, 0x50, 0x9f, 0x18, 0xee, + 0xdf, 0x7b, 0x79, 0xc4, 0x3f, 0xd4, 0x41, 0x45, 0xf2, 0xea, 0xdd, 0x5f, 0xda, 0x17, 0xd3, 0xb0, 0x50, 0xfc, 0x2c, 0xe9, + 0x6a, 0xb6, 0x35, 0xf3, 0xd7, 0xfd, 0xe6, 0x62, 0x51, 0x16, 0x5c, 0x8d, 0x26, 0xc3, 0x18, 0x9c, 0xf0, 0xb9, 0xe5, 0xa9, + 0x46, 0xd9, 0xe3, 0x80, 0x6c, 0xe3, 0x66, 0x70, 0xed, 0x4e, 0xfd, 0xf9, 0x8b, 0xdb, 0x06, 0x56, 0x3f, 0x2d, 0xfe, 0x74, + 0xee, 0x66, 0x75, 0x2a, 0xad, 0x1e, 0x41, 0x6c, 0x1b, 0x6a, 0xe4, 0x90, 0x76, 0x48, 0x27, 0x73, 0x4b, 0x13, 0xda, 0x72, + 0xa6, 0x7f, 0xc2, 0x7c, 0xb5, 0xca, 0x4c, 0x15, 0x64, 0x27, 0x9e, 0xc4, 0x9e, 0x3a, 0xb4, 0x13, 0x9d, 0xb8, 0x02, 0x3f, + 0x92, 0x6c, 0xe5, 0x73, 0x3e, 0x61, 0xbb, 0x01, 0xec, 0x81, 0x9b, 0x64, 0x59, 0x11, 0x4e, 0x42, 0x8b, 0x31, 0x97, 0x16, + 0x18, 0x53, 0x98, 0x82, 0x6e, 0xa5, 0x44, 0x7f, 0xcf, 0x05, 0x9c, 0x2c, 0x9d, 0x8f, 0xe3, 0x45, 0x57, 0xb2, 0xb5, 0x7a, + 0x71, 0x62, 0x25, 0x41, 0x8b, 0xed, 0xe9, 0x08, 0x46, 0x44, 0xda, 0xe3, 0xa3, 0xdf, 0x4b, 0x66, 0x77, 0x19, 0xc2, 0x4f, + 0xbb, 0xa7, 0xde, 0x4b, 0xa0, 0xbd, 0x95, 0x0f, 0xe1, 0x10, 0x49, 0x13, 0xa3, 0xec, 0x80, 0x27, 0xbb, 0x8b, 0xc8, 0xed, + 0x7a, 0x3a, 0x70, 0x5d, 0xea, 0x93, 0x6c, 0x0c, 0xc7, 0x2f, 0x41, 0x15, 0x64, 0x3d, 0x3a, 0x65, 0x02, 0x72, 0x78, 0xc9, + 0x35, 0x61, 0xe8, 0xd9, 0x63, 0x3f, 0x45, 0x7f, 0x04, 0xaf, 0x0b, 0x37, 0x7a, 0x66, 0x4e, 0x49, 0x3d, 0x6c, 0x3d, 0x2a, + 0xda, 0x0b, 0x81, 0x6d, 0x9f, 0x51, 0xea, 0xf6, 0x23, 0x6d, 0x7f, 0xcb, 0x75, 0x02, 0x49, 0x5e, 0x69, 0x57, 0x5b, 0x14, + 0xcb, 0xc2, 0xc8, 0xd4, 0xe4, 0x68, 0xab, 0xec, 0x51, 0x19, 0x80, 0xe4, 0xc1, 0xc7, 0x9b, 0x99, 0x15, 0xe1, 0x25, 0xf9, + 0x58, 0x18, 0x45, 0x0c, 0xde, 0xa7, 0x14, 0xe6, 0x96, 0xd5, 0xb8, 0x36, 0x83, 0x35, 0xfe, 0x77, 0x51, 0x4a, 0x57, 0x2e, + 0xaa, 0x26, 0x13, 0x23, 0x5d, 0x7d, 0xcf, 0x93, 0xce, 0x4a, 0x9a, 0xff, 0x03, 0x48, 0xf7, 0x10, 0x09, 0xe2, 0x01, 0xbb, + 0x17, 0xb6, 0x9d, 0xc7, 0x27, 0xe2, 0xd1, 0x26, 0xf1, 0x7c, 0xd0, 0x53, 0xf6, 0x53, 0x76, 0xfd, 0x39, 0x58, 0xd2, 0xc8, + 0xa8, 0x90, 0xa9, 0x75, 0x16, 0xaf, 0xe2, 0x91, 0x40, 0x53, 0x2e, 0x08, 0xdd, 0xb9, 0xfb, 0x17, 0x51, 0x51, 0x1b, 0xb9, + 0x12, 0xf0, 0x31, 0xd8, 0x48, 0x8f, 0x7d, 0x08, 0x9d, 0x1d, 0x2a, 0xb5, 0xcd, 0x46, 0x23, 0x2c, 0xf3, 0xb5, 0x11, 0x91, + 0x7f, 0x3c, 0x7a, 0x5e, 0x75, 0x90, 0x0e, 0xc0, 0xc0, 0x4f, 0x5e, 0xcb, 0xbc, 0x33, 0x09, 0x88, 0x4e, 0x68, 0xac, 0xba, + 0x46, 0x31, 0x41, 0x98, 0xf5, 0x75, 0x87, 0xf6, 0x0c, 0x0c, 0xaa, 0x84, 0x75, 0xe4, 0xfa, 0xa3, 0x1e, 0xe1, 0xe2, 0x88, + 0x09, 0xf0, 0x57, 0x8b, 0xdc, 0x47, 0x7b, 0xff, 0x39, 0xac, 0x51, 0x8b, 0x00, 0x08, 0xc0, 0x9f, 0xd4, 0xa4, 0xbe, 0xe5, + 0x41, 0x8b, 0xc5, 0x66, 0xdb, 0xed, 0x08, 0x0b, 0xdf, 0xa4, 0x2b, 0x5a, 0x59, 0xde, 0x0e, 0x9c, 0x8b, 0x7f, 0xd1, 0x80, + 0x4d, 0xf9, 0x22, 0x60, 0x2c, 0xd4, 0xf9, 0x1c, 0xd7, 0xf5, 0xbd, 0x64, 0x7f, 0x4f, 0xeb, 0xf8, 0xa5, 0xb2, 0x34, 0x3d, + 0xfa, 0x07, 0xef, 0x44, 0x3c, 0x00, 0x2c, 0xec, 0x36, 0x36, 0xdd, 0xd5, 0x5c, 0xbd, 0x6b, 0x27, 0xba, 0x13, 0x91, 0x90, + 0x58, 0xe7, 0x75, 0x89, 0x00, 0x6b, 0x5a, 0x0c, 0x35, 0x9c, 0xe3, 0x8a, 0xd8, 0x46, 0xd2, 0x15, 0x14, 0x8b, 0x8b, 0xff, + 0x6a, 0x35, 0xf9, 0xd7, 0x65, 0x67, 0x56, 0x6d, 0xd5, 0x2d, 0x9c, 0xd6, 0xb1, 0xe2, 0x9a, 0xb0, 0xfa, 0x0e, 0xa2, 0xd5, + 0x5d, 0x30, 0x15, 0x8e, 0x48, 0x59, 0xd0, 0x13, 0xa7, 0x2b, 0x40, 0x97, 0x8c, 0xe4, 0x02, 0x38, 0x28, 0x54, 0x53, 0x6c, + 0x1c, 0xc7, 0x38, 0x06, 0xe9, 0xfc, 0x2d, 0xd5, 0x59, 0x74, 0x77, 0x62, 0x14, 0xf2, 0xa7, 0x7e, 0xfe, 0x59, 0xbf, 0xdf, + 0x8b, 0x6e, 0xd7, 0x66, 0xd1, 0x6a, 0xb9, 0xe6, 0x35, 0x98, 0xc6, 0x76, 0x44, 0x38, 0xb4, 0xe8, 0x3c, 0xf5, 0x3c, 0x27, + 0xb9, 0xa1, 0x21, 0x7d, 0x17, 0xf9, 0xb3, 0x1e, 0x30, 0xe7, 0xab, 0xd5, 0x2d, 0x8c, 0x02, 0xc3, 0xa4, 0x3c, 0xf4, 0x09, + 0x9f, 0x17, 0xc1, 0xce, 0xc9, 0xf5, 0xdf, 0xdb, 0x8b, 0xf5, 0x05, 0x14, 0x6d, 0x74, 0xdf, 0xa9, 0x0b, 0x87, 0x98, 0x17, + 0xf3, 0x68, 0x8d, 0xb3, 0xbc, 0x86, 0x3a, 0x47, 0x1d, 0x29, 0x80, 0x40, 0xba, 0xb0, 0x3d, 0x65, 0x0d, 0xd7, 0x95, 0x4a, + 0x79, 0x0d, 0x34, 0x20, 0x72, 0x25, 0xaa, 0x71, 0x43, 0x5c, 0x52, 0x0b, 0x69, 0xde, 0xf7, 0xc5, 0xfd, 0xdb, 0x41, 0x05, + 0xb1, 0xde, 0x94, 0xdb, 0xc4, 0xe4, 0x85, 0xf2, 0x6c, 0xc5, 0xd1, 0x04, 0xcd, 0xd7, 0x84, 0x0b, 0xd8, 0xa8, 0x2c, 0x68, + 0xfd, 0xe7, 0x30, 0xaf, 0x6e, 0xae, 0x02, 0x3f, 0xea, 0x13, 0x68, 0xb0, 0xd1, 0xef, 0x6d, 0x78, 0xf8, 0x77, 0x3e, 0xe8, + 0x03, 0x05, 0x6e, 0x00, 0x59, 0xf1, 0xde, 0x57, 0xbe, 0xfa, 0x6b, 0xde, 0x47, 0x86, 0x21, 0xa0, 0x8e, 0xcc, 0x0b, 0x15, + 0x7e, 0x7d, 0xd2, 0x59, 0x37, 0x7f, 0x74, 0xc5, 0x79, 0x8e, 0xf0, 0x37, 0x9b, 0xb3, 0x0e, 0x7f, 0x14, 0x91, 0x0e, 0xe5, + 0xe8, 0xdf, 0xf7, 0xdf, 0x6b, 0x59, 0x79, 0x37, 0x90, 0x99, 0xc8, 0xff, 0xb2, 0xe9, 0xe4, 0x35, 0x8c, 0x20, 0xde, 0x8c, + 0x6c, 0xb8, 0x87, 0x16, 0xdd, 0xc4, 0x4b, 0x5e, 0x93, 0x38, 0x06, 0x0f, 0x4a, 0xb0, 0xba, 0xe1, 0xc5, 0xb1, 0x5d, 0x5f, + 0x3a, 0x2e, 0x84, 0x56, 0x72, 0x13, 0xb2, 0xb4, 0xdf, 0xc0, 0x36, 0xe6, 0xf2, 0xee, 0x77, 0x93, 0xc1, 0xc7, 0xc5, 0xe5, + 0x58, 0x66, 0x3e, 0x8c, 0x5d, 0xe3, 0x5d, 0xbd, 0x43, 0xf6, 0x72, 0x51, 0xe7, 0x4c, 0xd4, 0x2f, 0x46, 0x12, 0x66, 0xc2, + 0x7a, 0xd4, 0xd9, 0x75, 0x25, 0xa5, 0x63, 0x60, 0x9c, 0xc4, 0xff, 0x0a, 0xec, 0x8d, 0x13, 0x22, 0x3e, 0x95, 0xe8, 0xd9, + 0xd4, 0xa4, 0x12, 0xba, 0x46, 0x93, 0x1f, 0x6b, 0x9f, 0xb2, 0xba, 0xca, 0x39, 0xda, 0x32, 0xe5, 0x5c, 0xb3, 0x86, 0xc9, + 0x86, 0xb9, 0x9c, 0x92, 0x72, 0xe4, 0xa7, 0x53, 0xe4, 0x39, 0x07, 0x96, 0xc6, 0x18, 0xbc, 0xfc, 0x2e, 0x5f, 0xd6, 0x15, + 0x2c, 0x73, 0x01, 0x05, 0x74, 0xd7, 0x9a, 0x34, 0x35, 0x56, 0x32, 0xb7, 0x50, 0x22, 0x76, 0x66, 0x4d, 0x6f, 0xd1, 0x19, + 0x6a, 0x79, 0xc1, 0x3f, 0x15, 0x21, 0x04, 0x14, 0x34, 0xc9, 0x9a, 0xdb, 0x25, 0x0d, 0xfb, 0xa9, 0x53, 0xc0, 0x5f, 0xac, + 0xb7, 0xec, 0x67, 0xac, 0x8e, 0x46, 0x4c, 0xd7, 0x1b, 0x9b, 0x25, 0x87, 0x97, 0x73, 0xd9, 0xc8, 0xb3, 0x65, 0x22, 0x3b, + 0x35, 0xc0, 0x2f, 0xf5, 0x7d, 0xa4, 0x9b, 0x79, 0x92, 0xfb, 0xb6, 0x0b, 0xc9, 0xf9, 0x88, 0xc5, 0x5b, 0x88, 0x21, 0x0d, + 0xcf, 0xd9, 0x83, 0x6d, 0xae, 0x58, 0x3f, 0xac, 0x88, 0x16, 0xae, 0x3f, 0xb5, 0xdb, 0x78, 0x1c, 0x03, 0x3a, 0x19, 0xf1, + 0xbe, 0xc6, 0x46, 0x12, 0x6b, 0x18, 0x0b, 0x70, 0x83, 0x2d, 0x2f, 0x16, 0xac, 0xa9, 0x31, 0x2d, 0xf3, 0xe5, 0xd7, 0xe1, + 0x0e, 0x0e, 0x23, 0xb3, 0x9e, 0xc5, 0x6e, 0x35, 0xb7, 0xc4, 0x7f, 0xac, 0x60, 0x92, 0xde, 0x73, 0x3b, 0x02, 0xb6, 0xf5, + 0x97, 0xe6, 0xe1, 0x55, 0x50, 0x72, 0xd2, 0xb4, 0xbd, 0xcd, 0x7e, 0x11, 0xe4, 0x7b, 0x4b, 0xa5, 0x6b, 0x7e, 0xbf, 0xb8, + 0x4a, 0x1f, 0xf6, 0x34, 0x29, 0xee, 0x28, 0xb0, 0x45, 0x7d, 0x48, 0xc2, 0x18, 0xb2, 0x15, 0x0c, 0xe5, 0x5a, 0x3e, 0xee, + 0xdd, 0x1f, 0x20, 0x7b, 0xe6, 0x79, 0x60, 0xee, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, 0x29, 0x26, 0x07, 0x8d, + 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x08, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x49, 0x00, 0x00, 0x09, 0x4d, 0x00, 0x00, 0x09, 0x61, + 0x00, 0x00, 0x09, 0x65, 0x00, 0x00, 0x09, 0x69, 0x00, 0x00, 0x09, 0x6d, 0x00, 0x00, 0x09, 0x71, 0x00, 0x00, 0x09, 0x89, + 0x00, 0x00, 0x09, 0x8d, 0x00, 0x00, 0x09, 0xb9, 0x00, 0x00, 0x09, 0xbd, 0x00, 0x00, 0x09, 0xc1, 0x00, 0x00, 0x09, 0xc5, + 0x00, 0x00, 0x09, 0xd1, 0x00, 0x00, 0x09, 0xdd, 0x00, 0x00, 0x09, 0xe1, 0x00, 0x00, 0x09, 0xe5, 0x00, 0x00, 0x09, 0xe9, + 0x00, 0x00, 0x09, 0xed, 0x00, 0x00, 0x09, 0xf1, 0x00, 0x00, 0x09, 0xf5, 0x00, 0x00, 0x09, 0xf9, 0x00, 0x00, 0x09, 0xfd, + 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x0a, 0x05, 0x00, 0x00, 0x0a, 0x09, 0x00, 0x00, 0x0a, 0x0d, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x08, 0xc4, 0x7a, 0x50, 0x55, 0x75, 0xed, 0x3d, 0xfc, 0x68, + 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0xb4, 0x4e, 0xa3, 0xa8, 0x86, 0x4f, 0x76, 0xe9, + 0x0f, 0x06, 0x2d, 0xca, 0x91, 0x26, 0x8e, 0x86, 0x1a, 0x1f, 0xb9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0xf7, 0xc4, 0x67, 0x03, 0x4c, 0xab, 0x35, 0xae, + 0x20, 0x64, 0x45, 0xf0, 0xe3, 0x48, 0xbc, 0xba, 0x5f, 0xac, 0x81, 0xda, 0x00, 0x00, 0x00, 0x74, 0x2f, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2f, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x73, 0x73, + 0x69, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x2e, 0x61, 0x70, 0x70, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, + 0x69, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x14, 0xf7, 0xc4, 0x67, 0x03, 0x4c, 0xab, 0x35, 0xae, 0x20, 0x64, 0x45, 0xf0, 0xe3, 0x48, 0xbc, 0xba, + 0x5f, 0xac, 0x81, 0xda, 0x00, 0x00, 0x00, 0x74, 0x2f, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x4c, 0x69, 0x62, 0x72, + 0x61, 0x72, 0x79, 0x2f, 0x43, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x2e, 0x61, + 0x70, 0x70, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x10, 0x49, 0xe1, 0x42, + 0x39, 0xee, 0xe2, 0xbd, 0x76, 0x61, 0x00, 0x6f, 0xe5, 0xf4, 0xbe, 0xdb, 0xbc, 0x89, 0xbe, 0x56, 0x00, 0x00, 0x00, 0x44, + 0x2f, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x4d, 0x61, 0x69, 0x6c, 0x2e, 0x61, + 0x70, 0x70, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6d, 0x61, + 0x69, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, + 0x55, 0x29, 0x46, 0xa2, 0xfb, 0x92, 0xda, 0xe4, 0xf8, 0x4c, 0x7d, 0xdd, 0xc3, 0x4e, 0x52, 0x62, 0xff, 0x0f, 0xd2, 0x04, + 0x00, 0x00, 0x00, 0x40, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x73, 0x62, 0x69, 0x6e, 0x2f, 0x72, 0x61, 0x63, 0x6f, 0x6f, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x72, 0x61, + 0x63, 0x6f, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x5c, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1d, + 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x72, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x84, 0x5f, 0xda, 0x57, 0x4e, 0xc0, 0xb5, 0x32, 0xdf, 0xc4, 0x87, 0x7f, 0x8c, 0x04, 0x1f, 0x65, 0xa2, 0x23, 0x20, 0x8c, + 0xab, 0x49, 0x2f, 0xff, 0x12, 0xfa, 0x57, 0x33, 0xf8, 0xcb, 0x7a, 0xcd, 0xc4, 0x7b, 0xc0, 0xf6, 0xf7, 0xe7, 0x2f, 0x7d, + 0x3f, 0xec, 0xf5, 0x8a, 0xee, 0x1e, 0x26, 0xe9, 0x12, 0x96, 0xdb, 0xa2, 0x2a, 0xf6, 0xb9, 0x3c, 0x68, 0x14, 0x49, 0x86, + 0x00, 0xc0, 0xaa, 0x29, 0xd3, 0xad, 0x4b, 0x48, 0xca, 0x48, 0x3f, 0xdb, 0x36, 0xdd, 0x3d, 0x3b, 0x18, 0x59, 0x26, 0x2a, + 0x9e, 0x5f, 0x86, 0xe9, 0x4b, 0xaa, 0x83, 0x60, 0x20, 0x36, 0x1e, 0x59, 0x17, 0x33, 0x5b, 0x20, 0x42, 0x7a, 0x59, 0xfd, + 0xb3, 0xa2, 0x5f, 0x2b, 0xdb, 0x63, 0x7e, 0x66, 0xee, 0x5e, 0xf5, 0x22, 0x0c, 0x10, 0x61, 0xd3, 0x9e, 0x3d, 0xce, 0x62, + 0x6b, 0xc3, 0x97, 0x86, 0x68, 0x61, 0x2a, 0x31, 0xaa, 0x7d, 0x5d, 0x18, 0x1f, 0xe9, 0xc3, 0x12, 0xb7, 0x0d, 0x14, 0x84, + 0x5c, 0xa0, 0x84, 0x0c, 0x07, 0xef, 0x01, 0xf4, 0xd3, 0xa1, 0x14, 0xa8, 0x5a, 0xb8, 0x15, 0xb7, 0x1b, 0x7a, 0x4a, 0x12, + 0x2f, 0x9d, 0x8f, 0x79, 0xb1, 0x74, 0x3e, 0x50, 0xd5, 0x99, 0x9c, 0x26, 0x7d, 0x37, 0xaf, 0xc7, 0x7b, 0x15, 0x8c, 0x07, + 0xae, 0x74, 0xef, 0xc3, 0xb1, 0x6a, 0xa2, 0x76, 0xf9, 0x6d, 0x6e, 0xc2, 0x6a, 0x01, 0x9a, 0x5f, 0x23, 0xf4, 0xd5, 0xe3, + 0x6a, 0x34, 0x86, 0x1e, 0x9d, 0xed, 0x5c, 0x09, 0xd3, 0xba, 0xff, 0x2d, 0xbe, 0x4b, 0xbb, 0x6c, 0x6a, 0x20, 0xc9, 0x8b, + 0x51, 0xcd, 0x4c, 0x91, 0x51, 0x6d, 0xf5, 0x80, 0x42, 0x31, 0xc1, 0x3a, 0x10, 0xdc, 0xb4, 0x92, 0x97, 0x18, 0xcc, 0x26, + 0xf1, 0xe6, 0x18, 0xe1, 0x97, 0x21, 0x94, 0x3d, 0xca, 0xa7, 0xb5, 0xcd, 0xce, 0x53, 0x7b, 0x16, 0x0b, 0x80, 0x8d, 0x4c, + 0xc8, 0x28, 0xc8, 0x55, 0xcf, 0xc7, 0xba, 0xd1, 0x05, 0x6a, 0x66, 0x72, 0x51, 0xb2, 0xd4, 0x3d, 0x81, 0x8d, 0xc5, 0xb3, + 0x86, 0xa6, 0x02, 0x53, 0x16, 0x2a, 0x2a, 0x40, 0xf1, 0x8d, 0xff, 0x42, 0x9a, 0x12, 0xd2, 0x46, 0x1d, 0x42, 0x98, 0x1f, + 0x1c, 0x52, 0x3f, 0x11, 0xa7, 0x12, 0xa7, 0xba, 0xb7, 0x84, 0xba, 0x80, 0xdf, 0x3e, 0x89, 0xcd, 0x81, 0x05, 0x98, 0x0a, + 0x92, 0x3e, 0x4b, 0x61, 0x44, 0x2f, 0xb8, 0xfe, 0x86, 0x56, 0x6b, 0xe1, 0xc0, 0xb4, 0x09, 0x52, 0x6c, 0xb2, 0xff, 0x1f, + 0xe7, 0x74, 0x98, 0xb6, 0x65, 0x47, 0x31, 0x5a, 0x33, 0x3a, 0x8c, 0x05, 0x18, 0xa5, 0x25, 0xc6, 0xb7, 0x18, 0x29, 0xf9, + 0x87, 0x7c, 0x3c, 0x3d, 0x70, 0x56, 0x60, 0xfe, 0x0c, 0xb9, 0x17, 0x89, 0xa0, 0x72, 0xe6, 0xa5, 0x2f, 0xa6, 0xa9, 0xc4, + 0x34, 0x5a, 0xbe, 0x0d, 0xa5, 0xf3, 0xac, 0xe8, 0x69, 0xa8, 0x2e, 0x50, 0xa2, 0xc1, 0x99, 0x7e, 0x7c, 0xd2, 0xd7, 0x60, + 0x1b, 0x41, 0xe4, 0x1f, 0x76, 0x5c, 0xeb, 0x1b, 0x28, 0x53, 0xd3, 0xab, 0x48, 0xd0, 0x7f, 0xb8, 0x9d, 0x70, 0x39, 0x8a, + 0xcd, 0x3c, 0x0f, 0x03, 0x5e, 0xe8, 0xa9, 0x95, 0x60, 0x54, 0x93, 0xfa, 0xd1, 0x9b, 0x49, 0xdb, 0x34, 0x32, 0x36, 0x38, + 0x56, 0xbb, 0xbf, 0xcf, 0x54, 0xe6, 0x5c, 0xa2, 0x8a, 0x9e, 0x73, 0x83, 0xa0, 0x53, 0x71, 0xfd, 0xef, 0x49, 0x1a, 0xa7, + 0x06, 0xca, 0x90, 0xd5, 0x2f, 0x31, 0xb4, 0x52, 0x0f, 0xaf, 0xfe, 0x6c, 0x19, 0x6d, 0xca, 0x11, 0xaa, 0xaf, 0x24, 0x21, + 0x47, 0x7f, 0x15, 0x47, 0x51, 0x96, 0x59, 0x3b, 0x27, 0x13, 0xc6, 0x50, 0x7b, 0x1c, 0x84, 0x0d, 0x61, 0x3d, 0x51, 0x58, + 0x9c, 0xe4, 0x65, 0x06, 0x1f, 0x7b, 0x91, 0x98, 0x7d, 0x35, 0x8c, 0x9f, 0xba, 0x38, 0x90, 0x89, 0xa2, 0xae, 0x68, 0x68, + 0x4b, 0x11, 0x2f, 0xea, 0x4d, 0xcb, 0x01, 0x59, 0x94, 0x26, 0x52, 0x37, 0x01, 0x6e, 0xfb, 0x01, 0x8b, 0x61, 0x59, 0x5b, + 0x49, 0xdf, 0xf2, 0x1c, 0x48, 0xbc, 0xed, 0x98, 0x8f, 0x09, 0x38, 0xa2, 0xf8, 0x27, 0xbb, 0x1a, 0x04, 0xcf, 0xd0, 0x4a, + 0x93, 0x32, 0xb8, 0x9d, 0x2f, 0x9c, 0xf3, 0xb2, 0xa8, 0x56, 0x47, 0xff, 0xa1, 0x28, 0x60, 0x6b, 0xc2, 0x3c, 0x1b, 0x48, + 0x5d, 0xc9, 0x05, 0x39, 0x98, 0xe5, 0x98, 0xfb, 0x17, 0x3f, 0x6d, 0x41, 0x8d, 0xc5, 0xa1, 0xee, 0x31, 0x19, 0x00, 0x2d, + 0xfb, 0x1e, 0x8f, 0x5f, 0x72, 0x6a, 0x92, 0x64, 0x01, 0xad, 0xcc, 0x90, 0x14, 0x48, 0x83, 0x88, 0x2e, 0xc1, 0x58, 0xe5, + 0x33, 0xa4, 0x19, 0xc3, 0x1d, 0xee, 0x06, 0xb6, 0x96, 0xb7, 0x57, 0x04, 0xa5, 0x4a, 0xa0, 0xa5, 0x1b, 0xa5, 0xda, 0x91, + 0xb7, 0x2c, 0xcd, 0x6d, 0x81, 0xff, 0x9f, 0xac, 0xc9, 0x05, 0x26, 0x8f, 0xb2, 0x37, 0x3c, 0xb8, 0x53, 0xab, 0x2b, 0xaf, + 0x9e, 0x22, 0xd2, 0xcd, 0xf4, 0x65, 0xf3, 0x84, 0x68, 0x83, 0xc2, 0xf8, 0xb7, 0x05, 0x25, 0xfe, 0x08, 0x2c, 0xb2, 0xb4, + 0xf3, 0x95, 0x63, 0x9a, 0xcc, 0x9d, 0xb1, 0xee, 0x5c, 0x53, 0x3b, 0x6b, 0xab, 0x0e, 0x95, 0x50, 0xcc, 0x8e, 0xc3, 0x97, + 0x43, 0x67, 0xe5, 0x49, 0xd0, 0x20, 0xbd, 0xda, 0x45, 0x6c, 0xef, 0x9a, 0xc7, 0x47, 0xdc, 0x7f, 0xda, 0xab, 0xf2, 0x8a, + 0xc5, 0x4f, 0xc5, 0xdb, 0xba, 0x87, 0x5f, 0xc1, 0xe0, 0x12, 0xc0, 0xb1, 0x3e, 0x1b, 0x72, 0x34, 0x00, 0x9f, 0x0a, 0xb4, + 0x99, 0xf8, 0x33, 0xe7, 0xb7, 0xc6, 0xc0, 0xed, 0xe6, 0x2c, 0x1b, 0x29, 0x9c, 0xfd, 0xeb, 0x6f, 0x9b, 0x0a, 0x55, 0xd2, + 0x09, 0xa2, 0x64, 0x49, 0x39, 0x30, 0x33, 0xb2, 0x77, 0x31, 0x32, 0x81, 0x25, 0x58, 0x66, 0x4d, 0xd2, 0xc2, 0xa6, 0x18, + 0xdc, 0xfc, 0x0a, 0x73, 0x5f, 0xbc, 0xcc, 0xef, 0xfe, 0xee, 0x1d, 0x3d, 0xb8, 0x21, 0xfb, 0x52, 0x25, 0x6f, 0xc3, 0x99, + 0x67, 0xa1, 0x69, 0x20, 0xb3, 0x01, 0xb4, 0x75, 0xbe, 0x08, 0x49, 0x2e, 0xe3, 0x6f, 0x1a, 0xd0, 0xe9, 0x7c, 0xec, 0xbf, + 0x98, 0x45, 0x82, 0xf8, 0xc4, 0x77, 0x74, 0x20, 0xc9, 0x5f, 0xa1, 0x8b, 0xf4, 0xa8, 0x4d, 0x12, 0xd5, 0x92, 0xd1, 0xe1, + 0x42, 0x4b, 0xa2, 0x45, 0x18, 0x60, 0xaf, 0x9a, 0xf2, 0xe4, 0xcf, 0x3e, 0x66, 0x87, 0x12, 0x0e, 0xa7, 0x55, 0x53, 0x96, + 0xcb, 0xcf, 0xd3, 0x34, 0xab, 0xdd, 0x20, 0x0f, 0x62, 0x9a, 0xb4, 0x86, 0x2f, 0x9f, 0x01, 0xda, 0xd6, 0xe6, 0x2b, 0xe2, + 0x5b, 0xb9, 0x74, 0xd8, 0x28, 0xad, 0x94, 0x89, 0x3e, 0x3a, 0x2a, 0x82, 0xa2, 0x0a, 0x7b, 0x4b, 0x4f, 0x3f, 0xed, 0x7f, + 0x2a, 0x3a, 0x06, 0xc8, 0xd4, 0x65, 0xcd, 0x60, 0x19, 0x79, 0x36, 0x31, 0x4c, 0xc1, 0x1e, 0x55, 0x22, 0x4f, 0x6e, 0xe0, + 0x1b, 0xab, 0x0b, 0x49, 0xa8, 0x9f, 0xf9, 0xc9, 0x6c, 0xd4, 0xd6, 0xfa, 0x07, 0xcd, 0xf5, 0xe7, 0x94, 0x51, 0x1b, 0x3d, + 0xc5, 0x00, 0x79, 0x38, 0xaf, 0xc0, 0x23, 0x60, 0x2b, 0x92, 0xda, 0x76, 0x69, 0xf7, 0xda, 0x23, 0xf9, 0xa6, 0x21, 0x34, + 0xc6, 0xf3, 0xc3, 0x69, 0xa6, 0x25, 0x87, 0x70, 0x5c, 0x0c, 0xc1, 0xfc, 0x9c, 0x30, 0xbc, 0xdf, 0x26, 0xbe, 0x4b, 0x49, + 0x44, 0xdd, 0x2f, 0x21, 0xc1, 0xa8, 0xcd, 0x54, 0x7a, 0xa4, 0x1b, 0xae, 0x82, 0xce, 0x05, 0x50, 0x9c, 0xb6, 0x85, 0x5d, + 0xf9, 0xbd, 0xdd, 0x4a, 0x56, 0x51, 0x32, 0x50, 0xdd, 0xaa, 0x55, 0xfe, 0x26, 0x3c, 0xee, 0x36, 0xa4, 0xa8, 0x53, 0x66, + 0x72, 0x89, 0xf6, 0xa3, 0x25, 0x7a, 0x23, 0x53, 0x29, 0x4d, 0x34, 0x29, 0x62, 0x94, 0x4f, 0x4f, 0x1b, 0x53, 0xcb, 0xc1, + 0x7c, 0xd1, 0x50, 0x8e, 0xa3, 0x19, 0x89, 0xfa, 0x90, 0x42, 0x69, 0x16, 0xd0, 0x6f, 0xf8, 0x7a, 0xc2, 0x9e, 0x67, 0xe8, + 0xe8, 0xff, 0xf1, 0x61, 0x7b, 0x31, 0x19, 0xcf, 0xf1, 0x27, 0xee, 0xab, 0x63, 0xe8, 0xdb, 0xf7, 0x4c, 0xbf, 0xcf, 0x2f, + 0xe7, 0x83, 0x92, 0xf8, 0x6d, 0x15, 0x9e, 0x1d, 0x77, 0xef, 0x40, 0x79, 0x58, 0xe4, 0xf9, 0xa7, 0x3d, 0xb6, 0x2d, 0xd0, + 0xfc, 0x01, 0x66, 0x20, 0x2c, 0xd1, 0x29, 0x86, 0x9b, 0x88, 0xcd, 0x98, 0xb4, 0x66, 0x61, 0x94, 0x58, 0x56, 0xf4, 0xff, + 0x60, 0x90, 0xf2, 0x8c, 0x07, 0x1c, 0x0b, 0x13, 0xfe, 0xb6, 0x58, 0x15, 0x6a, 0x8a, 0xd7, 0x98, 0xb2, 0x3e, 0xee, 0x49, + 0xdb, 0x3a, 0x0f, 0x98, 0x27, 0xc6, 0x88, 0xc5, 0x15, 0xe5, 0x67, 0x08, 0x09, 0xfc, 0x63, 0x6c, 0x8f, 0x30, 0xf4, 0x95, + 0xb7, 0x69, 0xd4, 0x47, 0x93, 0xe5, 0xa6, 0xf9, 0x73, 0xdd, 0x98, 0xb4, 0x66, 0x02, 0x1f, 0x3b, 0xe7, 0x53, 0x9f, 0x54, + 0x44, 0x0b, 0x9b, 0xdb, 0xe8, 0xaa, 0x77, 0xc3, 0x89, 0x65, 0x12, 0xb2, 0xc5, 0x2f, 0x5e, 0xaa, 0xff, 0xab, 0x72, 0x1f, + 0xf1, 0xd3, 0xdc, 0x8f, 0xaf, 0x13, 0x31, 0xaa, 0x5d, 0x48, 0x5a, 0x1b, 0x31, 0x61, 0x0b, 0x48, 0x9b, 0xe6, 0x75, 0x2e, + 0xd5, 0xdb, 0xd3, 0x22, 0xb5, 0x77, 0x9b, 0x45, 0xc2, 0x9d, 0x1b, 0xe2, 0x2b, 0x8c, 0x14, 0x99, 0x10, 0x7c, 0x24, 0x18, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, + 0x20, 0x1e, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, + 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, + 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x03, 0xb0, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x11, 0x2c, 0x00, 0x00, 0x12, 0x50, 0x00, 0x00, 0x12, 0xb0, + 0x00, 0x00, 0x12, 0xe8, 0x00, 0x00, 0x13, 0x20, 0x00, 0x00, 0x13, 0x58, 0x00, 0x00, 0x13, 0x90, 0x00, 0x00, 0x13, 0xc8, + 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x38, 0x00, 0x00, 0x14, 0x70, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x11, 0x70, 0x00, 0x00, 0x11, 0xe0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, 0x02, 0x33, 0x38, 0xb5, + 0x23, 0xb6, 0xef, 0x97, 0x20, 0x1e, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, + 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, 0x29, 0x26, 0x07, 0x8d, 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x12, 0x78, 0x00, 0x00, 0x12, 0x94, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, + 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, 0x20, 0x1e, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, + 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, 0x29, 0x26, 0x07, 0x8d, 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x12, 0xd8, 0x00, 0x00, 0x12, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x13, 0x10, 0x00, 0x00, 0x13, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0x48, + 0x00, 0x00, 0x13, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0x80, 0x00, 0x00, 0x13, 0x88, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0xb8, 0x00, 0x00, 0x13, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x13, 0xf0, 0x00, 0x00, 0x13, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x14, 0x28, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0x60, + 0x00, 0x00, 0x14, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0x98, 0x00, 0x00, 0x14, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0xbc, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x15, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0xf8, + 0x00, 0x00, 0x05, 0xe4, 0x00, 0x00, 0x08, 0xa4, 0x00, 0x00, 0x0e, 0xfc, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0xe4, + 0x00, 0x00, 0x02, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf5, 0x00, 0x00, 0x01, 0xf9, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x02, 0x15, + 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x02, 0x3d, + 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x02, 0x6d, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x02, 0x81, + 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x02, 0x9d, + 0x00, 0x00, 0x02, 0xa1, 0x00, 0x00, 0x02, 0xa5, 0x00, 0x00, 0x02, 0xa9, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb1, + 0x00, 0x00, 0x02, 0xb5, 0x00, 0x00, 0x02, 0xb9, 0x00, 0x00, 0x02, 0xbd, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x70, 0xea, 0x6d, 0x4d, 0x2b, 0x42, 0xd6, 0x1d, 0xa7, 0x00, 0x00, 0x00, 0x02, + 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x59, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x59, 0x1b, 0x38, 0x6f, 0x83, 0xff, 0xcf, 0x13, 0x00, 0xc5, 0x58, 0x14, + 0x81, 0x60, 0xd5, 0xf2, 0x76, 0x2d, 0x7b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, + 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0xe5, 0x1f, 0x40, 0x4b, 0xde, 0x16, 0xe0, 0x41, + 0xc5, 0xdc, 0x68, 0x83, 0xfb, 0x0f, 0x7b, 0xad, 0x62, 0x9d, 0xa3, 0xee, 0xea, 0xa9, 0x6b, 0x27, 0x69, 0x1e, 0xea, 0xc7, + 0x1c, 0xf7, 0x06, 0xa5, 0x76, 0xcd, 0x9d, 0x65, 0x3c, 0xb1, 0x30, 0x6a, 0x30, 0xd1, 0x31, 0xbd, 0x8a, 0x19, 0x90, 0x89, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xce, 0x31, 0x50, 0xc1, 0x8c, 0xde, 0x4b, 0xa0, + 0xca, 0xfd, 0x36, 0x98, 0x33, 0x59, 0x99, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xce, 0x31, 0x50, 0xc1, 0x8c, 0xde, 0x4b, 0xa0, + 0xca, 0xfd, 0x36, 0x98, 0x33, 0x59, 0x99, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xec, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x01, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x02, 0x3d, + 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x02, 0x65, + 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x02, 0x9d, 0x00, 0x00, 0x02, 0xa1, + 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb9, 0x00, 0x00, 0x02, 0xbd, 0x00, 0x00, 0x02, 0xc1, 0x00, 0x00, 0x02, 0xc5, + 0x00, 0x00, 0x02, 0xc9, 0x00, 0x00, 0x02, 0xcd, 0x00, 0x00, 0x02, 0xd1, 0x00, 0x00, 0x02, 0xd5, 0x00, 0x00, 0x02, 0xd9, + 0x00, 0x00, 0x02, 0xdd, 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0x00, 0x00, 0x02, 0xe9, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x9c, 0x8b, 0x41, 0x4a, 0x57, 0xa6, 0xf2, 0x36, 0xc2, + 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x9a, 0xfe, 0xce, 0x76, 0xf7, 0x40, 0x3a, 0x9f, + 0xd2, 0xc5, 0x69, 0x65, 0x60, 0xea, 0x1a, 0x98, 0xc7, 0xed, 0x28, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, + 0x00, 0x00, 0x0c, 0x00, 0x00, 0x5a, 0x4c, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, + 0x83, 0x67, 0xc1, 0x00, 0xdf, 0x03, 0x66, 0xb0, 0xbb, 0x20, 0xb3, 0x39, 0x84, 0xf0, 0x07, 0xc3, 0x17, 0x75, 0x8a, 0x1b, + 0xce, 0x2a, 0xb7, 0xc3, 0x31, 0xd7, 0xea, 0xba, 0xa4, 0x38, 0xf5, 0x78, 0x94, 0xa5, 0xff, 0x08, 0x6d, 0x36, 0x41, 0xa5, + 0x8d, 0x6e, 0xf7, 0x55, 0x1f, 0x6f, 0xe9, 0x3c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0x66, 0x4e, 0xf9, 0x51, 0xc5, 0xeb, 0x28, 0x0b, 0xca, 0x0c, 0x15, 0x2f, 0x22, 0x80, 0x18, 0x7b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0x66, 0x4e, 0xf9, 0x51, 0xc5, 0xeb, 0x28, 0x0b, 0xca, 0x0c, 0x15, 0x2f, 0x22, 0x80, 0x18, 0x7b, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, + 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, + 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf5, + 0x00, 0x00, 0x01, 0xf9, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x02, 0x1d, + 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x02, 0x6d, + 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x02, 0x81, 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x02, 0x91, + 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x02, 0x9d, 0x00, 0x00, 0x02, 0xa1, 0x00, 0x00, 0x02, 0xa5, + 0x00, 0x00, 0x02, 0xa9, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb1, 0x00, 0x00, 0x02, 0xb5, 0x00, 0x00, 0x02, 0xb9, + 0x00, 0x00, 0x02, 0xbd, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x70, + 0x44, 0x1d, 0x55, 0x6f, 0xda, 0x1b, 0x4a, 0x43, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, + 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, + 0x23, 0x07, 0xb7, 0x3f, 0xb3, 0x23, 0xad, 0xb2, 0xa9, 0x7f, 0x10, 0x8b, 0x76, 0x89, 0x68, 0x1b, 0x42, 0xb4, 0x45, 0x98, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, + 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xc5, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x23, 0xe5, 0x14, 0x64, 0x77, 0x35, 0x5f, 0x79, 0x3e, 0x4c, 0x4d, 0x5e, 0xee, 0xa7, 0x26, 0x39, 0x7d, + 0x28, 0x18, 0xd5, 0xf5, 0x08, 0x07, 0x99, 0x37, 0xb1, 0xea, 0x83, 0x7c, 0xbc, 0xeb, 0x64, 0x47, 0xc6, 0xe1, 0x82, 0xfe, + 0x1f, 0x20, 0x67, 0x1e, 0x37, 0x92, 0x57, 0xaa, 0xbe, 0x4f, 0xac, 0x5f, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0xea, 0xa1, 0xad, 0x3e, 0x49, 0xa8, 0x35, 0x7b, 0xce, 0x5d, 0x8c, 0xd6, 0xdf, 0x25, 0xe4, 0x2d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0xea, 0xa1, 0xad, 0x3e, 0x49, 0xa8, 0x35, 0x7b, 0xce, 0x5d, 0x8c, 0xd6, 0xdf, 0x25, 0xe4, 0x2d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5c, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb1, 0x00, 0x00, 0x02, 0xb5, + 0x00, 0x00, 0x02, 0xb9, 0x00, 0x00, 0x02, 0xbd, 0x00, 0x00, 0x02, 0xd5, 0x00, 0x00, 0x02, 0xd9, 0x00, 0x00, 0x03, 0x05, + 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x03, 0x0d, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x03, 0x29, + 0x00, 0x00, 0x03, 0x2d, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x03, 0x39, 0x00, 0x00, 0x03, 0x3d, + 0x00, 0x00, 0x03, 0x41, 0x00, 0x00, 0x03, 0x45, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x03, 0x4d, 0x00, 0x00, 0x03, 0x51, + 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x03, 0x59, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xdc, + 0x00, 0x00, 0x02, 0x0c, 0x52, 0x60, 0x55, 0x9c, 0x4a, 0x26, 0x30, 0x1b, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, + 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x06, 0x93, 0x56, 0x67, 0xd4, 0x00, 0x07, 0x17, 0xac, 0xc1, 0xbd, 0xea, 0x93, 0x3b, 0xd3, 0x28, 0xa0, + 0x57, 0xe5, 0x77, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, + 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x9d, 0x01, 0xd2, 0x67, 0xcc, 0xce, 0x6d, 0x38, 0xee, 0x87, 0xc1, 0xcc, + 0x32, 0xbb, 0xee, 0x47, 0xfa, 0x77, 0x9b, 0xdf, 0x00, 0x00, 0x00, 0x44, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x62, 0x69, 0x6e, + 0x2f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x63, 0x6f, 0x6d, 0x2e, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0x74, 0x72, 0x69, 0x63, + 0x74, 0x69, 0x76, 0x65, 0xad, 0xa7, 0xd1, 0x01, 0x67, 0x9c, 0xc4, 0xea, 0xc3, 0xdf, 0x8e, 0xc4, 0x08, 0x5b, 0x35, 0x71, + 0x96, 0xc4, 0xb0, 0x57, 0x19, 0x46, 0xb5, 0x63, 0xce, 0xbb, 0x8e, 0xe7, 0x35, 0x53, 0x02, 0xe2, 0xb2, 0x8d, 0xfa, 0xf4, + 0x08, 0xdd, 0x5f, 0xda, 0x2e, 0x3e, 0xf4, 0x8c, 0x14, 0x02, 0xe2, 0x53, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0x10, 0x34, 0x14, 0x76, 0xa3, 0xc3, 0x9d, 0x60, 0x91, 0x3d, 0xda, 0x7c, 0x59, 0x37, 0xec, 0x91, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0x10, 0x34, 0x14, 0x76, 0xa3, 0xc3, 0x9d, 0x60, 0x91, 0x3d, 0xda, 0x7c, 0x59, 0x37, 0xec, 0x91, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfc, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0xa4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x02, 0x51, + 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x02, 0xa5, + 0x00, 0x00, 0x02, 0xa9, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xb1, 0x00, 0x00, 0x02, 0xbd, 0x00, 0x00, 0x02, 0xc9, + 0x00, 0x00, 0x02, 0xcd, 0x00, 0x00, 0x02, 0xd1, 0x00, 0x00, 0x02, 0xd5, 0x00, 0x00, 0x02, 0xd9, 0x00, 0x00, 0x02, 0xdd, + 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0x00, 0x00, 0x02, 0xe9, 0x00, 0x00, 0x02, 0xed, 0x00, 0x00, 0x02, 0xf1, + 0x00, 0x00, 0x02, 0xf5, 0x00, 0x00, 0x02, 0xf9, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x7c, + 0x00, 0x00, 0x01, 0xa4, 0x3b, 0xaf, 0x30, 0xf6, 0xce, 0x08, 0x47, 0xad, 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, + 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xcf, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x06, 0xeb, 0x22, 0x2e, 0xd0, 0xa1, 0x2a, 0x8b, 0xd2, 0x11, 0xac, 0x9f, 0x5b, 0x27, 0x35, 0x5d, 0xd8, + 0x58, 0x6d, 0x84, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xa8, 0x12, 0x5f, 0x3d, 0x91, 0x36, 0x30, 0x1a, 0x76, 0x25, 0x8c, 0xbf, + 0x1f, 0x58, 0xcb, 0x76, 0xd6, 0xbb, 0xff, 0xb1, 0xff, 0xff, 0xff, 0xff, 0x98, 0xb9, 0x89, 0x06, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xa8, 0x12, 0x5f, 0x3d, 0x91, 0x36, 0x30, 0x1a, + 0x76, 0x25, 0x8c, 0xbf, 0x1f, 0x58, 0xcb, 0x76, 0xd6, 0xbb, 0xff, 0xb1, 0xff, 0xff, 0xff, 0xff, 0x98, 0xb9, 0x89, 0x06, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0xc2, 0xa8, 0x12, 0x5f, 0x3d, 0xc2, 0x91, 0x36, 0x30, 0x1a, 0x76, 0x25, 0xc2, 0x8c, 0xc2, 0xbf, + 0x1f, 0x58, 0xc3, 0x8b, 0x76, 0xc3, 0x96, 0xc2, 0xbb, 0xc3, 0xbf, 0xc2, 0xb1, 0xc3, 0xbf, 0xc3, 0xbf, 0xc3, 0xbf, 0xc3, + 0xbf, 0xc2, 0x98, 0xc2, 0xb9, 0xc2, 0x89, 0x06, 0x01, 0x00, 0xff, 0xff, 0x00, 0x54, 0x55, 0x4d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, + 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0xe6, 0x50, 0x17, 0x0a, 0x9f, 0xb9, 0xab, 0x61, 0x5d, 0x77, 0x39, 0x8b, + 0x76, 0x2d, 0x3f, 0x20, 0xb2, 0xec, 0x7c, 0xbc, 0xa1, 0x54, 0xac, 0x1b, 0x1c, 0x6d, 0x6b, 0x88, 0x3b, 0xd2, 0x7b, 0x6b, + 0x24, 0x84, 0x7c, 0xca, 0xc7, 0xe8, 0x66, 0x8e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x18, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, + 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, + 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, + 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x02, 0xe8, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0xa8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x02, 0x41, + 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x02, 0x65, + 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x02, 0x95, 0x00, 0x00, 0x02, 0x99, 0x00, 0x00, 0x02, 0x9d, 0x00, 0x00, 0x02, 0xa9, + 0x00, 0x00, 0x02, 0xb5, 0x00, 0x00, 0x02, 0xb9, 0x00, 0x00, 0x02, 0xbd, 0x00, 0x00, 0x02, 0xc1, 0x00, 0x00, 0x02, 0xc5, + 0x00, 0x00, 0x02, 0xc9, 0x00, 0x00, 0x02, 0xcd, 0x00, 0x00, 0x02, 0xd1, 0x00, 0x00, 0x02, 0xd5, 0x00, 0x00, 0x02, 0xd9, + 0x00, 0x00, 0x02, 0xdd, 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xa8, 0xf4, 0x8e, 0xca, 0x78, 0x14, 0xb8, 0x41, 0x73, 0x00, 0x00, 0x00, 0x02, + 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x21, + 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x64, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x72, 0x3a, 0x27, 0x07, 0x00, 0xae, 0x19, 0xfc, 0x71, 0x1c, 0x6f, 0x2f, + 0xe2, 0x2b, 0x78, 0x9a, 0xdc, 0x88, 0xc1, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xc9, 0x22, 0xdf, 0x1e, 0x94, 0x1b, 0x4d, 0x42, + 0x21, 0x42, 0x85, 0xcd, 0x32, 0xec, 0xe5, 0xd7, 0xf9, 0x61, 0x38, 0xe1, 0xff, 0xff, 0xff, 0xff, 0x98, 0xb9, 0x89, 0x06, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xc9, 0x22, 0xdf, 0x1e, + 0x94, 0x1b, 0x4d, 0x42, 0x21, 0x42, 0x85, 0xcd, 0x32, 0xec, 0xe5, 0xd7, 0xf9, 0x61, 0x38, 0xe1, 0xff, 0xff, 0xff, 0xff, + 0x98, 0xb9, 0x89, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0xc3, 0x89, 0x22, 0xc3, 0x9f, 0x1e, 0xc2, 0x94, + 0x1b, 0x4d, 0x42, 0x21, 0x42, 0xc2, 0x85, 0xc3, 0x8d, 0x32, 0xc3, 0xac, 0xc3, 0xa5, 0xc3, 0x97, 0xc3, 0xb9, 0x61, 0x38, + 0xc3, 0xa1, 0xc3, 0xbf, 0xc3, 0xbf, 0xc3, 0xbf, 0xc3, 0xbf, 0xc2, 0x98, 0xc2, 0xb9, 0xc2, 0x89, 0x06, 0x01, 0x00, 0x4d, + 0x00, 0x54, 0x55, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0x7b, 0x74, 0x34, 0xf2, + 0x79, 0x55, 0x24, 0x13, 0xc5, 0x6c, 0xdd, 0xe2, 0xe7, 0xd5, 0xbf, 0x4e, 0xaa, 0xc8, 0x50, 0xa3, 0xc6, 0x46, 0x67, 0x62, + 0x08, 0x04, 0x0d, 0xe7, 0x54, 0xe1, 0xb5, 0x0a, 0x53, 0x0d, 0x90, 0xbc, 0xd7, 0x2e, 0x5f, 0x6d, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x08, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x4c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x81, 0x00, 0x00, 0x02, 0x85, 0x00, 0x00, 0x02, 0x9d, + 0x00, 0x00, 0x02, 0xa1, 0x00, 0x00, 0x02, 0xa5, 0x00, 0x00, 0x02, 0xa9, 0x00, 0x00, 0x02, 0xad, 0x00, 0x00, 0x02, 0xc5, + 0x00, 0x00, 0x02, 0xc9, 0x00, 0x00, 0x02, 0xf5, 0x00, 0x00, 0x02, 0xf9, 0x00, 0x00, 0x02, 0xfd, 0x00, 0x00, 0x03, 0x01, + 0x00, 0x00, 0x03, 0x0d, 0x00, 0x00, 0x03, 0x19, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x03, 0x21, 0x00, 0x00, 0x03, 0x25, + 0x00, 0x00, 0x03, 0x29, 0x00, 0x00, 0x03, 0x2d, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x03, 0x39, + 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x03, 0x41, 0x00, 0x00, 0x03, 0x45, 0x00, 0x00, 0x03, 0x49, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xcc, 0x00, 0x00, 0x01, 0xfc, 0x1a, 0xe7, 0x86, 0xc7, 0x8e, 0x0c, 0x7b, 0xed, + 0x00, 0x00, 0x00, 0x02, 0x87, 0x19, 0x1c, 0xa2, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, 0x02, 0xb5, 0x21, 0x22, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0xbb, 0x34, 0xae, 0xf4, 0x96, 0x00, 0x3a, 0xa9, + 0x6c, 0x3b, 0x6c, 0xa6, 0x1b, 0xa0, 0xfd, 0x0d, 0x0b, 0x7b, 0xc1, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x6e, 0x6f, 0x62, 0x6f, + 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x50, 0x81, 0xee, 0xbe, 0x1f, 0x36, 0xff, 0x64, + 0xa1, 0x66, 0x43, 0xd7, 0xdc, 0x0e, 0x61, 0xf0, 0x17, 0xaf, 0x60, 0x35, 0x00, 0x00, 0x00, 0x60, 0x2f, 0x41, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, + 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x20, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x2e, 0x61, 0x70, 0x70, 0x00, + 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x6b, 0x65, 0x79, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x73, 0xb8, 0x58, 0xf2, 0xef, + 0xb1, 0x4e, 0x1e, 0x2e, 0x15, 0xe0, 0x0f, 0xb5, 0xea, 0xd4, 0xf5, 0x1e, 0x45, 0x79, 0x80, 0x58, 0xe2, 0xb2, 0x93, 0xf6, + 0x1c, 0xbf, 0x8c, 0x2b, 0x1d, 0xdb, 0xed, 0x58, 0xd3, 0x90, 0x91, 0xfd, 0x86, 0xbe, 0x01, 0xdd, 0x76, 0x36, 0x01, 0xf0, + 0x1a, 0x4f, 0xd8, 0x7d, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x88, 0x63, 0xaf, 0x56, + 0xf7, 0x5a, 0x1f, 0xa9, 0xf0, 0x1f, 0x26, 0xc0, 0x6c, 0x8d, 0x8a, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x88, 0x63, 0xaf, 0x56, + 0xf7, 0x5a, 0x1f, 0xa9, 0xf0, 0x1f, 0x26, 0xc0, 0x6c, 0x8d, 0x8a, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, + 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x8c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x15, 0x64, + 0x00, 0x00, 0x18, 0xe0, 0x00, 0x00, 0x19, 0xf4, 0x00, 0x00, 0x1a, 0x7c, 0x00, 0x00, 0x1b, 0x04, 0x00, 0x00, 0x1b, 0x8c, + 0x00, 0x00, 0x1c, 0x14, 0x00, 0x00, 0x1c, 0x9c, 0x00, 0x00, 0x1d, 0x24, 0x00, 0x00, 0x1d, 0xac, 0x00, 0x00, 0x1e, 0x34, + 0x00, 0x00, 0x03, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x15, 0xd0, 0x00, 0x00, 0x16, 0x44, + 0x00, 0x00, 0x16, 0xb4, 0x00, 0x00, 0x17, 0x24, 0x00, 0x00, 0x17, 0x94, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x18, 0x74, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x17, 0x72, 0x65, 0x73, 0x74, + 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x10, 0x34, 0x14, 0x76, + 0xa3, 0xc3, 0x9d, 0x60, 0x91, 0x3d, 0xda, 0x7c, 0x59, 0x37, 0xec, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, + 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, + 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, + 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x66, 0x4e, 0xf9, 0x51, 0xc5, 0xeb, 0x28, 0x0b, 0xca, 0x0c, 0x15, 0x2f, + 0x22, 0x80, 0x18, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, + 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, + 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0x88, 0x63, 0xaf, 0x56, 0xf7, 0x5a, 0x1f, 0xa9, 0xf0, 0x1f, 0x26, 0xc0, 0x6c, 0x8d, 0x8a, 0xb4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, + 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, + 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xce, 0x31, 0x50, 0xc1, 0x8c, 0xde, 0x4b, 0xa0, + 0xca, 0xfd, 0x36, 0x98, 0x33, 0x59, 0x99, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0xea, 0xa1, 0xad, 0x3e, 0x49, 0xa8, 0x35, 0x7b, 0xce, 0x5d, 0x8c, 0xd6, 0xdf, 0x25, 0xe4, 0x2d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, + 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, + 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x7b, 0x38, 0x37, 0x31, + 0x39, 0x31, 0x63, 0x61, 0x32, 0x2d, 0x30, 0x66, 0x63, 0x39, 0x2d, 0x31, 0x31, 0x64, 0x34, 0x2d, 0x38, 0x34, 0x39, 0x61, + 0x2d, 0x30, 0x30, 0x30, 0x35, 0x30, 0x32, 0x62, 0x35, 0x32, 0x31, 0x32, 0x32, 0x7d, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x19, 0x30, + 0x00, 0x00, 0x19, 0x50, 0x00, 0x00, 0x19, 0x6c, 0x00, 0x00, 0x19, 0x88, 0x00, 0x00, 0x19, 0xa4, 0x00, 0x00, 0x19, 0xc0, + 0x00, 0x00, 0x19, 0xdc, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x17, + 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x10, 0x34, 0x14, 0x76, + 0xa3, 0xc3, 0x9d, 0x60, 0x91, 0x3d, 0xda, 0x7c, 0x59, 0x37, 0xec, 0x91, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0x66, 0x4e, 0xf9, 0x51, 0xc5, 0xeb, 0x28, 0x0b, 0xca, 0x0c, 0x15, 0x2f, 0x22, 0x80, 0x18, 0x7b, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x88, 0x63, 0xaf, 0x56, 0xf7, 0x5a, 0x1f, 0xa9, + 0xf0, 0x1f, 0x26, 0xc0, 0x6c, 0x8d, 0x8a, 0xb4, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0xce, 0x31, 0x50, 0xc1, 0x8c, 0xde, 0x4b, 0xa0, 0xca, 0xfd, 0x36, 0x98, 0x33, 0x59, 0x99, 0x39, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0xea, 0xa1, 0xad, 0x3e, 0x49, 0xa8, 0x35, 0x7b, 0xce, 0x5d, 0x8c, 0xd6, + 0xdf, 0x25, 0xe4, 0x2d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x70, 0x70, + 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1a, 0x44, 0x00, 0x00, 0x1a, 0x4c, + 0x00, 0x00, 0x1a, 0x54, 0x00, 0x00, 0x1a, 0x5c, 0x00, 0x00, 0x1a, 0x64, 0x00, 0x00, 0x1a, 0x6c, 0x00, 0x00, 0x1a, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1a, 0xcc, 0x00, 0x00, 0x1a, 0xd4, 0x00, 0x00, 0x1a, 0xdc, + 0x00, 0x00, 0x1a, 0xe4, 0x00, 0x00, 0x1a, 0xec, 0x00, 0x00, 0x1a, 0xf4, 0x00, 0x00, 0x1a, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1b, 0x54, 0x00, 0x00, 0x1b, 0x5c, 0x00, 0x00, 0x1b, 0x64, 0x00, 0x00, 0x1b, 0x6c, + 0x00, 0x00, 0x1b, 0x74, 0x00, 0x00, 0x1b, 0x7c, 0x00, 0x00, 0x1b, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x1b, 0xdc, 0x00, 0x00, 0x1b, 0xe4, 0x00, 0x00, 0x1b, 0xec, 0x00, 0x00, 0x1b, 0xf4, 0x00, 0x00, 0x1b, 0xfc, + 0x00, 0x00, 0x1c, 0x04, 0x00, 0x00, 0x1c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1c, 0x64, + 0x00, 0x00, 0x1c, 0x6c, 0x00, 0x00, 0x1c, 0x74, 0x00, 0x00, 0x1c, 0x7c, 0x00, 0x00, 0x1c, 0x84, 0x00, 0x00, 0x1c, 0x8c, + 0x00, 0x00, 0x1c, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1c, 0xec, 0x00, 0x00, 0x1c, 0xf4, + 0x00, 0x00, 0x1c, 0xfc, 0x00, 0x00, 0x1d, 0x04, 0x00, 0x00, 0x1d, 0x0c, 0x00, 0x00, 0x1d, 0x14, 0x00, 0x00, 0x1d, 0x1c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1d, 0x74, 0x00, 0x00, 0x1d, 0x7c, 0x00, 0x00, 0x1d, 0x84, + 0x00, 0x00, 0x1d, 0x8c, 0x00, 0x00, 0x1d, 0x94, 0x00, 0x00, 0x1d, 0x9c, 0x00, 0x00, 0x1d, 0xa4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x1d, 0xfc, 0x00, 0x00, 0x1e, 0x04, 0x00, 0x00, 0x1e, 0x0c, 0x00, 0x00, 0x1e, 0x14, + 0x00, 0x00, 0x1e, 0x1c, 0x00, 0x00, 0x1e, 0x24, 0x00, 0x00, 0x1e, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x88, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x1e, 0x84, 0x00, 0x00, 0x1e, 0x8c, 0x00, 0x00, 0x1e, 0x94, 0x00, 0x00, 0x1e, 0x9c, 0x00, 0x00, 0x1e, 0xa4, + 0x00, 0x00, 0x1e, 0xac, 0x00, 0x00, 0x1e, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0xdc, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x04, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, + 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xf5, + 0x73, 0x73, 0x67, 0x70, 0xea, 0xa1, 0xad, 0x3e, 0x49, 0xa8, 0x35, 0x7b, 0xce, 0x5d, 0x8c, 0xd6, 0xdf, 0x25, 0xe4, 0x2d, + 0x4a, 0x16, 0x48, 0x81, 0x4a, 0xfb, 0x22, 0x80, 0x56, 0xd0, 0x65, 0x2b, 0x3e, 0x11, 0x11, 0xe2, 0x12, 0x2b, 0xc6, 0x87, + 0xa1, 0xd0, 0x14, 0x1e, 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x35, 0x31, 0x30, 0x36, 0x5a, 0x00, + 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x35, 0x31, 0x30, 0x36, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x16, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xa9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, + 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x01, 0x15, 0x73, 0x73, 0x67, 0x70, 0x10, 0x34, 0x14, 0x76, 0xa3, 0xc3, 0x9d, 0x60, + 0x91, 0x3d, 0xda, 0x7c, 0x59, 0x37, 0xec, 0x91, 0xfd, 0xc0, 0xab, 0x3b, 0xfc, 0x61, 0xe6, 0xd5, 0xdd, 0xcf, 0x26, 0x91, + 0xe5, 0xe9, 0xfb, 0x2c, 0xc0, 0x8d, 0xfe, 0x4c, 0x96, 0xf5, 0x08, 0x64, 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, + 0x31, 0x38, 0x35, 0x31, 0x31, 0x37, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x35, 0x31, + 0x31, 0x37, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, + 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, + 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0xd9, 0x73, 0x73, 0x67, 0x70, 0x88, 0x63, 0xaf, 0x56, 0xf7, 0x5a, 0x1f, 0xa9, + 0xf0, 0x1f, 0x26, 0xc0, 0x6c, 0x8d, 0x8a, 0xb4, 0xdc, 0xaf, 0x18, 0xfa, 0xad, 0xad, 0x06, 0xf6, 0x32, 0x30, 0x31, 0x36, + 0x30, 0x34, 0x31, 0x31, 0x32, 0x31, 0x35, 0x31, 0x31, 0x35, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x31, 0x31, + 0x32, 0x31, 0x35, 0x31, 0x31, 0x35, 0x5a, 0x00, 0x61, 0x61, 0x70, 0x6c, 0x69, 0x70, 0x72, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x00, 0x00, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x11, + 0x73, 0x73, 0x75, 0x69, 0x00, 0x00, 0x00, 0x20, 0x87, 0x19, 0x1c, 0xa3, 0x0f, 0xc9, 0x11, 0xd4, 0x84, 0x9a, 0x00, 0x05, + 0x02, 0xb5, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x64, 0x62, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x21, 0x7e, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2f, 0x4b, 0x65, + 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x61, 0x73, 0x64, 0x66, 0x2d, 0x64, 0x62, + 0x00, 0x69, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00, 0xb8, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa0, 0x30, 0x81, 0x9d, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, + 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, + 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x56, 0x81, 0x44, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb4, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x3c, 0x00, 0x00, 0x04, 0xf0, 0x00, 0x00, 0x05, 0x5c, 0x00, 0x00, 0x00, 0xb4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x61, 0x63, 0x63, 0x74, 0x73, 0x76, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x70, 0x00, 0x00, 0x04, 0x94, 0x00, 0x00, 0x04, 0xc8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x6c, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x05, 0x34, 0x00, 0x00, 0x05, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, + 0x6d, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x8c, 0x00, 0x00, 0x05, 0xa4, 0x00, 0x00, 0x05, 0xb8, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, + 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x05, 0x2c, 0x80, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xa5, + 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x21, + 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x01, 0x31, 0x73, 0x73, 0x67, 0x70, 0x66, 0x4e, 0xf9, 0x51, + 0xc5, 0xeb, 0x28, 0x0b, 0xca, 0x0c, 0x15, 0x2f, 0x22, 0x80, 0x18, 0x7b, 0xce, 0x58, 0x3c, 0x63, 0xf0, 0xe1, 0x4b, 0xfc, + 0xee, 0x88, 0x20, 0xa4, 0xc4, 0x20, 0xc4, 0x8c, 0xaf, 0x9d, 0xe6, 0x89, 0x39, 0xe3, 0xcc, 0x27, 0x32, 0x30, 0x31, 0x36, + 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x34, 0x39, 0x33, 0x34, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, + 0x31, 0x38, 0x34, 0x39, 0x33, 0x34, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x61, 0x20, 0x75, 0x73, + 0x65, 0x66, 0x75, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x68, 0x74, 0x70, 0x73, + 0x00, 0x00, 0x00, 0x04, 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0xed, + 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x01, 0x11, + 0x73, 0x73, 0x67, 0x70, 0xce, 0x31, 0x50, 0xc1, 0x8c, 0xde, 0x4b, 0xa0, 0xca, 0xfd, 0x36, 0x98, 0x33, 0x59, 0x99, 0x39, + 0x60, 0x88, 0xd4, 0xf3, 0x53, 0x7d, 0x89, 0x6e, 0xc1, 0x4f, 0xfd, 0x7b, 0x4b, 0x9d, 0x0d, 0xe0, 0xe9, 0xd6, 0x84, 0xdf, + 0x0f, 0x23, 0x90, 0x0b, 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x34, 0x39, 0x34, 0x33, 0x5a, 0x00, + 0x32, 0x30, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x34, 0x39, 0x34, 0x33, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x61, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x68, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x04, + 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x02, 0x94, 0x00, 0x00, 0x03, 0x5c, 0x00, 0x00, 0x03, 0xac, 0x00, 0x00, 0x03, 0xe4, 0x00, 0x00, 0x04, 0x44, + 0x00, 0x00, 0x04, 0x7c, 0x00, 0x00, 0x04, 0xbc, 0x00, 0x00, 0x04, 0xf4, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x61, 0x63, 0x63, 0x74, 0x73, 0x64, 0x6d, 0x6e, 0x73, 0x72, 0x76, 0x72, + 0x70, 0x74, 0x63, 0x6c, 0x61, 0x74, 0x79, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x70, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0xd4, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x68, 0x74, 0x70, 0x73, + 0x00, 0x00, 0x00, 0x04, 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, + 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x63, 0x6c, 0x68, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x04, + 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x84, + 0x00, 0x00, 0x03, 0x98, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, + 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x64, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0xd4, + 0x00, 0x00, 0x03, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x0c, 0x00, 0x00, 0x04, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1c, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x61, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x6c, 0x00, 0x00, 0x04, 0x74, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x68, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, 0x74, 0x70, 0x73, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x74, 0x79, 0x70, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0xa4, 0x00, 0x00, 0x04, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, + 0x64, 0x66, 0x6c, 0x74, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0xe4, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x70, 0x61, 0x74, 0x68, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x1c, 0x00, 0x00, 0x05, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x61, 0x63, 0x63, 0x74, 0x76, 0x6c, 0x6d, 0x65, + 0x61, 0x64, 0x64, 0x72, 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x76, 0x6c, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x64, 0x64, 0x72, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x73, 0x73, 0x69, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x1c, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0b, 0xd8, 0x00, 0x00, 0x05, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x45, 0x00, 0x00, 0x04, 0x49, + 0x00, 0x00, 0x04, 0x4d, 0x00, 0x00, 0x04, 0x5d, 0x00, 0x00, 0x04, 0x71, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x05, 0xb9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xc1, 0x30, 0x82, 0x04, 0x01, 0x30, 0x82, 0x02, 0xe9, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x04, 0x56, 0x81, 0x44, 0xc1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x81, 0x9d, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, + 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, + 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, + 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, + 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x35, 0x35, 0x33, 0x32, 0x5a, 0x17, + 0x0d, 0x32, 0x36, 0x30, 0x34, 0x30, 0x36, 0x31, 0x38, 0x35, 0x35, 0x33, 0x32, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, + 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, + 0x62, 0x6f, 0x64, 0x79, 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, 0xb3, 0xaa, 0xa8, 0x77, 0xe7, 0x3e, 0x2d, 0x0c, 0xf4, 0x83, 0x55, 0xc2, 0x9e, + 0x50, 0x10, 0xc9, 0xef, 0xc8, 0x48, 0x38, 0xe4, 0x43, 0x96, 0xfa, 0x93, 0x32, 0xbf, 0x66, 0xad, 0x84, 0xa2, 0x8b, 0x6b, + 0x07, 0x8c, 0xc6, 0x93, 0x8c, 0x4d, 0x65, 0x0f, 0xad, 0x76, 0x73, 0x0c, 0x4d, 0x43, 0xee, 0x35, 0xd4, 0x68, 0x4a, 0x9a, + 0x6d, 0x4d, 0xa5, 0xae, 0x66, 0xcf, 0xfb, 0xbb, 0x93, 0xd3, 0x6a, 0xe3, 0xfc, 0x41, 0x97, 0xae, 0x90, 0xc3, 0xd8, 0x83, + 0xfb, 0x8d, 0x67, 0x84, 0xc1, 0xd5, 0x7d, 0x1d, 0x12, 0xca, 0x0c, 0xb5, 0xae, 0xf0, 0xe3, 0x36, 0x39, 0xf1, 0x68, 0x92, + 0x6f, 0xda, 0x2d, 0x48, 0x87, 0xf0, 0x4b, 0x15, 0x4e, 0x4f, 0x7a, 0x3a, 0x16, 0xb9, 0x02, 0x89, 0x95, 0x98, 0xab, 0xb2, + 0x58, 0x5b, 0x31, 0x7f, 0x49, 0x90, 0x48, 0xfd, 0x8d, 0x8a, 0x37, 0x3a, 0x4e, 0xd8, 0x00, 0x4a, 0xdc, 0xd4, 0x02, 0x9f, + 0xcd, 0x4b, 0xde, 0x75, 0x4a, 0xb2, 0x27, 0x8e, 0xe6, 0x2d, 0xea, 0x35, 0x89, 0x85, 0x8a, 0x37, 0x59, 0xd6, 0xd1, 0xf8, + 0x36, 0x7c, 0x93, 0x9e, 0xd6, 0xd1, 0xc3, 0xd9, 0x75, 0xa4, 0x4f, 0x40, 0x24, 0xe9, 0xc0, 0xde, 0xeb, 0xc0, 0x5e, 0xd6, + 0x04, 0xe1, 0xd0, 0x07, 0x29, 0xc1, 0x9d, 0x6f, 0x78, 0x2d, 0x5a, 0xef, 0xe6, 0xff, 0x25, 0x16, 0xcf, 0x60, 0x77, 0xa2, + 0x10, 0x2b, 0xa4, 0x2a, 0xff, 0x74, 0x3b, 0xe6, 0x4d, 0xc1, 0x13, 0xba, 0x8b, 0xe8, 0x15, 0x8e, 0xc7, 0xc3, 0xd4, 0x31, + 0xb0, 0x99, 0x51, 0x32, 0x30, 0x03, 0x0b, 0x1c, 0xa0, 0x0a, 0x17, 0x15, 0x34, 0x57, 0x38, 0xd3, 0x08, 0x13, 0xc4, 0xd6, + 0x7c, 0x24, 0x16, 0xd0, 0x2f, 0x00, 0x88, 0xd7, 0xd9, 0xca, 0x1e, 0x6b, 0x50, 0x3b, 0x5f, 0xb6, 0x08, 0xb1, 0x29, 0x42, + 0x70, 0xf1, 0x89, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x47, 0x30, 0x45, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, + 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, + 0x14, 0x30, 0x12, 0x81, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 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, 0x00, 0xa3, 0x3e, 0x5c, 0x33, 0x06, 0x0b, 0x74, 0xf7, 0x59, 0x56, 0x2e, 0x26, 0x18, 0xe0, 0x59, 0xc9, 0x20, 0x9d, + 0xaa, 0xf2, 0xfb, 0xa0, 0xf8, 0x11, 0x00, 0x71, 0x53, 0x3d, 0xfa, 0xdc, 0xe9, 0x12, 0x4c, 0x8a, 0xa1, 0x1c, 0x7c, 0xb3, + 0x4b, 0xa5, 0xa0, 0xfa, 0x03, 0xc5, 0x82, 0x1c, 0xab, 0x44, 0xf6, 0xcb, 0x59, 0x4b, 0x80, 0xeb, 0xc0, 0xa8, 0x0e, 0xc6, + 0x93, 0xea, 0xbf, 0x67, 0x41, 0xa9, 0x64, 0xcb, 0xb4, 0x3e, 0xf7, 0x64, 0xcf, 0x4c, 0xef, 0x24, 0x62, 0x73, 0x2d, 0xed, + 0xb4, 0xec, 0x30, 0x97, 0x91, 0x9f, 0x18, 0xe9, 0x12, 0x93, 0x18, 0x83, 0x70, 0xb0, 0xc4, 0x35, 0x33, 0x67, 0x17, 0xb0, + 0x8b, 0xbe, 0x45, 0xde, 0x98, 0x23, 0xf2, 0x02, 0x77, 0x79, 0x55, 0x53, 0xc4, 0xd7, 0x67, 0x81, 0xde, 0xa1, 0x3f, 0x63, + 0xb5, 0x87, 0xb6, 0x20, 0x8d, 0x4f, 0x5e, 0x7e, 0x27, 0x30, 0x99, 0xe0, 0xff, 0x91, 0x8b, 0x00, 0x8d, 0x7d, 0xe5, 0x57, + 0x57, 0xd8, 0xd9, 0x7d, 0x6f, 0xc6, 0xb8, 0x6f, 0x84, 0xed, 0x84, 0x9d, 0xd9, 0xac, 0x13, 0xd8, 0x4a, 0x96, 0x55, 0x2d, + 0x8e, 0x21, 0x11, 0xc9, 0xa4, 0x81, 0x10, 0x7a, 0x0a, 0x15, 0xce, 0x99, 0x98, 0x09, 0xdd, 0xec, 0x8d, 0x1b, 0xfb, 0x17, + 0x55, 0x03, 0xa6, 0x44, 0xb5, 0xc9, 0xa9, 0x1f, 0x52, 0xd7, 0x35, 0x06, 0x8d, 0x0a, 0x5a, 0x01, 0x2a, 0xb0, 0xd2, 0x0c, + 0xfa, 0xd9, 0x66, 0xfa, 0x35, 0x6e, 0xa0, 0xbc, 0x21, 0xe4, 0xe1, 0xe0, 0x3c, 0x3b, 0x7a, 0xef, 0x7d, 0xe1, 0x34, 0x2e, + 0xe3, 0x9c, 0xc0, 0xa9, 0x4c, 0x16, 0xab, 0x00, 0x60, 0xe0, 0x44, 0xeb, 0x62, 0xcc, 0x1d, 0x27, 0x84, 0x0f, 0x33, 0x37, + 0x9d, 0xc5, 0xc4, 0xa1, 0xd3, 0xe8, 0x38, 0xff, 0xf2, 0xdf, 0xcd, 0x7c, 0xbb, 0xc3, 0xa1, 0xae, 0x4d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, + 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0xa0, 0x30, 0x81, 0x9d, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, + 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0xa0, 0x30, 0x81, 0x9d, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x31, 0x14, 0x30, 0x12, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, + 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, + 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x56, 0x81, 0x44, 0xc1, + 0x00, 0x00, 0x00, 0x14, 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, 0x29, 0x26, 0x07, 0x8d, 0x1b, 0xb4, 0x93, 0xc4, + 0x3e, 0xfd, 0x6a, 0x65, 0x00, 0x00, 0x05, 0xd8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x31, 0x00, 0x00, 0x04, 0x35, 0x00, 0x00, 0x04, 0x39, + 0x00, 0x00, 0x04, 0x4d, 0x00, 0x00, 0x04, 0x61, 0x00, 0x00, 0x05, 0x0d, 0x00, 0x00, 0x05, 0xb9, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0xc1, 0x30, 0x82, 0x03, 0xee, 0x30, 0x82, 0x02, 0xd6, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x06, + 0xe0, 0x2a, 0x1d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, + 0xa2, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, + 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x17, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, + 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, + 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x30, 0x38, 0x31, 0x38, 0x35, 0x36, 0x34, 0x36, 0x5a, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x34, 0x30, 0x36, 0x31, 0x38, 0x35, 0x36, 0x34, 0x36, 0x5a, 0x30, 0x81, 0xa2, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x17, 0x46, 0x4f, + 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, + 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, + 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 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, 0xb6, 0x07, 0xac, 0x5c, 0xc6, 0xcb, 0xf0, + 0xb7, 0x97, 0x0d, 0x43, 0x1a, 0xe9, 0x61, 0xe7, 0x34, 0x63, 0x6a, 0x26, 0x0d, 0x77, 0xba, 0x25, 0xaa, 0xc8, 0x46, 0xf8, + 0xc9, 0xdd, 0x21, 0xb4, 0x3e, 0x2e, 0x11, 0x8e, 0xb6, 0x72, 0xf2, 0x01, 0x16, 0x07, 0xcf, 0x88, 0x91, 0xc4, 0xc0, 0x48, + 0x64, 0x41, 0x91, 0xf7, 0x63, 0x72, 0xd5, 0x37, 0xef, 0x37, 0x62, 0xed, 0x33, 0xb3, 0xf9, 0x6e, 0x31, 0xd1, 0x68, 0xe7, + 0xde, 0x62, 0x9f, 0x82, 0xb8, 0x9e, 0x11, 0xe7, 0x66, 0x91, 0xc1, 0xbe, 0xe5, 0x5c, 0xd6, 0x71, 0x83, 0x91, 0xbc, 0x0f, + 0xa8, 0x06, 0xc3, 0xe9, 0xb6, 0x76, 0x16, 0xae, 0x69, 0x0a, 0x47, 0xe4, 0x65, 0xaa, 0x13, 0x71, 0x48, 0xb3, 0x5c, 0x25, + 0xa5, 0x1a, 0xd0, 0x2a, 0x57, 0x57, 0xf9, 0xb7, 0x13, 0xbd, 0xf4, 0x13, 0x5a, 0x11, 0x1b, 0xcc, 0xd8, 0x9a, 0x5f, 0x82, + 0x3f, 0xa7, 0x6b, 0x64, 0x47, 0x54, 0xb6, 0x81, 0xaf, 0xcb, 0x4b, 0x94, 0x39, 0x65, 0x15, 0xba, 0x6a, 0x02, 0x7c, 0x71, + 0x30, 0x60, 0x21, 0x12, 0x63, 0x28, 0xe0, 0x85, 0xca, 0xcc, 0x07, 0xb1, 0x13, 0x40, 0x19, 0x72, 0x02, 0x35, 0x0e, 0x2d, + 0x4b, 0x8a, 0xcd, 0x1d, 0x09, 0x65, 0xb0, 0x81, 0x49, 0xea, 0x70, 0x15, 0x92, 0x19, 0x7b, 0xfe, 0x15, 0xf7, 0x4a, 0x3f, + 0x1e, 0x3c, 0x63, 0x7a, 0x0f, 0x17, 0x32, 0x1a, 0xb7, 0x26, 0xa1, 0xa0, 0x9b, 0x3f, 0x4e, 0x7c, 0x38, 0xe6, 0x27, 0xbf, + 0xa8, 0x1b, 0xf7, 0xbd, 0x2d, 0xfd, 0x9b, 0x05, 0x0c, 0xaa, 0x81, 0xb8, 0x09, 0xd4, 0xe2, 0xe3, 0xbd, 0x6c, 0x70, 0xc0, + 0x7e, 0x95, 0xd4, 0x0b, 0x13, 0xab, 0xb8, 0xdd, 0x3d, 0x4c, 0x59, 0xf0, 0xc7, 0x8e, 0x47, 0xb5, 0xd8, 0x31, 0x78, 0x80, + 0xd2, 0x5f, 0x0c, 0x0b, 0xae, 0x22, 0xe7, 0x9e, 0xd3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x2a, 0x30, 0x28, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, + 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xaf, 0xe3, + 0x41, 0xaa, 0x63, 0xdc, 0x3e, 0xd1, 0x46, 0x1e, 0x7a, 0x09, 0x04, 0x4a, 0xfd, 0x54, 0xc7, 0xd9, 0x25, 0x2f, 0xce, 0x8e, + 0x5d, 0x34, 0x96, 0x04, 0x67, 0xbc, 0x6f, 0xb6, 0x99, 0x35, 0xc2, 0x16, 0x1c, 0x2a, 0xc3, 0x5f, 0xdf, 0x6e, 0xe2, 0xe4, + 0x2e, 0xbb, 0x64, 0x1c, 0x0a, 0xff, 0x62, 0x79, 0x70, 0x7c, 0xc6, 0x8e, 0xd9, 0x95, 0xb6, 0x8a, 0x3d, 0xf6, 0xdd, 0x79, + 0x1c, 0xeb, 0x73, 0x05, 0x2f, 0x7e, 0x38, 0xb8, 0x9c, 0xfc, 0x06, 0x8f, 0x5f, 0xd7, 0xec, 0xd3, 0x23, 0xae, 0x75, 0x0f, + 0x8e, 0x70, 0xb2, 0xd8, 0x88, 0xa0, 0x4f, 0x53, 0x0a, 0xcc, 0xee, 0x18, 0xf2, 0x5b, 0xf8, 0xe1, 0x22, 0x6b, 0xeb, 0x4d, + 0x9d, 0x2a, 0xa1, 0x46, 0xf4, 0xc7, 0x99, 0x26, 0x5b, 0xaf, 0x92, 0x54, 0x72, 0xe7, 0xea, 0x49, 0x34, 0x98, 0x8d, 0x93, + 0x18, 0xc5, 0x6e, 0x79, 0x79, 0xb3, 0x63, 0x76, 0xf7, 0x84, 0x49, 0x06, 0x58, 0x14, 0x1a, 0x86, 0xbd, 0xe5, 0x5a, 0xf8, + 0x81, 0x06, 0x15, 0x0c, 0xf7, 0x57, 0x4e, 0xeb, 0xbe, 0xc9, 0xe6, 0x09, 0xa3, 0x1d, 0xcc, 0xc6, 0x08, 0xbc, 0x71, 0x4b, + 0x62, 0x1a, 0xec, 0xdd, 0xad, 0xe3, 0x00, 0xd9, 0xf3, 0x98, 0x94, 0x75, 0xb5, 0xc2, 0x64, 0xec, 0xec, 0xe1, 0x88, 0x5b, + 0x24, 0xd6, 0xa2, 0x27, 0x86, 0x10, 0xc4, 0xfc, 0xf7, 0x8d, 0x79, 0x95, 0x20, 0x3e, 0xc5, 0x7a, 0xdc, 0x57, 0xc8, 0x2e, + 0x78, 0x63, 0xd5, 0x09, 0xc3, 0xa9, 0xa4, 0xd9, 0x83, 0x99, 0xbe, 0x17, 0xdc, 0x22, 0x85, 0x98, 0x0b, 0xe1, 0xf6, 0x67, + 0x47, 0xf7, 0x1d, 0xed, 0x40, 0xe4, 0x5c, 0x5e, 0x58, 0xf1, 0x27, 0x5b, 0xe2, 0x7b, 0xb0, 0xf5, 0xbf, 0x37, 0xc3, 0xe2, + 0x73, 0xa8, 0xd6, 0xf1, 0x42, 0xb2, 0x56, 0x90, 0x00, 0xa4, 0x35, 0x4a, 0x5a, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0xa5, 0x30, 0x81, 0xa2, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x17, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, + 0x4f, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, + 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, + 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, + 0x30, 0x81, 0xa2, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x17, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, + 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0xe0, 0x2a, 0x1d, 0x00, 0x00, 0x00, 0x14, + 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, 0x20, 0x1e, 0x00, 0x7c, + 0x00, 0x00, 0x06, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x81, 0x00, 0x00, 0x04, 0x85, 0x00, 0x00, 0x04, 0x89, 0x00, 0x00, 0x04, 0xa5, + 0x00, 0x00, 0x04, 0xc5, 0x00, 0x00, 0x05, 0x81, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x45, + 0x30, 0x82, 0x04, 0x3d, 0x30, 0x82, 0x03, 0x25, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x00, 0xfb, 0xff, 0xa8, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, + 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, + 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x31, 0x32, 0x32, 0x34, 0x30, 0x32, 0x36, 0x5a, 0x17, 0x0d, 0x32, 0x36, 0x30, + 0x34, 0x30, 0x39, 0x32, 0x32, 0x34, 0x30, 0x32, 0x36, 0x5a, 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, + 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, + 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, + 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 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, 0xc3, 0xe8, 0xe0, 0x34, 0xff, 0x63, 0x08, 0xce, 0x36, 0x82, 0x02, 0xe7, 0x91, + 0x0b, 0x73, 0x84, 0xb9, 0xad, 0xd8, 0x79, 0x92, 0x34, 0x20, 0x96, 0xd1, 0x3a, 0xc7, 0x7f, 0x19, 0xd7, 0xcf, 0x9f, 0xab, + 0x2b, 0xc0, 0x0c, 0xe1, 0xf6, 0x0e, 0x9e, 0x9f, 0x73, 0x42, 0x95, 0xf1, 0x2c, 0x63, 0xff, 0x3f, 0x31, 0xb1, 0xe3, 0x24, + 0x1a, 0x75, 0x7d, 0x50, 0x2c, 0x23, 0x59, 0x53, 0x2c, 0xab, 0xaf, 0xd7, 0x5c, 0xf1, 0x27, 0xd2, 0xe9, 0xf5, 0x8f, 0x76, + 0xc4, 0x96, 0x74, 0x3c, 0xda, 0x65, 0xd4, 0x9e, 0xde, 0x33, 0x25, 0x5d, 0xed, 0x04, 0x94, 0x2c, 0xb5, 0x18, 0xeb, 0x64, + 0x8e, 0xf4, 0xd4, 0xe0, 0xb6, 0xfc, 0xcc, 0xd7, 0xfb, 0x90, 0x9c, 0xc1, 0xe6, 0x09, 0xb9, 0x8c, 0xc9, 0xba, 0x91, 0x4d, + 0x63, 0x5f, 0xa1, 0x75, 0x13, 0x11, 0x7d, 0x13, 0xa9, 0x2c, 0x07, 0xbd, 0xcb, 0x5d, 0xc5, 0xb0, 0x4f, 0xed, 0x95, 0xc6, + 0x8c, 0xe9, 0x78, 0xa2, 0xa5, 0x42, 0x15, 0x5a, 0xd0, 0x9c, 0x9c, 0x85, 0x85, 0x6e, 0x50, 0xae, 0x19, 0xd5, 0x91, 0x13, + 0x62, 0x96, 0xd9, 0x4a, 0x47, 0xe3, 0xfe, 0x8f, 0x7d, 0x47, 0xbd, 0xbe, 0xaa, 0x37, 0x64, 0xe3, 0xf0, 0xa3, 0xa4, 0xd0, + 0xef, 0xef, 0x2a, 0xa7, 0x45, 0xbf, 0x21, 0x79, 0xb8, 0x5c, 0x04, 0x8a, 0x2f, 0x7b, 0xe0, 0xe2, 0x32, 0x58, 0x75, 0xec, + 0xec, 0x2f, 0x78, 0xa5, 0x9a, 0x7b, 0xa3, 0x3c, 0xf6, 0x67, 0x00, 0x83, 0xe5, 0x77, 0x1d, 0x2b, 0xdd, 0x74, 0xd0, 0x45, + 0xcf, 0xa4, 0x0c, 0xf2, 0xe2, 0x60, 0xa8, 0x70, 0x87, 0x05, 0x0b, 0x7c, 0xef, 0x88, 0x09, 0x23, 0x15, 0xdf, 0xdb, 0x9f, + 0xc2, 0x80, 0x1f, 0x0a, 0x12, 0xcb, 0x00, 0xa4, 0x8a, 0x77, 0xa7, 0x54, 0x8f, 0xcb, 0x91, 0xbb, 0x55, 0x52, 0x51, 0x8f, + 0xca, 0xf6, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, + 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, + 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04, 0x30, 0x27, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, + 0x20, 0x30, 0x1e, 0x81, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x40, 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, 0x8c, 0x44, 0x70, 0xda, 0xd9, 0x65, 0x52, + 0xfd, 0x46, 0x0e, 0xab, 0xbb, 0xb5, 0x1c, 0x46, 0x0a, 0xcb, 0x3d, 0xc3, 0x71, 0x79, 0xa8, 0x5f, 0x3b, 0x45, 0x49, 0x29, + 0x0c, 0xf5, 0x69, 0xb4, 0x27, 0x4d, 0x79, 0xad, 0xa9, 0x93, 0x11, 0x7b, 0xad, 0x45, 0xc6, 0x49, 0x54, 0x8b, 0x5d, 0x5f, + 0xcc, 0x9d, 0xd9, 0xe4, 0x8f, 0xff, 0x21, 0x0f, 0x7a, 0x40, 0xf2, 0xd6, 0xce, 0xe1, 0x97, 0x5f, 0x7d, 0x9c, 0x76, 0x22, + 0x73, 0x30, 0x3b, 0xb4, 0x5b, 0xa0, 0x07, 0x70, 0x96, 0x97, 0x84, 0xe1, 0x47, 0x5b, 0x3e, 0xd2, 0xed, 0x3f, 0xca, 0x97, + 0x3a, 0x33, 0x52, 0xb8, 0x22, 0x89, 0xe2, 0x2e, 0x61, 0x5e, 0x20, 0x1a, 0xf9, 0x4f, 0x9a, 0x18, 0xde, 0xf3, 0x8e, 0x11, + 0x3b, 0x19, 0x09, 0xce, 0x8e, 0xb9, 0x28, 0x5f, 0x64, 0x54, 0xc1, 0x33, 0x19, 0x68, 0x96, 0x54, 0x53, 0x84, 0xb6, 0xf2, + 0xdb, 0xb3, 0x6b, 0xca, 0x36, 0x08, 0xb1, 0xa3, 0x0d, 0x19, 0x4e, 0xac, 0x17, 0x25, 0x96, 0x0d, 0x4c, 0x9e, 0xc5, 0xa0, + 0xcc, 0xe4, 0x52, 0x98, 0x1c, 0xcf, 0x0a, 0x77, 0x91, 0xf2, 0xc8, 0xae, 0x8c, 0x1c, 0x1d, 0xae, 0x79, 0xf6, 0x0c, 0x65, + 0xf0, 0xb4, 0xdd, 0x0c, 0x6f, 0x35, 0x12, 0x93, 0xb7, 0x20, 0xd1, 0x29, 0xa3, 0x40, 0xb5, 0x66, 0x67, 0x69, 0xdd, 0x97, + 0xcf, 0x48, 0x9f, 0xe9, 0x00, 0x33, 0x0e, 0x8e, 0xae, 0xc6, 0x40, 0xe3, 0x40, 0xdb, 0xab, 0x8b, 0x1e, 0x34, 0xbb, 0x0b, + 0xb7, 0x42, 0xd4, 0x0d, 0x9e, 0x86, 0x99, 0x3c, 0xbd, 0x34, 0xc5, 0xba, 0xac, 0x03, 0x8b, 0xcd, 0xa3, 0xee, 0x36, 0x52, + 0x28, 0x59, 0x7a, 0x29, 0xd7, 0x1f, 0xa1, 0x18, 0xc5, 0xba, 0x7a, 0xc4, 0xf0, 0x67, 0x4a, 0x61, 0x5c, 0x83, 0xad, 0x6c, + 0x89, 0x0b, 0xdd, 0x40, 0xf8, 0xfd, 0x8c, 0xce, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x16, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x00, 0x00, 0x00, 0xb8, 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, + 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0xb8, 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, + 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, + 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, + 0x00, 0xfb, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x14, 0xd7, 0x58, 0x0b, 0xdf, 0xe7, 0x97, 0x49, 0x7e, 0xd7, 0x44, 0x80, 0x01, + 0xf5, 0xf3, 0x7f, 0xf6, 0x1d, 0x5c, 0x24, 0x16, 0x00, 0x00, 0x08, 0xe8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x12, 0x5c, + 0x00, 0x00, 0x14, 0xd0, 0x00, 0x00, 0x15, 0x18, 0x00, 0x00, 0x15, 0x9c, 0x00, 0x00, 0x17, 0xe4, 0x00, 0x00, 0x1a, 0x2c, + 0x00, 0x00, 0x1a, 0x80, 0x00, 0x00, 0x1a, 0x98, 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x03, 0x63, 0x74, 0x79, 0x70, 0x69, 0x73, 0x73, 0x75, 0x73, 0x6e, 0x62, 0x72, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x12, 0x94, 0x00, 0x00, 0x13, 0x48, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa0, 0x30, 0x81, 0x9d, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, + 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, + 0x56, 0x81, 0x44, 0xc1, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa5, 0x30, 0x81, 0xa2, 0x31, + 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x17, 0x46, + 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, + 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0xe0, 0x2a, 0x1d, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xb8, 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, + 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x00, 0xfb, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x63, 0x74, 0x79, 0x70, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x08, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x61, 0x6c, 0x69, 0x73, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x15, 0x48, 0x00, 0x00, 0x15, 0x60, + 0x00, 0x00, 0x15, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x75, 0x62, 0x6a, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x15, 0xcc, 0x00, 0x00, 0x16, 0x74, 0x00, 0x00, 0x17, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa0, 0x30, 0x81, 0x9d, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, + 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0xac, + 0x00, 0x00, 0x00, 0xa5, 0x30, 0x81, 0xa2, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x20, 0x30, 0x1e, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x17, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x4d, 0x45, 0x4e, + 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0xb8, + 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, + 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x31, 0x14, 0x30, 0x12, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, + 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, 0x6e, 0x6f, 0x62, 0x6f, + 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x69, 0x73, 0x73, 0x75, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x18, 0x14, 0x00, 0x00, 0x18, 0xbc, 0x00, 0x00, 0x19, 0x6c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa0, + 0x30, 0x81, 0x9d, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, + 0x6d, 0x69, 0x6d, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, + 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, + 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, + 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, + 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0xa5, 0x30, 0x81, 0xa2, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x17, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, 0x45, 0x4c, + 0x4f, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, + 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, + 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x6e, 0x6f, 0x62, + 0x6f, 0x64, 0x79, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, + 0x00, 0x00, 0x00, 0xb8, 0x30, 0x81, 0xb5, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x16, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x73, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x18, 0x46, 0x4f, 0x52, 0x20, 0x44, 0x45, 0x56, + 0x45, 0x4c, 0x4f, 0x50, 0x4d, 0x45, 0x4e, 0x54, 0x20, 0x55, 0x53, 0x45, 0x20, 0x4f, 0x4e, 0x4c, 0x59, 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, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x1c, + 0x6e, 0x6f, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x73, 0x6e, 0x62, 0x72, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1a, 0x5c, 0x00, 0x00, 0x1a, 0x68, + 0x00, 0x00, 0x1a, 0x74, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x04, 0x00, 0xfb, 0xff, 0xa8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x06, 0xe0, 0x2a, 0x1d, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x56, 0x81, 0x44, 0xc1, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x6b, 0x69, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0x70, 0x6b, 0x79, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x1a, 0xc8, 0x00, 0x00, 0x1a, 0xe4, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0xc7, 0xc5, 0x36, 0xbc, 0xce, 0x8e, 0x86, 0xa8, + 0x02, 0x33, 0x38, 0xb5, 0x23, 0xb6, 0xef, 0x97, 0x20, 0x1e, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, + 0xc9, 0x58, 0x3f, 0x54, 0xf7, 0x9c, 0x21, 0xee, 0x29, 0x26, 0x07, 0x8d, 0x1b, 0xb4, 0x93, 0xc4, 0x3e, 0xfd, 0x6a, 0x65, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0xd7, 0x58, 0x0b, 0xdf, 0xe7, 0x97, 0x49, 0x7e, 0xd7, 0x44, 0x80, 0x01, + 0xf5, 0xf3, 0x7f, 0xf6, 0x1d, 0x5c, 0x24, 0x16, 0x00, 0x00, 0x00, 0xe8, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa8, + 0x00, 0x00, 0x00, 0x00, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xa8, + 0x52, 0xba, 0xd6, 0xe8, 0x80, 0xd9, 0x0e, 0xbb, 0x2e, 0x64, 0x65, 0xce, 0xcd, 0xe6, 0xa9, 0x71, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xff, 0xff, 0xff, 0x00, 0x7f, 0x00, 0x00, 0x58, 0xcc, 0x46, 0xd5, 0x94, 0x46, 0x74, 0xb1, 0x30, 0x40, 0x9b, 0x78, + 0xb0, 0x30, 0x4b, 0x1a, 0xa1, 0x93, 0x58, 0x1f, 0x48, 0xd4, 0x81, 0x1e, 0x1e, 0x1e, 0xe2, 0xaf, 0xda, 0x6a, 0x3e, 0x6e, + 0x08, 0x90, 0x5e, 0xd5, 0xf1, 0xce, 0x8b, 0x78, 0x8a, 0x5e, 0xe2, 0x36, 0x45, 0x92, 0xee, 0xeb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7f, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xe6, 0xb4, 0xf8, 0xd6, 0xa3, 0x68, 0x66, 0xde, 0x70, 0xd4, 0xe0, 0xd6, 0x9a, 0x46, 0x5d, 0xbd, + 0x60, 0x41, 0x2b, 0x19, 0x2b, 0x4b, 0x55, 0x64, 0x60, 0xe4, 0x91, 0x17, 0x5e, 0xa2, 0x08, 0xe0, 0x1c, 0x6e, 0xbd, 0xf1, + 0x08, 0xfd, 0x2d, 0x7b, 0x42, 0x6a, 0x7c, 0xa3, 0x73, 0x6d, 0xb0, 0xfd, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48 +}; +unsigned int test_keychain_len = 45864; + + + +#pragma clang diagnostic pop + +#endif /* kc_file_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/keychain_regressions.h b/OSX/libsecurity_keychain/regressions/keychain_regressions.h index 89ab2b02..74b23a55 100644 --- a/OSX/libsecurity_keychain/regressions/keychain_regressions.h +++ b/OSX/libsecurity_keychain/regressions/keychain_regressions.h @@ -4,10 +4,43 @@ */ #include +ONE_TEST(kc_01_keychain_creation) +ONE_TEST(kc_02_unlock_noui) +ONE_TEST(kc_03_status) +ONE_TEST(kc_03_keychain_list) +ONE_TEST(kc_04_is_valid) +ONE_TEST(kc_05_find_existing_items) +ONE_TEST(kc_05_find_existing_items_locked) +ONE_TEST(kc_06_cert_search_email) +ONE_TEST(kc_10_item_add_generic) +ONE_TEST(kc_10_item_add_internet) +ONE_TEST(kc_10_item_add_certificate) +ONE_TEST(kc_12_key_create_symmetric) +ONE_TEST(kc_12_key_create_symmetric_and_use) +ONE_TEST(kc_15_key_update_valueref) +ONE_TEST(kc_15_item_update_label_skimaad) +ONE_TEST(kc_16_item_update_password) +ONE_TEST(kc_17_item_find_key) +ONE_TEST(kc_18_find_combined) +ONE_TEST(kc_19_item_copy_internet) +ONE_TEST(kc_20_identity_persistent_refs) +ONE_TEST(kc_20_identity_key_attributes) +ONE_TEST(kc_20_identity_find_stress) +ONE_TEST(kc_20_key_find_stress) +ONE_TEST(kc_20_item_find_stress) +ONE_TEST(kc_21_item_use_callback) +ONE_TEST(kc_21_item_xattrs) +ONE_TEST(kc_23_key_export_symmetric) +ONE_TEST(kc_24_key_copy_keychain) +ONE_TEST(kc_26_key_import_public) +ONE_TEST(kc_27_key_non_extractable) +ONE_TEST(kc_28_p12_import) +ONE_TEST(kc_28_cert_sign) ONE_TEST(kc_30_xara) ONE_TEST(kc_40_seckey) ONE_TEST(kc_41_sececkey) ONE_TEST(kc_42_trust_revocation) +ONE_TEST(kc_43_seckey_interop) ONE_TEST(si_20_sectrust_provisioning) ONE_TEST(si_33_keychain_backup) ONE_TEST(si_34_one_true_keychain) diff --git a/OSX/libsecurity_keychain/regressions/si-34-one-true-keychain.c b/OSX/libsecurity_keychain/regressions/si-34-one-true-keychain.c index 15747439..0242d399 100644 --- a/OSX/libsecurity_keychain/regressions/si-34-one-true-keychain.c +++ b/OSX/libsecurity_keychain/regressions/si-34-one-true-keychain.c @@ -97,16 +97,16 @@ static void tests(void) ok_status(SecItemAdd(noLegacyQuery, &result), "add internet password in iOS keychain"); CFDictionaryRemoveValue(noLegacyQuery, kSecValueData); - is_status(SecItemCopyMatching(query, &result), errSecItemNotFound, "do not find the ios item"); + ok_status(SecItemCopyMatching(query, &result), "find the ios item with generic query"); CFReleaseNull(result); ok_status(SecItemCopyMatching(noLegacyQuery, &result), "find the ios item with noLegacy"); CFReleaseNull(result); - is_status(SecItemCopyMatching(syncAnyQuery, &result), errSecItemNotFound, "do not find the ios item with synchronizableAny"); + ok_status(SecItemCopyMatching(syncAnyQuery, &result), "find the ios item with synchronizableAny"); CFReleaseNull(result); is_status(SecItemCopyMatching(syncQuery, &result), errSecItemNotFound, "do not find the ios item with synchronizable"); CFReleaseNull(result); - is_status(SecItemUpdate(query, toUpdate), errSecItemNotFound, "do not update the ios item"); + ok_status(SecItemUpdate(query, toUpdate), "update the ios item without any flags"); ok_status(SecItemUpdate(noLegacyQuery, toUpdate), "update the ios item with noLegacy"); ok_status(SecItemUpdate(syncAnyQuery, toUpdate), "update the ios item with synchronizableAny"); diff --git a/OSX/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist b/OSX/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist index dfe876f3..8d13a776 100644 --- a/OSX/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist +++ b/OSX/libsecurity_keychain/xpc-tsa/XPCTimeStampingService-Info.plist @@ -11,7 +11,7 @@ CFBundleIconFile CFBundleIdentifier - com.apple.security.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/libsecurity_keychain/xpc-tsa/main-tsa.m b/OSX/libsecurity_keychain/xpc-tsa/main-tsa.m index f32836de..807b1f28 100644 --- a/OSX/libsecurity_keychain/xpc-tsa/main-tsa.m +++ b/OSX/libsecurity_keychain/xpc-tsa/main-tsa.m @@ -44,7 +44,7 @@ void handle_connection_event(const xpc_connection_t peer); void handle_request_event(struct connection_info *info, xpc_object_t event); #ifndef NDEBUG - #define xpctsa_secdebug(format...) \ + #define xpctsa_secinfo(format...) \ do { \ syslog(LOG_WARNING, format); \ } while (0) @@ -55,10 +55,10 @@ void handle_request_event(struct connection_info *info, xpc_object_t event); #else //empty - #define xpctsa_secdebug(format...) + #define xpctsa_secinfo(format...) #define xpctsaNSLog(format...) #endif -#define xpctsaDebug(args...) xpctsa_secdebug(args) +#define xpctsaDebug(args...) xpctsa_secinfo(args) /* These came from: diff --git a/OSX/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist b/OSX/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist index dfe876f3..8d13a776 100644 --- a/OSX/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist +++ b/OSX/libsecurity_keychain/xpc/XPCKeychainSandboxCheck-Info.plist @@ -11,7 +11,7 @@ CFBundleIconFile CFBundleIdentifier - com.apple.security.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/OSX/libsecurity_manifest/lib/AppleManifest.cpp b/OSX/libsecurity_manifest/lib/AppleManifest.cpp index 31db9426..448b42fa 100644 --- a/OSX/libsecurity_manifest/lib/AppleManifest.cpp +++ b/OSX/libsecurity_manifest/lib/AppleManifest.cpp @@ -52,7 +52,7 @@ static void ConvertUInt64ToBytes (UInt64 length, UInt8* bytes) static void WriteLengthAndUpdate (CFMutableDataRef data, UInt64 length, CFIndex location) { // back patch the length of the list - secdebug ("manifest", "Length was %lld, patched at location %lld", length, (UInt64) location); + secinfo ("manifest", "Length was %lld, patched at location %lld", length, (UInt64) location); UInt8 lengthBytes[kLengthLength]; ConvertUInt64ToBytes (length, lengthBytes); @@ -115,7 +115,7 @@ static void WriteFileSystemItemHeader (CFMutableDataRef data, const FileSystemEn { // write the name const char* name = fsi->GetName (); - secdebug ("manifest", "\tAdding header for %s", name); + secinfo ("manifest", "\tAdding header for %s", name); uint16_t len = (uint16_t)strlen (name); AppendUInt16 (data, len); CFDataAppendBytes (data, (UInt8*) name, len); @@ -148,7 +148,7 @@ AppleManifest::~AppleManifest () void AppleManifest::AddDirectoryToManifest (CFMutableDataRef manifest, ManifestDirectoryItem* directory) { - secdebug ("manifest", "Adding directory %s to manifest", directory->GetName ()); + secinfo ("manifest", "Adding directory %s to manifest", directory->GetName ()); CFIndex currentIndex = GetCurrentLengthAndExtend (manifest); AppendUInt16 (manifest, (UInt16) kManifestDirectoryItemType); @@ -334,7 +334,7 @@ CFDataRef AppleManifest::Export (ManifestInternal& manifest) // there had better be at least one signer if (mSignerList.size () == 0) { - secdebug ("manifest", "No signers found"); + secinfo ("manifest", "No signers found"); MacOSError::throwMe (errSecManifestNoSigners); } @@ -480,7 +480,7 @@ static void ReconstructFileSystemHeader (uint32& finger, const uint8* data, File name[length] = 0; item->SetName (name); - secdebug ("manifest", " File item name is %s", name); + secinfo ("manifest", " File item name is %s", name); finger += length; @@ -488,9 +488,9 @@ static void ReconstructFileSystemHeader (uint32& finger, const uint8* data, File gid_t gid = (gid_t) ReconstructUInt32 (finger, data); mode_t mode = (mode_t) ReconstructUInt32 (finger, data); - secdebug ("manifest", " File item uid is %d", uid); - secdebug ("manifest", " File item gid is %d", gid); - secdebug ("manifest", " File item mode is %d", mode); + secinfo ("manifest", " File item uid is %d", uid); + secinfo ("manifest", " File item gid is %d", gid); + secinfo ("manifest", " File item mode is %d", mode); item->SetUID (uid); item->SetGID (gid); @@ -511,7 +511,7 @@ static void ParseItemHeader (uint32 &finger, const uint8* data, ManifestItemType void AppleManifest::ReconstructDataBlob (uint32 &finger, const uint8* data, ManifestDataBlobItem*& item) { - secdebug ("manifest", "Reconstructing data blob."); + secinfo ("manifest", "Reconstructing data blob."); item = new ManifestDataBlobItem (); u_int64_t length = ReconstructUInt64 (finger, data); item->SetLength ((size_t)length); @@ -524,7 +524,7 @@ void AppleManifest::ReconstructDataBlob (uint32 &finger, const uint8* data, Mani void AppleManifest::ReconstructDirectory (uint32 &finger, const uint8* data, ManifestDirectoryItem*& directory) { // make the directory - secdebug ("manifest", "Reconstructing directory."); + secinfo ("manifest", "Reconstructing directory."); directory = new ManifestDirectoryItem (); ReconstructFileSystemHeader (finger, data, directory); @@ -535,7 +535,7 @@ void AppleManifest::ReconstructDirectory (uint32 &finger, const uint8* data, Man void AppleManifest::ReconstructFile (uint32& finger, const uint8* data, ManifestFileItem *& file) { - secdebug ("manifest", "Reconstructing file."); + secinfo ("manifest", "Reconstructing file."); // make the file file = new ManifestFileItem (); ReconstructFileSystemHeader (finger, data, file); @@ -563,7 +563,7 @@ void AppleManifest::ReconstructFile (uint32& finger, const uint8* data, Manifest void AppleManifest::ReconstructSymLink (uint32& finger, const uint8* data, ManifestSymLinkItem*& file) { - secdebug ("manifest", "Reconstructing symlink."); + secinfo ("manifest", "Reconstructing symlink."); file = new ManifestSymLinkItem (); ReconstructFileSystemHeader (finger, data, file); @@ -575,7 +575,7 @@ void AppleManifest::ReconstructSymLink (uint32& finger, const uint8* data, Manif void AppleManifest::ReconstructOther (uint32& finger, const uint8* data, ManifestOtherItem*& other) { - secdebug ("manifest", "Reconstructing other."); + secinfo ("manifest", "Reconstructing other."); other = new ManifestOtherItem (); ReconstructFileSystemHeader (finger, data, other); } @@ -585,10 +585,12 @@ void AppleManifest::ReconstructOther (uint32& finger, const uint8* data, Manifes void AppleManifest::ReconstructManifestItemList (uint32 &finger, const uint8* data, ManifestItemList &itemList) { uint32 start = finger; - u_int64_t length = ReconstructUInt64 (finger, data); -#warning Casting from uint64 to uint32, this is ripe for overflow. - uint32 end = (uint32)(start + length); - + uint64_t length = ReconstructUInt64 (finger, data); + uint32 end = (uint32)(start + length); + + if (length > UINT32_MAX || (length + (uint64_t)start) > (uint64_t)UINT32_MAX) + MacOSError::throwMe (errSecManifestDamaged); + while (finger < end) { u_int64_t itemEnd; diff --git a/OSX/libsecurity_manifest/lib/ManifestInternal.cpp b/OSX/libsecurity_manifest/lib/ManifestInternal.cpp index 9ce1aedc..df1bfa14 100644 --- a/OSX/libsecurity_manifest/lib/ManifestInternal.cpp +++ b/OSX/libsecurity_manifest/lib/ManifestInternal.cpp @@ -108,7 +108,7 @@ void ManifestItemList::AddFileSystemObject (char* path, StringSet& exceptions, b StringSet::iterator it = exceptions.find (path); if (it != exceptions.end ()) { - secdebug ("manifest", "Did not add %s to the manifest.", path); + secinfo ("manifest", "Did not add %s to the manifest.", path); return; } @@ -223,13 +223,13 @@ void ManifestItemList::ConvertToStringSet (const char* path, CFArrayRef exceptio // always prepend the prefix -- the spec says that all items in the exception list are relative to the root std::string s = prefix + cfString (CFStringRef (dataRef)); - secdebug ("manifest", "Uncanonicalized path is %s", s.c_str ()); + secinfo ("manifest", "Uncanonicalized path is %s", s.c_str ()); // canonicalize the path and insert if successful. char realPath [PATH_MAX]; if (realpath (s.c_str (), realPath) != NULL) { - secdebug ("manifest", "Inserted path %s as an exception", realPath); + secinfo ("manifest", "Inserted path %s as an exception", realPath); exceptions.insert (realPath); } } @@ -362,7 +362,7 @@ ManifestInternal::ManifestInternal () ManifestInternal::~ManifestInternal () { - secdebug ("manifest", "Destroyed manifest internal %p", this); + secinfo ("manifest", "Destroyed manifest internal %p", this); } @@ -493,7 +493,7 @@ void FileSystemEntryItem::SetPath (char* path) // while we are at it, extract that last name of the path name and save it off as the name mName = StringTail (path); - secdebug ("manifest", "Created file item for %s with name %s", mPath.c_str (), mName.c_str ()); + secinfo ("manifest", "Created file item for %s with name %s", mPath.c_str (), mName.c_str ()); } @@ -577,7 +577,7 @@ bool ManifestFileItem::FileSystemHasTrueForks (char* pathToFile) int result = statfs (pathToFile, &st); if (result != 0) { - secdebug ("manifest", "Could not get statfs (error was %s)", strerror (errno)); + secinfo ("manifest", "Could not get statfs (error was %s)", strerror (errno)); UnixError::throwMe (); } @@ -632,7 +632,7 @@ ManifestFileItem::ManifestFileItem () : mNumForks (1) ManifestFileItem::~ManifestFileItem () { - secdebug ("manifest", "Destroyed manifest item %p for path %s", this, mPath.c_str ()); + secinfo ("manifest", "Destroyed manifest item %p for path %s", this, mPath.c_str ()); } @@ -734,7 +734,7 @@ static u_int32_t ExtractUInt32 (u_int8_t *&finger) void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name, SHA1Digest &digest, size_t &fileLength) { - secdebug ("manifest", "Creating digest for AppleDouble resource fork %s", name); + secinfo ("manifest", "Creating digest for AppleDouble resource fork %s", name); CC_SHA1_CTX digestContext; CC_SHA1_Init (&digestContext); @@ -760,7 +760,7 @@ void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name, SHA1 if (bytesRead != st.st_size) { - delete [] buffer; + delete[] buffer; UnixError::throwMe (); } @@ -801,14 +801,14 @@ void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name, SHA1 // compute the SHA1 hash CC_SHA1_Final (digest, &digestContext); - delete [] buffer; + delete[] buffer; } void ManifestFileItem::ComputeDigestForFile (char* name, SHA1Digest &digest, size_t &fileLength, struct stat &st) { - secdebug ("manifest", "Creating digest for %s", name); + secinfo ("manifest", "Creating digest for %s", name); // create a context for the digest operation CC_SHA1_CTX digestContext; @@ -865,7 +865,7 @@ void ManifestFileItem::Compare (ManifestItem *manifestItem, bool compareOwnerAnd ManifestFileItem* item = static_cast< ManifestFileItem*>(manifestItem); - secdebug ("manifest", "Comparing file item %s against %s", GetName (), item->GetName ()); + secinfo ("manifest", "Comparing file item %s against %s", GetName (), item->GetName ()); // the number of forks should be equal if (mNumForks != item->mNumForks) @@ -903,7 +903,7 @@ ManifestDirectoryItem::ManifestDirectoryItem () ManifestDirectoryItem::~ManifestDirectoryItem () { - secdebug ("manifest", "Destroyed directory item %p for path %s", this, mPath.c_str ()); + secinfo ("manifest", "Destroyed directory item %p for path %s", this, mPath.c_str ()); } @@ -995,7 +995,7 @@ void ManifestDirectoryItem::SetPath (char* path, StringSet &exceptions, bool isR FileSystemEntryItem::SetPath (path); } - secdebug ("manifest", "Added directory entry for %s with name %s", mPath.c_str (), mName.c_str ()); + secinfo ("manifest", "Added directory entry for %s with name %s", mPath.c_str (), mName.c_str ()); // enumerate the contents of the directory. char* path_argv[] = { path, NULL }; @@ -1050,7 +1050,7 @@ void ManifestDirectoryItem::Compare (ManifestItem* a, bool compareOwnerAndGroup) { FileSystemEntryItem::Compare (a, compareOwnerAndGroup); ManifestDirectoryItem* aa = static_cast(a); - secdebug ("manifest", "Comparing directory item %s against %s", GetName (), aa->GetName ()); + secinfo ("manifest", "Comparing directory item %s against %s", GetName (), aa->GetName ()); mDirectoryItems.Compare (aa->mDirectoryItems, compareOwnerAndGroup); } @@ -1068,7 +1068,7 @@ ManifestSymLinkItem::ManifestSymLinkItem () ManifestSymLinkItem::~ManifestSymLinkItem () { - secdebug ("manifest", "Destroyed symlink item for %s", mPath.c_str ()); + secinfo ("manifest", "Destroyed symlink item for %s", mPath.c_str ()); } @@ -1077,7 +1077,7 @@ void ManifestSymLinkItem::ComputeRepresentation () { char path [FILENAME_MAX]; int result = (int)readlink (mPath.c_str (), path, sizeof (path)); - secdebug ("manifest", "Read content %s for %s", path, mPath.c_str ()); + secinfo ("manifest", "Read content %s for %s", path, mPath.c_str ()); // create a digest context CC_SHA1_CTX digestContext; @@ -1119,7 +1119,7 @@ void ManifestSymLinkItem::Compare (ManifestItem *a, bool compareOwnerAndGroup) { FileSystemEntryItem::Compare (a, compareOwnerAndGroup); ManifestSymLinkItem* aa = static_cast(a); - secdebug ("manifest", "Comparing symlink item %s against %s", GetName (), aa->GetName ()); + secinfo ("manifest", "Comparing symlink item %s against %s", GetName (), aa->GetName ()); // now compare the data if (memcmp (&mDigest, &aa->mDigest, kSHA1DigestSize) != 0) @@ -1142,7 +1142,7 @@ ManifestOtherItem::ManifestOtherItem () ManifestOtherItem::~ManifestOtherItem () { - secdebug ("manifest", "Destroyed other item for path %s", mPath.c_str ()); + secinfo ("manifest", "Destroyed other item for path %s", mPath.c_str ()); } @@ -1157,5 +1157,5 @@ ManifestItemType ManifestOtherItem::GetItemType () void ManifestOtherItem::Compare (ManifestItem *a, bool compareOwnerAndGroup) { FileSystemEntryItem::Compare (a, compareOwnerAndGroup); - secdebug ("manifest", "Comparing other item %s against %s", GetName (), static_cast(a)->GetName ()); + secinfo ("manifest", "Comparing other item %s against %s", GetName (), static_cast(a)->GetName ()); } diff --git a/OSX/libsecurity_manifest/lib/SecManifest.cpp b/OSX/libsecurity_manifest/lib/SecManifest.cpp index fb0b6bdb..401c193b 100644 --- a/OSX/libsecurity_manifest/lib/SecManifest.cpp +++ b/OSX/libsecurity_manifest/lib/SecManifest.cpp @@ -45,7 +45,7 @@ OSStatus SecManifestGetVersion (UInt32 *version) { - secdebug ("manifest", "SecManifestGetVersion"); + secinfo ("manifest", "SecManifestGetVersion"); *version = 0x01000000; return errSecSuccess; } @@ -59,7 +59,7 @@ OSStatus SecManifestCreate(SecManifestRef *manifest) Manifest* manifestPtr = new Manifest (); *manifest = (SecManifestRef) manifestPtr; - secdebug ("manifest", "SecManifestCreate(%p)", manifest); + secinfo ("manifest", "SecManifestCreate(%p)", manifest); API_END } @@ -71,12 +71,14 @@ void SecManifestRelease (SecManifestRef manifest) delete (Manifest*) manifest; } - - +// On release builds, this function isn't called (due to how secinfo works). Assure the compiler this is okay. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" static const char* GetDescription (CFTypeRef object) { return CFStringGetCStringPtr (CFCopyDescription (object), kCFStringEncodingMacRoman); } +#pragma clang pop @@ -103,7 +105,7 @@ OSStatus SecManifestVerifySignatureWithPolicy (CFDataRef data, { API_BEGIN - secdebug ("manifest", "SecManifestVerifySignature (%s, %p, %p, %p, %p)", GetDescription (data), setupCallback, setupContext, evaluateCallback, evaluateContext); + secinfo ("manifest", "SecManifestVerifySignature (%s, %p, %p, %p, %p)", GetDescription (data), setupCallback, setupContext, evaluateCallback, evaluateContext); Required (setupCallback); Required (evaluateCallback); @@ -143,7 +145,7 @@ OSStatus SecManifestCreateSignature(SecManifestRef manifest, UInt32 options, CFD { API_BEGIN - secdebug ("manifest", "SecManifestCreateSignature(%p, %ul, %p)", manifest, (unsigned int) options, data); + secinfo ("manifest", "SecManifestCreateSignature(%p, %ul, %p)", manifest, (unsigned int) options, data); Manifest* manifestPtr = (Manifest*) manifest; if (options != 0) @@ -170,7 +172,7 @@ OSStatus SecManifestAddObject(SecManifestRef manifest, CFTypeRef object, CFArray { API_BEGIN - secdebug ("manifest", "SecManifestAddObject(%p), %s, %s", + secinfo ("manifest", "SecManifestAddObject(%p), %s, %s", manifest, GetDescription (object), exceptionList ? GetDescription (exceptionList) : "NULL"); @@ -186,7 +188,7 @@ OSStatus SecManifestCompare(SecManifestRef manifest1, SecManifestRef manifest2, { API_BEGIN - secdebug ("manifest", "SecManifestVerify(%p, %p, %d)", manifest1, manifest2, (int) options); + secinfo ("manifest", "SecManifestVerify(%p, %p, %d)", manifest1, manifest2, (int) options); ManifestInternal &m1 = ((Manifest*) (manifest1))->GetManifestInternal (); ManifestInternal &m2 = ((Manifest*) (manifest2))->GetManifestInternal (); @@ -202,7 +204,7 @@ OSStatus SecManifestAddSigner(SecManifestRef manifest, SecIdentityRef identity) { API_BEGIN - secdebug ("manifest", "SecManifestAddSigner(%p, %p)", manifest, identity); + secinfo ("manifest", "SecManifestAddSigner(%p, %p)", manifest, identity); Manifest* manifestPtr = (Manifest*) (manifest); // check to see if there is a serializer present diff --git a/OSX/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj b/OSX/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj index 4e2157cc..6c31b8c5 100644 --- a/OSX/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_manifest/libsecurity_manifest.xcodeproj/project.pbxproj @@ -55,16 +55,16 @@ D60C834809F5AD980069DF6D /* SecureDownloadInternal.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = SecureDownloadInternal.c; path = lib/SecureDownloadInternal.c; sourceTree = ""; }; D60C834909F5AD980069DF6D /* SecureDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SecureDownloadInternal.h; path = lib/SecureDownloadInternal.h; sourceTree = ""; }; D637ECC205DA85AD0096F1E6 /* Manifest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Manifest.cpp; path = lib/Manifest.cpp; sourceTree = ""; }; - D637ECC305DA85AD0096F1E6 /* SecManifest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SecManifest.cpp; path = lib/SecManifest.cpp; sourceTree = ""; }; + D637ECC305DA85AD0096F1E6 /* SecManifest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = SecManifest.cpp; path = lib/SecManifest.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; D658622605DA860900E7380F /* Manifest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Manifest.h; path = lib/Manifest.h; sourceTree = ""; }; D658622705DA860900E7380F /* SecManifest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SecManifest.h; path = lib/SecManifest.h; sourceTree = ""; }; D658622E05DA866200E7380F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; D658627305DA867300E7380F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; D6C8AFAE05DD2430003DB724 /* libsecurity_manifest.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_manifest.a; sourceTree = BUILT_PRODUCTS_DIR; }; D6C8AFE005DD2FF8003DB724 /* security_manifest.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; name = security_manifest.exp; path = lib/security_manifest.exp; sourceTree = ""; }; - D6CDE5B805E3DBD9006C8558 /* AppleManifest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AppleManifest.cpp; path = lib/AppleManifest.cpp; sourceTree = ""; }; + D6CDE5B805E3DBD9006C8558 /* AppleManifest.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = AppleManifest.cpp; path = lib/AppleManifest.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; D6CDE5B905E3DBD9006C8558 /* AppleManifest.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AppleManifest.h; path = lib/AppleManifest.h; sourceTree = ""; }; - D6E7672205F3F8B6007C5669 /* ManifestInternal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ManifestInternal.cpp; path = lib/ManifestInternal.cpp; sourceTree = ""; }; + D6E7672205F3F8B6007C5669 /* ManifestInternal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = ManifestInternal.cpp; path = lib/ManifestInternal.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; D6E7672305F3F8B6007C5669 /* ManifestInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ManifestInternal.h; path = lib/ManifestInternal.h; sourceTree = ""; }; D6E7672405F3F8B6007C5669 /* ManifestSigner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ManifestSigner.cpp; path = lib/ManifestSigner.cpp; sourceTree = ""; }; D6E7672505F3F8B6007C5669 /* ManifestSigner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ManifestSigner.h; path = lib/ManifestSigner.h; sourceTree = ""; }; @@ -194,7 +194,6 @@ buildRules = ( ); dependencies = ( - 182BB32B146F0F8B000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_manifest; productName = libsecurity_manifest; @@ -207,7 +206,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD39A0987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_manifest" */; compatibilityVersion = "Xcode 3.2"; @@ -308,12 +307,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB31F146F0F07000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -321,12 +329,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB31F146F0F07000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_mds/lib/MDSAttrParser.cpp b/OSX/libsecurity_mds/lib/MDSAttrParser.cpp index 1a8a9650..27b9261d 100644 --- a/OSX/libsecurity_mds/lib/MDSAttrParser.cpp +++ b/OSX/libsecurity_mds/lib/MDSAttrParser.cpp @@ -29,6 +29,7 @@ #include "MDSAttrUtils.h" #include "MDSDictionary.h" #include +#include #include namespace Security @@ -101,10 +102,10 @@ Parsing bundle { void MDSAttrParser::parseAttrs(CFStringRef subdir) { /* get all *.mdsinfo files */ - CFArrayRef bundleInfoFiles = CFBundleCopyResourceURLsOfType(mBundle, + CFRef bundleInfoFiles = CFBundleCopyResourceURLsOfType(mBundle, CFSTR(MDS_INFO_TYPE), subdir); - if(bundleInfoFiles == NULL) { + if(!bundleInfoFiles) { Syslog::alert("MDSAttrParser: no mdsattr files for %s", mPath); return; } @@ -128,7 +129,7 @@ void MDSAttrParser::parseAttrs(CFStringRef subdir) } // @@@ Workaround for 4234967: skip any filename beginning with "._" - CFStringRef lastComponent = CFURLCopyLastPathComponent(infoUrl); + CFRef lastComponent = CFURLCopyLastPathComponent(infoUrl); if (lastComponent) { CFStringRef resFilePfx = CFSTR("._"); // setting the search length and location like this permits, @@ -140,7 +141,6 @@ void MDSAttrParser::parseAttrs(CFStringRef subdir) range, 0/*options*/, NULL/*returned substr*/); - CFRelease(lastComponent); if (skip == true) { Syslog::warning("MDSAttrParser: ignoring resource file"); continue; @@ -149,7 +149,6 @@ void MDSAttrParser::parseAttrs(CFStringRef subdir) parseFile(infoUrl, subdir); } /* for each mdsinfo */ - CF_RELEASE(bundleInfoFiles); } void MDSAttrParser::parseFile(CFURLRef infoUrl, CFStringRef subdir) @@ -438,14 +437,11 @@ void MDSAttrParser::parseCspCapabilitiesRecord( mdsDict->lookupAttributes(&CSPCapabilitiesDict1RelInfo, outAttrs, numTopLevelAttrs); - bool fetchedFromDisk = false; - /* obtain Capabilities array */ - CFArrayRef capArray = (CFArrayRef)mdsDict->lookupWithIndirect("Capabilities", + CFRef capArray = (CFArrayRef)mdsDict->lookupWithIndirect("Capabilities", mBundle, - CFArrayGetTypeID(), - fetchedFromDisk); - if(capArray == NULL) { + CFArrayGetTypeID()); + if(!capArray) { /* well we did not get very far.... */ MPDebug("parseCspCapabilitiesRecord: no (or bad) Capabilities"); delete [] outAttrs; @@ -543,9 +539,6 @@ void MDSAttrParser::parseCspCapabilitiesRecord( MDSFreeDbRecordAttrs(outAttrs, numTopLevelAttrs); delete [] outAttrs; - if(fetchedFromDisk) { - CF_RELEASE(capArray); - } } /* diff --git a/OSX/libsecurity_mds/lib/MDSAttrUtils.h b/OSX/libsecurity_mds/lib/MDSAttrUtils.h index 8ad06a4f..346d209b 100644 --- a/OSX/libsecurity_mds/lib/MDSAttrUtils.h +++ b/OSX/libsecurity_mds/lib/MDSAttrUtils.h @@ -34,10 +34,10 @@ #include "MDSSession.h" /* log parsing events */ -#define MPDebug(args...) secdebug("MDS_Parse", ## args) +#define MPDebug(args...) secinfo("MDS_Parse", ## args) /* log scanning events */ -#define MSDebug(args...) secdebug("MDS_Scan", ## args) +#define MSDebug(args...) secinfo("MDS_Scan", ## args) /* * I can't believe that CFRelease does not do this... diff --git a/OSX/libsecurity_mds/lib/MDSDatabase.cpp b/OSX/libsecurity_mds/lib/MDSDatabase.cpp index fb388dae..b9c2bfe5 100644 --- a/OSX/libsecurity_mds/lib/MDSDatabase.cpp +++ b/OSX/libsecurity_mds/lib/MDSDatabase.cpp @@ -48,7 +48,7 @@ MDSDatabase::~MDSDatabase () DbContext * MDSDatabase::makeDbContext (DatabaseSession &inDatabaseSession, CSSM_DB_ACCESS_TYPE inAccessRequest, - const CSSM_ACCESS_CREDENTIALS *inAccessCred, + const AccessCredentials *inAccessCred, const void *inOpenParameters) { return new DbContext (*this, inDatabaseSession, inAccessRequest, @@ -75,7 +75,7 @@ MDSDatabase::createRelation(DbContext &dbContext, CSSM_DB_RECORDTYPE inRelationID, const char *inRelationName, uint32 inNumberOfAttributes, - const CSSM_DB_SCHEMA_ATTRIBUTE_INFO &inAttributeInfo, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, uint32 inNumberOfIndexes, const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo) { @@ -176,7 +176,7 @@ MDSDatabase::dbCreate (DbContext &inDbContext, const CSSM_DBINFO &inDBInfo, void MDSDatabase::dbDelete (DatabaseSession &inDatabaseSession, - const CSSM_ACCESS_CREDENTIALS *inAccessCred) + const AccessCredentials *inAccessCred) { CssmError ::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } @@ -184,7 +184,7 @@ MDSDatabase::dbDelete (DatabaseSession &inDatabaseSession, void MDSDatabase::authenticate(DbContext &dbContext, CSSM_DB_ACCESS_TYPE inAccessRequest, - const CSSM_ACCESS_CREDENTIALS &inAccessCred) + const AccessCredentials &inAccessCred) { CssmError ::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } @@ -200,7 +200,7 @@ MDSDatabase::getDbAcl(DbContext &dbContext, void MDSDatabase::changeDbAcl(DbContext &dbContext, - const CSSM_ACCESS_CREDENTIALS &inAccessCred, + const AccessCredentials &inAccessCred, const CSSM_ACL_EDIT &inAclEdit) { CssmError ::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); @@ -214,7 +214,7 @@ MDSDatabase::getDbOwner(DbContext &dbContext, CSSM_ACL_OWNER_PROTOTYPE &outOwner void MDSDatabase::changeDbOwner(DbContext &dbContext, - const CSSM_ACCESS_CREDENTIALS &inAccessCred, + const AccessCredentials &inAccessCred, const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner) { CssmError ::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); diff --git a/OSX/libsecurity_mds/lib/MDSDatabase.h b/OSX/libsecurity_mds/lib/MDSDatabase.h index 0849fe5a..500af73b 100644 --- a/OSX/libsecurity_mds/lib/MDSDatabase.h +++ b/OSX/libsecurity_mds/lib/MDSDatabase.h @@ -52,7 +52,7 @@ public: DbContext * makeDbContext(DatabaseSession &inDatabaseSession, CSSM_DB_ACCESS_TYPE inAccessRequest, - const CSSM_ACCESS_CREDENTIALS *inAccessCred, + const AccessCredentials *inAccessCred, const void *inOpenParameters); virtual void @@ -67,14 +67,14 @@ public: virtual void dbDelete(DatabaseSession &inDatabaseSession, - const CSSM_ACCESS_CREDENTIALS *inAccessCred); + const AccessCredentials *inAccessCred); virtual void createRelation (DbContext &dbContext, CSSM_DB_RECORDTYPE inRelationID, const char *inRelationName, uint32 inNumberOfAttributes, - const CSSM_DB_SCHEMA_ATTRIBUTE_INFO &inAttributeInfo, + const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *inAttributeInfo, uint32 inNumberOfIndexes, const CSSM_DB_SCHEMA_INDEX_INFO &inIndexInfo); @@ -84,7 +84,7 @@ public: virtual void authenticate(DbContext &dbContext, CSSM_DB_ACCESS_TYPE inAccessRequest, - const CSSM_ACCESS_CREDENTIALS &inAccessCred); + const AccessCredentials &inAccessCred); virtual void getDbAcl(DbContext &dbContext, @@ -94,7 +94,7 @@ public: virtual void changeDbAcl(DbContext &dbContext, - const CSSM_ACCESS_CREDENTIALS &inAccessCred, + const AccessCredentials &inAccessCred, const CSSM_ACL_EDIT &inAclEdit); virtual void @@ -102,7 +102,7 @@ public: virtual void changeDbOwner(DbContext &dbContext, - const CSSM_ACCESS_CREDENTIALS &inAccessCred, + const AccessCredentials &inAccessCred, const CSSM_ACL_OWNER_PROTOTYPE &inNewOwner); virtual char * diff --git a/OSX/libsecurity_mds/lib/MDSDictionary.cpp b/OSX/libsecurity_mds/lib/MDSDictionary.cpp index 604e0403..6bae2b8e 100644 --- a/OSX/libsecurity_mds/lib/MDSDictionary.cpp +++ b/OSX/libsecurity_mds/lib/MDSDictionary.cpp @@ -387,10 +387,7 @@ void MDSDictionary::lookupAttributes( const CFPropertyListRef MDSDictionary::lookupWithIndirect( const char *key, CFBundleRef bundle, - CFTypeID desiredType, - bool &fetchedFromDisk) // true --> caller must CFRelease the returned - // value - // false -> it's part of this dictionary + CFTypeID desiredType) { CFPropertyListRef ourRtn = NULL; CFDataRef dictData = NULL; @@ -402,8 +399,6 @@ const CFPropertyListRef MDSDictionary::lookupWithIndirect( assert(key != NULL); assert(bundle != NULL); - fetchedFromDisk = false; - /* basic local lookup */ CFStringRef cfKey = CFStringCreateWithCString(NULL, key, @@ -412,22 +407,22 @@ const CFPropertyListRef MDSDictionary::lookupWithIndirect( MPDebug("CFStringCreateWithCString error"); return NULL; } - const void *rtn = CFDictionaryGetValue(mDict, cfKey); + CFCopyRef rtn = (CFStringRef)CFDictionaryGetValue(mDict, cfKey); CFRelease(cfKey); - if(rtn == NULL) { + if(!rtn) { return NULL; } - CFTypeID foundType = CFGetTypeID((CFTypeRef)rtn); + CFTypeID foundType = CFGetTypeID(rtn); if(foundType == desiredType) { /* found what we're looking for; done */ - return (CFPropertyListRef)rtn; + return (CFPropertyListRef)rtn.yield(); } /* is it a string which starts with "file:"? */ if(foundType != CFStringGetTypeID()) { return NULL; } - const char *cVal = MDSCFStringToCString((CFStringRef)rtn); + const char *cVal = MDSCFStringToCString(rtn); if(cVal == NULL) { MPDebug("MDSCFStringToCString error in lookupWithIndirect"); return NULL; @@ -490,8 +485,7 @@ const CFPropertyListRef MDSDictionary::lookupWithIndirect( } MPDebug("lookupWithIndirect: resource %s FOUND", cVal); - fetchedFromDisk = true; - + abort: delete [] cVal; CF_RELEASE(cfFileName); diff --git a/OSX/libsecurity_mds/lib/MDSDictionary.h b/OSX/libsecurity_mds/lib/MDSDictionary.h index 25839526..04916659 100644 --- a/OSX/libsecurity_mds/lib/MDSDictionary.h +++ b/OSX/libsecurity_mds/lib/MDSDictionary.h @@ -107,11 +107,7 @@ public: const CFPropertyListRef lookupWithIndirect( const char *key, CFBundleRef bundle, - CFTypeID desiredType, - bool &fetchedFromDisk); // true --> caller must CFRelease the returned - // value - // false -> it's part of this dictionary - + CFTypeID desiredType); void setDefaults(const MDS_InstallDefaults *defaults); private: diff --git a/OSX/libsecurity_mds/lib/MDSModule.cpp b/OSX/libsecurity_mds/lib/MDSModule.cpp index ebf050cb..4a3716a1 100644 --- a/OSX/libsecurity_mds/lib/MDSModule.cpp +++ b/OSX/libsecurity_mds/lib/MDSModule.cpp @@ -127,7 +127,7 @@ void MDSModule::setDbPath(const char *path) void MDSModule::setServerMode() { - secdebug("MDSModule", "setting global server mode"); + secinfo("MDSModule", "setting global server mode"); mServerMode = true; } diff --git a/OSX/libsecurity_mds/lib/MDSSession.cpp b/OSX/libsecurity_mds/lib/MDSSession.cpp index 93c13f4f..d91669a5 100644 --- a/OSX/libsecurity_mds/lib/MDSSession.cpp +++ b/OSX/libsecurity_mds/lib/MDSSession.cpp @@ -126,10 +126,10 @@ namespace Security #define MDS_SCAN_INTERVAL 5 /* trace file I/O */ -#define MSIoDbg(args...) secdebug("MDS_IO", ## args) +#define MSIoDbg(args...) secinfo("MDS_IO", ## args) /* Trace cleanDir() */ -#define MSCleanDirDbg(args...) secdebug("MDS_CleanDir", ## args) +#define MSCleanDirDbg(args...) secinfo("MDS_CleanDir", ## args) static std::string GetMDSBaseDBDir(bool isRoot) { @@ -766,11 +766,11 @@ MDSSession::LockHelper::obtainLock( { mFD = -1; for(;;) { - secdebug("mdslock", "obtainLock: calling open(%s)", lockFile); + secinfo("mdslock", "obtainLock: calling open(%s)", lockFile); mFD = open(lockFile, O_EXLOCK | O_CREAT | O_RDWR, 0644); if(mFD == -1) { int err = errno; - secdebug("mdslock", "obtainLock: open error %d", errno); + secinfo("mdslock", "obtainLock: open error %d", errno); if(err == EINTR) { /* got a signal, go again */ continue; @@ -781,7 +781,7 @@ MDSSession::LockHelper::obtainLock( } } else { - secdebug("mdslock", "obtainLock: success"); + secinfo("mdslock", "obtainLock: success"); return true; } } @@ -797,7 +797,7 @@ MDSSession::LockHelper::obtainLock( MDSSession::LockHelper::~LockHelper() { - secdebug("mdslock", "releaseLock"); + secinfo("mdslock", "releaseLock"); if (mFD == -1) { return; diff --git a/OSX/libsecurity_mds/lib/mds.h b/OSX/libsecurity_mds/lib/mds.h index cc75ad2e..c2d590e4 100644 --- a/OSX/libsecurity_mds/lib/mds.h +++ b/OSX/libsecurity_mds/lib/mds.h @@ -33,6 +33,9 @@ extern "C" { #endif +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + typedef CSSM_DL_HANDLE MDS_HANDLE; typedef CSSM_DL_DB_HANDLE MDS_DB_HANDLE; @@ -146,6 +149,8 @@ CSSM_RETURN CSSMAPI MDS_Uninstall (MDS_HANDLE MdsHandle) DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER; +#pragma clang diagnostic pop + #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_mds/lib/mdsapi.cpp b/OSX/libsecurity_mds/lib/mdsapi.cpp index a23fe744..d594fa9b 100644 --- a/OSX/libsecurity_mds/lib/mdsapi.cpp +++ b/OSX/libsecurity_mds/lib/mdsapi.cpp @@ -37,7 +37,7 @@ #include #include -#define MSApiDebug(args...) secdebug("MDS_API", ## args) +#define MSApiDebug(args...) secinfo("MDS_API", ## args) /* Protects access to AppleDataBase */ ModuleNexus adbMutex; diff --git a/OSX/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj b/OSX/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj index a7569125..195b6bba 100644 --- a/OSX/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_mds/libsecurity_mds.xcodeproj/project.pbxproj @@ -37,13 +37,6 @@ remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; remoteInfo = libsecurity_cdsa_plugin; }; - 182BB369146F1259000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB362146F1255000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -52,22 +45,22 @@ 182BB360146F11F1000BF1F3 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; 182BB361146F11F1000BF1F3 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; 182BB362146F1255000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libsecurity_cdsa_plugin.xcodeproj; path = ../libsecurity_cdsa_plugin/libsecurity_cdsa_plugin.xcodeproj; sourceTree = ""; }; - 4C308389053237100028A8C6 /* mdsapi.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = mdsapi.cpp; sourceTree = ""; }; + 4C308389053237100028A8C6 /* mdsapi.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = mdsapi.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C30838A053237100028A8C6 /* MDSAttrParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSAttrParser.cpp; sourceTree = ""; }; 4C30838B053237100028A8C6 /* MDSAttrParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSAttrParser.h; sourceTree = ""; }; 4C30838C053237100028A8C6 /* MDSAttrStrings.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSAttrStrings.cpp; sourceTree = ""; }; 4C30838D053237100028A8C6 /* MDSAttrStrings.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSAttrStrings.h; sourceTree = ""; }; 4C30838E053237100028A8C6 /* MDSAttrUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSAttrUtils.cpp; sourceTree = ""; }; - 4C30838F053237100028A8C6 /* MDSAttrUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSAttrUtils.h; sourceTree = ""; }; + 4C30838F053237100028A8C6 /* MDSAttrUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MDSAttrUtils.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 4C308390053237100028A8C6 /* MDSDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSDatabase.cpp; sourceTree = ""; }; 4C308391053237100028A8C6 /* MDSDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSDatabase.h; sourceTree = ""; }; 4C308392053237100028A8C6 /* MDSDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSDictionary.cpp; sourceTree = ""; }; 4C308393053237100028A8C6 /* MDSDictionary.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSDictionary.h; sourceTree = ""; }; - 4C308394053237100028A8C6 /* MDSModule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSModule.cpp; sourceTree = ""; }; + 4C308394053237100028A8C6 /* MDSModule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MDSModule.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C308395053237100028A8C6 /* MDSModule.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSModule.h; sourceTree = ""; }; 4C308398053237100028A8C6 /* MDSSchema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSSchema.cpp; sourceTree = ""; }; 4C308399053237100028A8C6 /* MDSSchema.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSSchema.h; sourceTree = ""; }; - 4C30839A053237100028A8C6 /* MDSSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MDSSession.cpp; sourceTree = ""; usesTabs = 1; }; + 4C30839A053237100028A8C6 /* MDSSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MDSSession.cpp; sourceTree = ""; usesTabs = 1; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4C30839B053237100028A8C6 /* MDSSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MDSSession.h; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_mds.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_mds.a; sourceTree = BUILT_PRODUCTS_DIR; }; 4CCB008B05800B0B00981D43 /* security_mds.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; path = security_mds.exp; sourceTree = ""; }; @@ -188,7 +181,6 @@ buildRules = ( ); dependencies = ( - 182BB36A146F1259000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_mds; productName = libsecurity_mds; @@ -201,7 +193,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3A80987FCDE001272E0 /* Build configuration list for PBXProject "libsecurity_mds" */; compatibilityVersion = "Xcode 3.2"; @@ -255,14 +247,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 182BB36A146F1259000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB369146F1259000BF1F3 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ C27AD3A50987FCDE001272E0 /* Debug */ = { isa = XCBuildConfiguration; @@ -292,13 +276,22 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB360146F11F1000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -306,13 +299,20 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB360146F11F1000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_ocspd/common/ocspdDebug.h b/OSX/libsecurity_ocspd/common/ocspdDebug.h index 65f5b6d3..4a25566c 100644 --- a/OSX/libsecurity_ocspd/common/ocspdDebug.h +++ b/OSX/libsecurity_ocspd/common/ocspdDebug.h @@ -26,41 +26,13 @@ #include -/* If OCSP_USE_SYSLOG is defined and not 0, use syslog() for debug - * logging in addition to invoking the secdebug macro (which, as of - * Snow Leopard, emits a static dtrace probe instead of an actual - * log message.) - */ -#ifndef OCSP_USE_SYSLOG -#define OCSP_USE_SYSLOG 0 -#endif - -#if OCSP_USE_SYSLOG -#include -#define ocsp_secdebug(scope, format...) \ -{ \ - syslog(LOG_NOTICE, format); \ - secdebug(scope, format); \ -} -#else -#define ocsp_secdebug(scope, format...) \ - secdebug(scope, format) -#endif - -#ifdef NDEBUG -/* this actually compiles to nothing */ -#define ocspdErrorLog(args...) ocsp_secdebug("ocspdError", ## args) -#else -/*#define ocspdErrorLog(args...) printf(args)*/ -#define ocspdErrorLog(args...) ocsp_secdebug("ocspdError", ## args) -#endif - -#define ocspdDebug(args...) ocsp_secdebug("ocspd", ## args) -#define ocspdDbDebug(args...) ocsp_secdebug("ocspdDb", ## args) -#define ocspdCrlDebug(args...) ocsp_secdebug("ocspdCrlDebug", ## args) -#define ocspdTrustDebug(args...) ocsp_secdebug("ocspdTrustDebug", ## args) -#define ocspdHttpDebug(args...) ocsp_secdebug("ocspdHttp", ## args) -#define ocspdLdapDebug(args...) ocsp_secdebug("ocspdLdap", ## args) +#define ocspdErrorLog(args...) secnotice("ocspdError", ## args) +#define ocspdDebug(args...) secinfo("ocspd", ## args) +#define ocspdDbDebug(args...) secinfo("ocspdDb", ## args) +#define ocspdCrlDebug(args...) secinfo("ocspdCrlDebug", ## args) +#define ocspdTrustDebug(args...) secinfo("ocspdTrustDebug", ## args) +#define ocspdHttpDebug(args...) secinfo("ocspdHttp", ## args) +#define ocspdLdapDebug(args...) secinfo("ocspdLdap", ## args) #endif /* _OCSPD_DEBUGGING_H_ */ diff --git a/OSX/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj b/OSX/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj index 20bcbb03..dc39772d 100644 --- a/OSX/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_ocspd/libsecurity_ocspd.xcodeproj/project.pbxproj @@ -52,7 +52,7 @@ 051BDB6D069B36CD00F9D07E /* mig.mk */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = mig.mk; sourceTree = ""; }; 051BDB6E069B36CD00F9D07E /* ocspd.defs */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.mig; path = ocspd.defs; sourceTree = ""; }; 051BDB71069B36EA00F9D07E /* ocspd_client.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ocspd_client.cpp; path = derived_src/security_ocspd/ocspd_client.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; - 056FCCE6069B389300F710C4 /* ocspdDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ocspdDebug.h; path = common/ocspdDebug.h; sourceTree = SOURCE_ROOT; }; + 056FCCE6069B389300F710C4 /* ocspdDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = ocspdDebug.h; path = common/ocspdDebug.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 056FCCEE069B390A00F710C4 /* ocspd.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ocspd.h; path = derived_src/security_ocspd/ocspd.h; sourceTree = BUILT_PRODUCTS_DIR; }; 056FCCEF069B390A00F710C4 /* ocspd_server.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ocspd_server.cpp; path = derived_src/security_ocspd/ocspd_server.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; 056FCDBE069B429900F710C4 /* ocspdTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ocspdTypes.h; sourceTree = ""; }; @@ -220,7 +220,6 @@ buildRules = ( ); dependencies = ( - 182BB3C3146F1D93000BF1F3 /* PBXTargetDependency */, 18446129146E88C600B12992 /* PBXTargetDependency */, ); name = libsecurity_ocspd; @@ -235,7 +234,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3BA0987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_ocspd" */; compatibilityVersion = "Xcode 3.2"; @@ -278,12 +277,17 @@ files = ( ); inputPaths = ( + "$(SRCROOT)/", + "$(SRCROOT)/mig/", + "$(SRCROOT)/client/", + "$(SRCROOT)/common/", ); outputPaths = ( + "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "nmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; + shellScript = "# with our source directories as input files, Xcode will only re-run this phase if there's been a source change\nnmedit -p \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\"\nranlib \"${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}\""; }; /* End PBXShellScriptBuildPhase section */ @@ -358,13 +362,22 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1844612D146E894C00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -372,13 +385,20 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1844612D146E894C00B12992 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_pkcs12/lib/pkcs12Debug.h b/OSX/libsecurity_pkcs12/lib/pkcs12Debug.h index 7e0b97cd..066e3f11 100644 --- a/OSX/libsecurity_pkcs12/lib/pkcs12Debug.h +++ b/OSX/libsecurity_pkcs12/lib/pkcs12Debug.h @@ -32,7 +32,7 @@ #ifdef NDEBUG /* this actually compiles to nothing */ -#define p12ErrorLog(args...) secdebug("p12Error", ## args) +#define p12ErrorLog(args...) secinfo("p12Error", ## args) #define p12LogCssmError(op, err) #else #define p12ErrorLog(args...) printf(args) @@ -40,9 +40,9 @@ #endif /* individual debug loggers */ -#define p12DecodeLog(args...) secdebug("p12Decode", ## args) -#define p12EncodeLog(args...) secdebug("p12Encode", ## args) -#define p12CryptoLog(args...) secdebug("p12Crypto", ## args) +#define p12DecodeLog(args...) secinfo("p12Decode", ## args) +#define p12EncodeLog(args...) secinfo("p12Encode", ## args) +#define p12CryptoLog(args...) secinfo("p12Crypto", ## args) #endif /* _PKCS12_TEMPLATES_H_ */ diff --git a/OSX/libsecurity_pkcs12/lib/pkcs12Utils.cpp b/OSX/libsecurity_pkcs12/lib/pkcs12Utils.cpp index 7ad4593c..618ea3de 100644 --- a/OSX/libsecurity_pkcs12/lib/pkcs12Utils.cpp +++ b/OSX/libsecurity_pkcs12/lib/pkcs12Utils.cpp @@ -133,14 +133,18 @@ CSSM_DATA_PTR p12StringToUtf8( if(cfStr == NULL) { return NULL; } - CFIndex strLen = CFStringGetLength(cfStr); + + CFIndex strLen = 0; + CFRange range = { 0, CFStringGetLength(cfStr) }; + CFStringGetBytes(cfStr, range, kCFStringEncodingUTF8, 0, FALSE, NULL, 0, &strLen); if(strLen == 0) { return NULL; } + CSSM_DATA_PTR rtn = coder.mallocn(); - coder.allocItem(*rtn, strLen + 1); - if(!CFStringGetCString(cfStr, (char *)rtn->Data,strLen + 1, - kCFStringEncodingUTF8)) { + coder.allocItem(*rtn, strLen); + + if(!CFStringGetBytes(cfStr, range, kCFStringEncodingUTF8, 0, FALSE, (UInt8*)rtn->Data, strLen, &strLen)) { /* not convertible from native Unicode to UTF8 */ return NULL; } diff --git a/OSX/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj b/OSX/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj index 907bb45b..7df8b7ca 100644 --- a/OSX/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_pkcs12/libsecurity_pkcs12.xcodeproj/project.pbxproj @@ -48,7 +48,7 @@ /* Begin PBXFileReference section */ 05396DB50417A34400003D05 /* pkcs12BagAttrs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pkcs12BagAttrs.cpp; sourceTree = ""; }; - 05396DB90417B81000003D05 /* pkcs12Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12Debug.h; sourceTree = ""; }; + 05396DB90417B81000003D05 /* pkcs12Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = pkcs12Debug.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 054289210416A4EA00003D05 /* pkcs12SafeBag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12SafeBag.h; sourceTree = ""; }; 054289230416A5A800003D05 /* pkcs12BagAttrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12BagAttrs.h; sourceTree = ""; }; 054289250416AA2F00003D05 /* pkcs12Coder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs12Coder.h; sourceTree = ""; }; @@ -184,7 +184,6 @@ buildRules = ( ); dependencies = ( - 182BB3E3146F204A000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_pkcs12; productInstallPath = /usr/local/lib; @@ -198,7 +197,7 @@ 0592AC85041551E100003D05 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3C80987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_pkcs12" */; compatibilityVersion = "Xcode 3.2"; @@ -283,12 +282,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB3D9146F1F86000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -296,12 +304,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB3D9146F1F86000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp b/OSX/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp index 7b37b9f8..1d267ac6 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDCSPDLPlugin.cpp @@ -101,8 +101,8 @@ void SDCSPDLPlugin::consume(NotificationDomain domain, NotificationEvent event, if (const NameValuePair *uidp = nvd.FindByName(SSUID_KEY)) { CssmSubserviceUid *uid = (CssmSubserviceUid *)uidp->Value().data(); assert(uid); - secdebug("sdcspdl", "sending callback %d upstream", event); + secinfo("sdcspdl", "sending callback %d upstream", event); sendCallback(event, n2h (uid->subserviceId()), CSSM_SERVICE_DL | CSSM_SERVICE_CSP); } else - secdebug("sdcspdl", "callback event %d has no SSUID data", event); + secinfo("sdcspdl", "callback event %d has no SSUID data", event); } diff --git a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp index 8a29dba7..b72e2e52 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.cpp @@ -337,8 +337,8 @@ SDCSPSession::ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, void SDCSPSession::QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, - const Context &Context, - const CssmKey &Key, + const Context *Context, + const CssmKey *Key, CSSM_KEY_SIZE &KeySize) { unimplemented(); @@ -361,7 +361,7 @@ SDCSPSession::FreeKey(const AccessCredentials *accessCred, // 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). - secdebug("freeKey", "CSPDL FreeKey"); + secinfo("freeKey", "CSPDL FreeKey"); auto_ptr ssKey(&mSDCSPDLSession.find(ioKey)); ssKey->free(accessCred, ioKey, deleteKey); } diff --git a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.h b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.h index 530bbd23..5b9f0e99 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.h +++ b/OSX/libsecurity_sd_cspdl/lib/SDCSPSession.h @@ -126,8 +126,8 @@ public: void ObtainPrivateKeyFromPublicKey(const CssmKey &PublicKey, CssmKey &PrivateKey); void QueryKeySizeInBits(CSSM_CC_HANDLE CCHandle, - const Context &Context, - const CssmKey &Key, + const Context *Context, + const CssmKey *Key, CSSM_KEY_SIZE &KeySize); void FreeKey(const AccessCredentials *AccessCred, CssmKey &key, CSSM_BOOL Delete); diff --git a/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp b/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp index b6ebdc87..1717eaf5 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDContext.cpp @@ -31,7 +31,7 @@ #include "SDKey.h" #include -#define ssCryptDebug(args...) secdebug("ssCrypt", ## args) +#define ssCryptDebug(args...) secinfo("ssCrypt", ## args) using namespace SecurityServer; diff --git a/OSX/libsecurity_sd_cspdl/lib/SDDLSession.cpp b/OSX/libsecurity_sd_cspdl/lib/SDDLSession.cpp index a3aafbee..5a4f09c9 100644 --- a/OSX/libsecurity_sd_cspdl/lib/SDDLSession.cpp +++ b/OSX/libsecurity_sd_cspdl/lib/SDDLSession.cpp @@ -262,18 +262,18 @@ SDDLSession::postGetRecord(RecordHandle record, U32HandleObject::Handle resultsH catch (...) { try { mClientSession.releaseRecord(record); } - catch(...) { secdebug("ssCrypt", "releaseRecord threw during catch"); } + catch(...) { secinfo("ssCrypt", "releaseRecord threw during catch"); } if (resultsHandle != CSSM_INVALID_HANDLE) { try { mClientSession.releaseSearch(resultsHandle); } - catch(...) { secdebug("ssCrypt", "releaseSearch threw during catch"); } + catch(...) { secinfo("ssCrypt", "releaseSearch threw during catch"); } } throw; } } else { // not a key if (hKey != noKey) { try { mClientSession.releaseRecord(record); } - catch(...) { secdebug("ssCrypt", "failed releasing bogus key handle"); } + catch(...) { secinfo("ssCrypt", "failed releasing bogus key handle"); } CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } } @@ -452,7 +452,7 @@ SDDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, const AclEntryInfo &slot = acls.at(0); if (acls.size() > 1) - secdebug("acl", + secinfo("acl", "Using entry handle %ld from %d total candidates", slot.handle(), acls.size()); AclEdit edit(slot.handle(), slot.proto()); diff --git a/OSX/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj b/OSX/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj index f0f8d639..89e7ed41 100644 --- a/OSX/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_sd_cspdl/libsecurity_sd_cspdl.xcodeproj/project.pbxproj @@ -34,13 +34,6 @@ remoteGlobalIDString = 4CA1FEBE052A3C8100F22E42; remoteInfo = libsecurity_cdsa_plugin; }; - 182BB3D3146F1E6D000BF1F3 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 182BB3CC146F1E61000BF1F3 /* libsecurity_cdsa_plugin.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = C2C38A530535EDE600D7421F; - remoteInfo = libsecurity_cdsa_plugin_generate; - }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -52,18 +45,18 @@ 4094B0AB057EA69D00B44BCC /* sd_cspdl_common.mdsinfo */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.xml; path = sd_cspdl_common.mdsinfo; sourceTree = ""; }; 4C2741E905D463310072C0F2 /* APPLE_LICENSE */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = APPLE_LICENSE; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_sd_cspdl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_sd_cspdl.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CC3A0A805D45BC200484B20 /* SDContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDContext.cpp; sourceTree = ""; }; + 4CC3A0A805D45BC200484B20 /* SDContext.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SDContext.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CC3A0A905D45BC200484B20 /* SDContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDContext.h; sourceTree = ""; }; 4CC3A0AA05D45BC200484B20 /* SDCSPDLBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDCSPDLBuiltin.cpp; sourceTree = ""; }; 4CC3A0AB05D45BC200484B20 /* SDCSPDLDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDCSPDLDatabase.cpp; sourceTree = ""; }; 4CC3A0AC05D45BC200484B20 /* SDCSPDLDatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDCSPDLDatabase.h; sourceTree = ""; }; - 4CC3A0AD05D45BC200484B20 /* SDCSPDLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDCSPDLPlugin.cpp; sourceTree = ""; }; + 4CC3A0AD05D45BC200484B20 /* SDCSPDLPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SDCSPDLPlugin.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CC3A0AE05D45BC200484B20 /* SDCSPDLPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDCSPDLPlugin.h; sourceTree = ""; }; 4CC3A0AF05D45BC200484B20 /* SDCSPDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDCSPDLSession.cpp; sourceTree = ""; }; 4CC3A0B005D45BC200484B20 /* SDCSPDLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDCSPDLSession.h; sourceTree = ""; }; - 4CC3A0B105D45BC200484B20 /* SDCSPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDCSPSession.cpp; sourceTree = ""; }; + 4CC3A0B105D45BC200484B20 /* SDCSPSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SDCSPSession.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CC3A0B205D45BC200484B20 /* SDCSPSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDCSPSession.h; sourceTree = ""; }; - 4CC3A0B505D45BC200484B20 /* SDDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDDLSession.cpp; sourceTree = ""; }; + 4CC3A0B505D45BC200484B20 /* SDDLSession.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SDDLSession.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CC3A0B605D45BC200484B20 /* SDDLSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDDLSession.h; sourceTree = ""; }; 4CC3A0B705D45BC200484B20 /* SDFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SDFactory.cpp; sourceTree = ""; }; 4CC3A0B805D45BC200484B20 /* SDFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDFactory.h; sourceTree = ""; }; @@ -186,7 +179,6 @@ buildRules = ( ); dependencies = ( - 182BB3D4146F1E6D000BF1F3 /* PBXTargetDependency */, ); name = libsecurity_sd_cspdl; productInstallPath = /usr/local/lib; @@ -200,7 +192,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD3DE0987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_sd_cspdl" */; compatibilityVersion = "Xcode 3.2"; @@ -254,14 +246,6 @@ }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 182BB3D4146F1E6D000BF1F3 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = libsecurity_cdsa_plugin_generate; - targetProxy = 182BB3D3146F1E6D000BF1F3 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin XCBuildConfiguration section */ C27AD3D70987FCDF001272E0 /* Debug */ = { isa = XCBuildConfiguration; @@ -291,12 +275,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB3C9146F1DE0000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -304,12 +297,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB3C9146F1DE0000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_smime/TODO b/OSX/libsecurity_smime/TODO deleted file mode 100644 index 9c9564f0..00000000 --- a/OSX/libsecurity_smime/TODO +++ /dev/null @@ -1,9 +0,0 @@ -cmsattr.c -cmsdecode.c -cmsdigest.c -cmsrecinfo.c -cmssigdata.c -cmssiginfo.c - -* Support NSS_CMSRecipientInfo_Encode - cmst.h and cms.h changes. diff --git a/OSX/libsecurity_smime/lib/SecCMS.c b/OSX/libsecurity_smime/lib/SecCMS.c index bcb2552a..0bf6f89f 100644 --- a/OSX/libsecurity_smime/lib/SecCMS.c +++ b/OSX/libsecurity_smime/lib/SecCMS.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2014-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,16 +24,381 @@ #include -#include +#include + +#include #include -#include #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include "cmstpriv.h" +#include "cmspriv.h" #include +CFTypeRef kSecCMSSignDigest = CFSTR("kSecCMSSignDigest"); +CFTypeRef kSecCMSSignDetached = CFSTR("kSecCMSSignDetached"); +CFTypeRef kSecCMSCertChainMode = CFSTR("kSecCMSCertChainMode"); +CFTypeRef kSecCMSAdditionalCerts = CFSTR("kSecCMSAdditionalCerts"); +CFTypeRef kSecCMSSignedAttributes = CFSTR("kSecCMSSignedAttributes"); +CFTypeRef kSecCMSSignDate = CFSTR("kSecCMSSignDate"); +CFTypeRef kSecCMSAllCerts = CFSTR("kSecCMSAllCerts"); + +CFTypeRef kSecCMSSignHashAlgorithm = CFSTR("kSecCMSSignHashAlgorithm"); +CFTypeRef kSecCMSHashingAlgorithmSHA1 = CFSTR("kSecCMSHashingAlgorithmSHA1"); +CFTypeRef kSecCMSHashingAlgorithmSHA256 = CFSTR("kSecCMSHashingAlgorithmSHA256"); +CFTypeRef kSecCMSHashingAlgorithmSHA384 = CFSTR("kSecCMSHashingAlgorithmSHA384"); +CFTypeRef kSecCMSHashingAlgorithmSHA512 = CFSTR("kSecCMSHashingAlgorithmSHA512"); + +static SecCmsAttribute * +make_attr(PLArenaPool *poolp, SecAsn1Item *type, SecAsn1Item *value, bool encoded) +{ + SecAsn1Item * copiedvalue; + SecCmsAttribute *attr = (SecCmsAttribute *)PORT_ArenaZAlloc(poolp, sizeof(SecCmsAttribute)); + if (attr == NULL) + goto loser; + + if (SECITEM_CopyItem(poolp, &(attr->type), type) != SECSuccess) + goto loser; + + if (value != NULL) { + if ((copiedvalue = SECITEM_AllocItem(poolp, NULL, value->Length)) == NULL) + goto loser; + + if (SECITEM_CopyItem(poolp, copiedvalue, value) != SECSuccess) + goto loser; + + if (SecCmsArrayAdd(poolp, (void ***)&(attr->values), (void *)copiedvalue) != SECSuccess) + goto loser; + } + + attr->encoded = encoded; + +loser: + return attr; +} + +static void +signerinfo_add_auth_attr(SecCmsSignerInfoRef signerinfo, /*SECOidTag oidtag*/ + SecAsn1Item *oid, SecAsn1Item *value, bool encoded) +{ + PLArenaPool *poolp = signerinfo->cmsg->poolp; + PORT_Assert (poolp != NULL); + void *mark = PORT_ArenaMark (poolp); + + SecCmsAttribute *attr = make_attr(poolp, oid, value, encoded); + if (!attr || SecCmsAttributeArrayAddAttr(poolp, &(signerinfo->authAttr), attr) != SECSuccess) + goto loser; + + PORT_ArenaUnmark (poolp, mark); + return; + +loser: + PORT_Assert (mark != NULL); + PORT_ArenaRelease (poolp, mark); + return; +} + +static void sign_all_attributes(const void *key, const void *value, void *context) +{ + SecAsn1Item oid = { CFDataGetLength(key), (uint8_t*)CFDataGetBytePtr(key) }, + oid_value = { CFDataGetLength(value), (uint8_t*)CFDataGetBytePtr(value) }; + + signerinfo_add_auth_attr((SecCmsSignerInfoRef)context, &oid, &oid_value, true); +} + +static OSStatus SecCMSSignDataOrDigestAndAttributes(SecIdentityRef identity, + CFDataRef data, bool detached, bool data_is_digest, SECOidTag sign_algorithm, + CFMutableDataRef signed_data, CFDictionaryRef signed_attributes, SecCmsCertChainMode chainMode, CFArrayRef additional_certs) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + SecCmsSignerInfoRef signerinfo; + OSStatus status = errSecParam; + PLArenaPool *arena = NULL; + + require(!data_is_digest || detached /* if digest, must be detached */, out); + + require(cmsg = SecCmsMessageCreate(NULL), out); + require(sigd = SecCmsSignedDataCreate(cmsg), out); + require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); + require_noerr(SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), out); + require(cinfo = SecCmsSignedDataGetContentInfo(sigd), out); + require_noerr(SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, detached), out); + require(signerinfo = SecCmsSignerInfoCreate(cmsg, identity, sign_algorithm), out); + if (additional_certs) + require_noerr(SecCmsSignedDataAddCertList(sigd, additional_certs), out); + require_noerr(SecCmsSignerInfoIncludeCerts(signerinfo, chainMode, certUsageAnyCA), out); + require_noerr(SecCmsSignerInfoAddSigningTime(signerinfo, CFAbsoluteTimeGetCurrent()), out); + + if (signed_attributes) + CFDictionaryApplyFunction(signed_attributes, sign_all_attributes, signerinfo); + + SecAsn1Item input = {}; + if (data) { + input.Length = CFDataGetLength(data); + input.Data = (uint8_t*)CFDataGetBytePtr(data); + } + + CSSM_DATA cssm_signed_data = {0, NULL}; + // make an encoder context + if ((arena = PORT_NewArena(1024)) == NULL) { + goto out; + } + if (data_is_digest) { + require_noerr(SecCmsSignedDataSetDigestValue(sigd, sign_algorithm, &input), out); + require_noerr(SecCmsMessageEncode(cmsg, NULL, (SecArenaPoolRef)arena, &cssm_signed_data), out); + } + else + require_noerr(SecCmsMessageEncode(cmsg,(data && input.Length) ? &input : NULL, + (SecArenaPoolRef)arena, &cssm_signed_data), out); + + if (signed_data && cssm_signed_data.Data) { + CFDataAppendBytes(signed_data, cssm_signed_data.Data, cssm_signed_data.Length); + } + + status = errSecSuccess; +out: + if (arena) PORT_FreeArena(arena, PR_FALSE); + if (cmsg) SecCmsMessageDestroy(cmsg); + return status; +} + +OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, + CFDictionaryRef parameters, CFDictionaryRef signed_attributes, + CFMutableDataRef signed_data) +{ + bool is_digest = false, is_detached = false; + CFStringRef algorithm_name = NULL; + SecCmsCertChainMode chain_mode = SecCmsCMCertChain; + CFArrayRef additional_certs = NULL; + + if (parameters) { + is_digest = CFDictionaryGetValueIfPresent(parameters, + kSecCMSSignDigest, NULL); + is_detached = CFDictionaryGetValueIfPresent(parameters, + kSecCMSSignDetached, NULL); + algorithm_name = CFDictionaryGetValue(parameters, + kSecCMSSignHashAlgorithm); + + CFTypeRef chain_mode_param = CFDictionaryGetValue(parameters, kSecCMSCertChainMode); + if (chain_mode_param && (CFGetTypeID(chain_mode_param) == CFStringGetTypeID())) + chain_mode = CFStringGetIntValue(chain_mode_param); + + CFTypeRef additional_certs_param = CFDictionaryGetValue(parameters, kSecCMSAdditionalCerts); + if (additional_certs_param && (CFGetTypeID(additional_certs_param) == CFArrayGetTypeID())) + additional_certs = (CFArrayRef)additional_certs_param; + } + + SECOidTag algorithm = SEC_OID_SHA1; + if (algorithm_name) { + if (CFEqual(kSecCMSHashingAlgorithmSHA1, algorithm_name)) { + algorithm = SEC_OID_SHA1; + } else if (CFEqual(kSecCMSHashingAlgorithmSHA256, algorithm_name)) { + algorithm = SEC_OID_SHA256; + } else if (CFEqual(kSecCMSHashingAlgorithmSHA384, algorithm_name)) { + algorithm = SEC_OID_SHA384; + } else if (CFEqual(kSecCMSHashingAlgorithmSHA512, algorithm_name)) { + algorithm = SEC_OID_SHA512; + } else { + // signing with MD5 is no longer allowed + algorithm = SEC_OID_UNKNOWN; + } + } + + return SecCMSSignDataOrDigestAndAttributes(identity, data, + is_detached, is_digest, algorithm, + signed_data, signed_attributes, chain_mode, additional_certs); +} + +static OSStatus +SecCmsSignedDataSetDigestContext(SecCmsSignedDataRef sigd, + SecCmsDigestContextRef digestContext) +{ + SecAsn1Item * *digests; + + PLArenaPool *arena = NULL; + + if ((arena = PORT_NewArena(1024)) == NULL) + goto loser; + + if (SecCmsDigestContextFinishMultiple(digestContext, (SecArenaPoolRef)arena, &digests) != SECSuccess) + goto loser; + + SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(sigd); + if(digestAlgorithms == NULL) { + goto loser; + } + + if (SecCmsSignedDataSetDigests(sigd, digestAlgorithms, digests) != SECSuccess) + goto loser; + + return 0; +loser: + if (arena) + PORT_FreeArena(arena, PR_FALSE); + return PORT_GetError(); +} + +static CFMutableArrayRef copy_signed_attribute_values(SecCmsAttribute *attr) +{ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecAsn1Item **item = attr->values; + if (item) while (*item) { + CFDataRef asn1data = CFDataCreate(kCFAllocatorDefault, (*item)->Data, (*item)->Length); + if (asn1data) { + CFArrayAppendValue(array, asn1data); + CFRelease(asn1data); + } + item++; + } + return array; +} + +static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certs, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes) +{ + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + OSStatus status = errSecParam; + + SecAsn1Item encoded_message = { CFDataGetLength(message), (uint8_t*)CFDataGetBytePtr(message) }; + require_noerr_action_quiet(SecCmsMessageDecode(&encoded_message, NULL, NULL, NULL, NULL, NULL, NULL, &cmsg), + out, status = errSecDecode); + /* expected to be a signed data message at the top level */ + require_quiet(cinfo = SecCmsMessageContentLevel(cmsg, 0), out); + require_quiet(SecCmsContentInfoGetContentTypeTag(cinfo) == SEC_OID_PKCS7_SIGNED_DATA, out); + require_quiet(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out); + + if (detached_contents) + { + require_quiet(!SecCmsSignedDataHasDigests(sigd), out); + SECAlgorithmID **digestalgs = SecCmsSignedDataGetDigestAlgs(sigd); + SecCmsDigestContextRef digcx = SecCmsDigestContextStartMultiple(digestalgs); + SecCmsDigestContextUpdate(digcx, CFDataGetBytePtr(detached_contents), CFDataGetLength(detached_contents)); + SecCmsSignedDataSetDigestContext(sigd, digcx); + } + + if (additional_certs) + require_noerr_quiet(SecCmsSignedDataAddCertList(sigd, additional_certs), out); + + if (policy) { /* if no policy is given skip verification */ + /* find out about signers */ + int nsigners = SecCmsSignedDataSignerInfoCount(sigd); + require_quiet(nsigners == 1, out); + require_noerr_action_quiet(SecCmsSignedDataVerifySignerInfo(sigd, 0, NULL, policy, trustref), + out, status = errSecAuthFailed); + } + + status = errSecSuccess; + + if (attached_contents) { + const SecAsn1Item *content = SecCmsMessageGetContent(cmsg); + if (content) + *attached_contents = CFDataCreate(kCFAllocatorDefault, content->Data, content->Length); + else + *attached_contents = NULL; + } + + if (signed_attributes) { + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + require_quiet(attrs, out); + SecCmsAttribute **signed_attrs = sigd->signerInfos[0]->authAttr; + if (signed_attrs) while (*signed_attrs) { + CFDataRef type = CFDataCreate(kCFAllocatorDefault, (*signed_attrs)->type.Data, (*signed_attrs)->type.Length); + if (type) { + CFMutableArrayRef attr = copy_signed_attribute_values(*signed_attrs); + if (attr) { + CFMutableArrayRef existing_attrs = (CFMutableArrayRef)CFDictionaryGetValue(attrs, type); + if (existing_attrs) { + CFIndex count = CFArrayGetCount(attr); + if (count) + CFArrayAppendArray(existing_attrs, attr, CFRangeMake(0, count)); + } else + CFDictionarySetValue(attrs, type, attr); + CFRelease(attr); + } + CFRelease(type); + } + signed_attrs++; + } + CFMutableArrayRef certs = NULL; + + SecAsn1Item **cert_datas = SecCmsSignedDataGetCertificateList(sigd); + certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + SecAsn1Item *cert_data; + if (cert_datas) while ((cert_data = *cert_datas) != NULL) { + SecCertificateRef cert = SecCertificateCreateWithBytes(NULL, cert_data->Data, cert_data->Length); + if (cert) { + CFArrayAppendValue(certs, cert); + CFRelease(cert); + } + cert_datas++; + } + + CFDictionaryAddValue(attrs, kSecCMSAllCerts, certs); + + /* Add "cooked" values separately */ + CFAbsoluteTime signing_time; + if (errSecSuccess == SecCmsSignerInfoGetSigningTime(sigd->signerInfos[0], &signing_time)) { + CFDateRef signing_date = CFDateCreate(kCFAllocatorDefault, signing_time); + if (signing_date){ + CFDictionarySetValue(attrs, kSecCMSSignDate, signing_date); + if (signing_date) CFRelease(signing_date); + } + } + + *signed_attributes = attrs; + if (certs) CFRelease(certs); + } + + +out: + if (cmsg) SecCmsMessageDestroy(cmsg); + return status; +} + +OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes) +{ + OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, signed_attributes); + + return status; +} + +OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, + CFDataRef *attached_contents, CFDictionaryRef *message_attributes) +{ + CFDictionaryRef signed_attributes = NULL; + OSStatus status = SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, additional_certificates, attached_contents, &signed_attributes); + if (!status && signed_attributes && message_attributes) { + *message_attributes = CFDictionaryCreate(kCFAllocatorDefault, &kSecCMSSignedAttributes, (const void **)&signed_attributes, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + if (signed_attributes) CFRelease(signed_attributes); + + return status; +} + +OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents) { + return SecCMSVerifySignedData_internal(message, detached_contents, policy, trustref, NULL, attached_contents, NULL); +} + /* Designed to match the sec submodule implementation available for iOS */ CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message) { SecCmsMessageRef cmsg = NULL; @@ -72,6 +437,71 @@ out: } +extern const SecAsn1Template SecCmsMessageTemplate[]; + +CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof) { + OSStatus status = errSecParam; + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo; + SecCmsSignedDataRef sigd = NULL; + CFMutableDataRef cert_only_signed_data = NULL; + CFArrayRef cert_array = NULL; + CFIndex cert_array_count = 0; + SecCertificateRef cert = NULL; + + require(cert_or_array_thereof, out); + + require(cmsg = SecCmsMessageCreate(NULL), out); + require(sigd = SecCmsSignedDataCreate(cmsg), out); + require_noerr(SecCmsContentInfoSetContentData(cmsg, &(sigd->contentInfo), NULL, PR_TRUE), out); + require(cinfo = SecCmsMessageGetContentInfo(cmsg), out); + require_noerr(SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), out); + long version = SEC_CMS_SIGNED_DATA_VERSION_BASIC; + require(SEC_ASN1EncodeInteger(cmsg->poolp, &(sigd->version), version), out); + + if (CFGetTypeID(cert_or_array_thereof) == SecCertificateGetTypeID()) { + cert_array = CFArrayCreate(kCFAllocatorDefault, &cert_or_array_thereof, 1, &kCFTypeArrayCallBacks); + } else if (CFGetTypeID(cert_or_array_thereof) == CFArrayGetTypeID()) { + cert_array = CFArrayCreateCopy(kCFAllocatorDefault, (CFArrayRef)cert_or_array_thereof); + } + + require(cert_array, out); + cert_array_count = CFArrayGetCount(cert_array); + require(cert_array_count > 0, out); + + sigd->rawCerts = (SecAsn1Item * *)PORT_ArenaAlloc(cmsg->poolp, (cert_array_count + 1) * sizeof(SecAsn1Item *)); + require(sigd->rawCerts, out); + CFIndex ix; + for (ix = 0; ix < cert_array_count; ix++) { + cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, ix); + require(cert, out); + + sigd->rawCerts[ix] = PORT_ArenaZAlloc(cmsg->poolp, sizeof(SecAsn1Item)); + SecAsn1Item cert_data = { SecCertificateGetLength(cert), + (uint8_t *)SecCertificateGetBytePtr(cert) }; + *(sigd->rawCerts[ix]) = cert_data; + } + sigd->rawCerts[ix] = NULL; + + /* this is a SET OF, so we need to sort them guys - we have the DER already, though */ + if (cert_array_count > 1) + SecCmsArraySort((void **)sigd->rawCerts, SecCmsUtilDERCompare, NULL, NULL); + + cert_only_signed_data = CFDataCreateMutable(kCFAllocatorDefault, 0); + SecAsn1Item cert_only_signed_data_item = {}; + require_quiet(SEC_ASN1EncodeItem(cmsg->poolp, &cert_only_signed_data_item, + cmsg, SecCmsMessageTemplate), out); + CFDataAppendBytes(cert_only_signed_data, cert_only_signed_data_item.Data, + cert_only_signed_data_item.Length); + + status = errSecSuccess; +out: + if (cert_array) { CFRelease(cert_array); } + if (status && cert_only_signed_data) { CFRelease(cert_only_signed_data); } + if (cmsg) SecCmsMessageDestroy(cmsg); + return cert_only_signed_data; +} + CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert) { static const uint8_t header[] = { @@ -135,6 +565,3 @@ out: } return message; } - - - diff --git a/OSX/libsecurity_smime/lib/SecCMS.h b/OSX/libsecurity_smime/lib/SecCMS.h index 574dae1b..cb88a9ba 100644 --- a/OSX/libsecurity_smime/lib/SecCMS.h +++ b/OSX/libsecurity_smime/lib/SecCMS.h @@ -27,6 +27,21 @@ #include #include +#include + +extern const void * kSecCMSSignDigest; +extern const void * kSecCMSSignDetached; +extern const void * kSecCMSSignHashAlgorithm; +extern const void * kSecCMSCertChainMode; +extern const void * kSecCMSAdditionalCerts; +extern const void * kSecCMSSignedAttributes; +extern const void * kSecCMSSignDate; +extern const void * kSecCMSAllCerts; + +extern const void * kSecCMSHashingAlgorithmSHA1; +extern const void * kSecCMSHashingAlgorithmSHA256; +extern const void * kSecCMSHashingAlgorithmSHA384; +extern const void * kSecCMSHashingAlgorithmSHA512; /* Return an array of certificates contained in message, if message is of the type SignedData and has no signers, return NULL otherwise. Not that if @@ -37,7 +52,59 @@ CFArrayRef SecCMSCertificatesOnlyMessageCopyCertificates(CFDataRef message); /* Create a degenerate PKCS#7 containing a cert or a CFArray of certs. */ +CFDataRef SecCMSCreateCertificatesOnlyMessage(CFTypeRef cert_or_array_thereof); CFDataRef SecCMSCreateCertificatesOnlyMessageIAP(SecCertificateRef cert); +/*! + @function SecCMSVerifyCopyDataAndAttributes + @abstract verify a signed data cms blob. + @param message the cms message to be parsed + @param detached_contents to pass detached contents (optional) + @param policy specifies policy or array thereof should be used (optional). + if none is passed the blob will **not** be verified and only + the attached contents will be returned. + @param trustref (output/optional) if specified, the trust chain built during + verification will not be evaluated but returned to the caller to do so. + @param attached_contents (output/optional) return a copy of the attached + contents. + @param signed_attributes (output/optional) return a copy of the signed + attributes as a CFDictionary from oids (CFData) to values + (CFArray of CFData). + @result A result code. See "Security Error Codes" (SecBase.h). + errSecDecode not a CMS message we can parse, + errSecAuthFailed bad signature, or untrusted signer if caller doesn't + ask for trustref, + errSecParam garbage in, garbage out. + */ +OSStatus SecCMSVerifyCopyDataAndAttributes(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, + CFDataRef *attached_contents, CFDictionaryRef *signed_attributes); + +/*! + @function SecCMSVerify + @abstract same as SecCMSVerifyCopyDataAndAttributes, for binary compatibility. + */ +OSStatus SecCMSVerify(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFDataRef *attached_contents); + +OSStatus SecCMSVerifySignedData(CFDataRef message, CFDataRef detached_contents, + CFTypeRef policy, SecTrustRef *trustref, CFArrayRef additional_certificates, + CFDataRef *attached_contents, CFDictionaryRef *message_attributes); + +/*! + @function SecCMSCreateSignedData + @abstract create a signed data cms blob. + @param identity signer + @param data SHA-1 digest or message to be signed + @param parameters (input/optional) specify algorithm, detached, digest + @param signed_attributes (input/optional) signed attributes to insert + as a CFDictionary from oids (CFData) to value (CFData). + @param signed_data (output) return signed message. + @result A result code. See "Security Error Codes" (SecBase.h). + errSecParam garbage in, garbage out. + */ +OSStatus SecCMSCreateSignedData(SecIdentityRef identity, CFDataRef data, + CFDictionaryRef parameters, CFDictionaryRef signed_attributes, + CFMutableDataRef signed_data); #endif diff --git a/OSX/libsecurity_smime/lib/cmscinfo.c b/OSX/libsecurity_smime/lib/cmscinfo.c index e13acbe8..e7fecb2c 100644 --- a/OSX/libsecurity_smime/lib/cmscinfo.c +++ b/OSX/libsecurity_smime/lib/cmscinfo.c @@ -66,6 +66,8 @@ SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo) { SECOidTag kind; + if(!cinfo) return; + kind = SecCmsContentInfoGetContentTypeTag(cinfo); switch (kind) { case SEC_OID_PKCS7_ENVELOPED_DATA: diff --git a/OSX/libsecurity_smime/lib/cmscipher.c b/OSX/libsecurity_smime/lib/cmscipher.c index 02ec0873..a0016873 100644 --- a/OSX/libsecurity_smime/lib/cmscipher.c +++ b/OSX/libsecurity_smime/lib/cmscipher.c @@ -283,6 +283,7 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2, sec_rc2cbc_parameter_template); PORT_Free(rc2.rc2ParameterVersion.Data); + rc2.rc2ParameterVersion.Data = NULL; if (newParams == NULL) goto loser; break; @@ -322,10 +323,12 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith goto loser; if (initVector.Length != iv.Length) { PORT_Free(iv.Data); + iv.Data = NULL; goto loser; } memcpy(initVector.Data, iv.Data, initVector.Length); PORT_Free(iv.Data); + iv.Data = NULL; break; } case SEC_OID_RC2_CBC: @@ -340,14 +343,18 @@ SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorith if (initVector.Length != rc2.iv.Length) { PORT_Free(rc2.iv.Data); + rc2.iv.Data = NULL; PORT_Free(rc2.rc2ParameterVersion.Data); + rc2.rc2ParameterVersion.Data = NULL; goto loser; } memcpy(initVector.Data, rc2.iv.Data, initVector.Length); PORT_Free(rc2.iv.Data); + rc2.iv.Data = NULL; ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); PORT_Free(rc2.rc2ParameterVersion.Data); + rc2.rc2ParameterVersion.Data = NULL; if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits) goto loser; break; diff --git a/OSX/libsecurity_smime/lib/cmsdecode.c b/OSX/libsecurity_smime/lib/cmsdecode.c index 765a1685..f6112e78 100644 --- a/OSX/libsecurity_smime/lib/cmsdecode.c +++ b/OSX/libsecurity_smime/lib/cmsdecode.c @@ -676,9 +676,16 @@ SecCmsDecoderDestroy(SecCmsDecoderRef p7dcx) { /* XXXX what about inner decoders? running digests? decryption? */ /* XXXX there's a leak here! */ - SecCmsMessageDestroy(p7dcx->cmsg); - if (p7dcx->dcx) + if (p7dcx->cmsg) { + SecCmsMessageDestroy(p7dcx->cmsg); + } + if (p7dcx->dcx) { (void)SEC_ASN1DecoderFinish(p7dcx->dcx); + } + /* Clear out references */ + p7dcx->cmsg = NULL; + p7dcx->dcx = NULL; + p7dcx->childp7dcx = NULL; PORT_Free(p7dcx); } @@ -696,7 +703,9 @@ SecCmsDecoderFinish(SecCmsDecoderRef p7dcx, SecCmsMessageRef *outMessage) if (p7dcx->dcx == NULL || SEC_ASN1DecoderFinish(p7dcx->dcx) != SECSuccess || nss_cms_after_end(p7dcx) != SECSuccess) { - SecCmsMessageDestroy(cmsg); /* needs to get rid of pool if it's ours */ + if (p7dcx->cmsg) { + SecCmsMessageDestroy(cmsg); /* needs to get rid of pool if it's ours */ + } result = PORT_GetError(); goto loser; } @@ -705,6 +714,10 @@ SecCmsDecoderFinish(SecCmsDecoderRef p7dcx, SecCmsMessageRef *outMessage) result = noErr; loser: + /* Clear out references */ + p7dcx->cmsg = NULL; + p7dcx->dcx = NULL; + p7dcx->childp7dcx = NULL; PORT_Free(p7dcx); return result; } diff --git a/OSX/libsecurity_smime/lib/cmsdigdata.c b/OSX/libsecurity_smime/lib/cmsdigdata.c index 8fb7d5e5..d850ece4 100644 --- a/OSX/libsecurity_smime/lib/cmsdigdata.c +++ b/OSX/libsecurity_smime/lib/cmsdigdata.c @@ -89,6 +89,9 @@ loser: void SecCmsDigestedDataDestroy(SecCmsDigestedDataRef digd) { + if (digd == NULL) { + return; + } /* everything's in a pool, so don't worry about the storage */ SecCmsContentInfoDestroy(&(digd->contentInfo)); return; @@ -218,6 +221,9 @@ SecCmsDigestedDataDecodeAfterData(SecCmsDigestedDataRef digd) OSStatus SecCmsDigestedDataDecodeAfterEnd(SecCmsDigestedDataRef digd) { + if (!digd) { + return SECFailure; + } /* did we have digest calculation going on? */ if (digd->cdigest.Length != 0) { /* XXX comparision btw digest & cdigest */ diff --git a/OSX/libsecurity_smime/lib/cmsdigest.c b/OSX/libsecurity_smime/lib/cmsdigest.c index 0c16686e..52e07480 100644 --- a/OSX/libsecurity_smime/lib/cmsdigest.c +++ b/OSX/libsecurity_smime/lib/cmsdigest.c @@ -68,7 +68,7 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) digcnt = (digestalgs == NULL) ? 0 : SecCmsArrayCount((void **)digestalgs); - cmsdigcx = (SecCmsDigestContextRef)PORT_Alloc(sizeof(struct SecCmsDigestContextStr)); + cmsdigcx = (SecCmsDigestContextRef)PORT_ZAlloc(sizeof(struct SecCmsDigestContextStr)); if (cmsdigcx == NULL) return NULL; @@ -77,7 +77,7 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) if (digcnt >= (int)(INT_MAX/sizeof(CSSM_CC_HANDLE))) { goto loser; } - cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_Alloc(digcnt * sizeof(CSSM_CC_HANDLE)); + cmsdigcx->digobjs = (CSSM_CC_HANDLE *)PORT_ZAlloc(digcnt * sizeof(CSSM_CC_HANDLE)); if (cmsdigcx->digobjs == NULL) goto loser; } @@ -117,8 +117,11 @@ SecCmsDigestContextStartMultiple(SECAlgorithmID **digestalgs) loser: if (cmsdigcx) { - if (cmsdigcx->digobjs) + if (cmsdigcx->digobjs) { PORT_Free(cmsdigcx->digobjs); + cmsdigcx->digobjs = NULL; + cmsdigcx->digcnt = 0; + } } return NULL; } @@ -149,7 +152,7 @@ SecCmsDigestContextUpdate(SecCmsDigestContextRef cmsdigcx, const unsigned char * dataBuf.Data = (uint8 *)data; cmsdigcx->saw_contents = PR_TRUE; for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs[i]) + if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) CSSM_DigestDataUpdate(cmsdigcx->digobjs[i], &dataBuf, 1); } @@ -162,8 +165,10 @@ SecCmsDigestContextCancel(SecCmsDigestContextRef cmsdigcx) int i; for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs[i]) + if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) { CSSM_DeleteContext(cmsdigcx->digobjs[i]); + cmsdigcx->digobjs[i] = 0; + } } /* @@ -183,8 +188,10 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolR /* no contents? do not update digests */ if (digestsp == NULL || !cmsdigcx->saw_contents) { for (i = 0; i < cmsdigcx->digcnt; i++) - if (cmsdigcx->digobjs[i]) + if (cmsdigcx->digobjs && cmsdigcx->digobjs[i]) { CSSM_DeleteContext(cmsdigcx->digobjs[i]); + cmsdigcx->digobjs[i] = 0; + } rv = SECSuccess; if (digestsp) *digestsp = NULL; @@ -205,7 +212,12 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolR } for (i = 0; i < cmsdigcx->digcnt; i++, digest++) { - digobj = cmsdigcx->digobjs[i]; + if (cmsdigcx->digobjs) { + digobj = cmsdigcx->digobjs[i]; + } else { + digobj = 0; + } + CSSM_QUERY_SIZE_DATA dataSize; rv = CSSM_QuerySize(digobj, CSSM_FALSE, 1, &dataSize); if (rv != CSSM_OK) @@ -228,6 +240,7 @@ SecCmsDigestContextFinishMultiple(SecCmsDigestContextRef cmsdigcx, SecArenaPoolR } CSSM_DeleteContext(digobj); + cmsdigcx->digobjs[i] = 0; } else { @@ -251,6 +264,8 @@ loser: cleanup: if (cmsdigcx->digcnt > 0) { PORT_Free(cmsdigcx->digobjs); + cmsdigcx->digobjs = NULL; + cmsdigcx->digcnt = 0; } PORT_Free(cmsdigcx); diff --git a/OSX/libsecurity_smime/lib/cmsencdata.c b/OSX/libsecurity_smime/lib/cmsencdata.c index 895b5085..0bdf3fee 100644 --- a/OSX/libsecurity_smime/lib/cmsencdata.c +++ b/OSX/libsecurity_smime/lib/cmsencdata.c @@ -116,6 +116,9 @@ loser: void SecCmsEncryptedDataDestroy(SecCmsEncryptedDataRef encd) { + if (encd == NULL) { + return; + } /* everything's in a pool, so don't worry about the storage */ SecCmsContentInfoDestroy(&(encd->contentInfo)); return; diff --git a/OSX/libsecurity_smime/lib/cmsmessage.c b/OSX/libsecurity_smime/lib/cmsmessage.c index 816ce4af..75512389 100644 --- a/OSX/libsecurity_smime/lib/cmsmessage.c +++ b/OSX/libsecurity_smime/lib/cmsmessage.c @@ -135,8 +135,10 @@ SecCmsMessageDestroy(SecCmsMessageRef cmsg) SecCmsContentInfoDestroy(&(cmsg->contentInfo)); /* if poolp is not NULL, cmsg is the owner of its arena */ - if (cmsg->poolp_is_ours) + if (cmsg->poolp_is_ours) { PORT_FreeArena (cmsg->poolp, PR_FALSE); /* XXX clear it? */ + cmsg->poolp = NULL; + } } /* diff --git a/OSX/libsecurity_smime/lib/cmspubkey.c b/OSX/libsecurity_smime/lib/cmspubkey.c index a42f322b..19ff2065 100644 --- a/OSX/libsecurity_smime/lib/cmspubkey.c +++ b/OSX/libsecurity_smime/lib/cmspubkey.c @@ -45,12 +45,16 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include +#include /* ====== RSA ======================================================================= */ @@ -68,7 +72,11 @@ SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert, OSStatus rv; SecPublicKeyRef publickey; +#if TARGET_OS_MAC && !TARGET_OS_IPHONE rv = SecCertificateCopyPublicKey(cert,&publickey); +#else + publickey = SecCertificateCopyPublicKey(cert); +#endif if (publickey == NULL) return SECFailure; @@ -100,12 +108,16 @@ SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp, } #endif /* allocate memory for the encrypted key */ +#if TARGET_OS_MAC && !TARGET_OS_IPHONE rv = SecKeyGetStrengthInBits(publickey, NULL, &data_len); if (rv) - goto loser; - + goto loser; // Convert length to bytes; - data_len >>= 2; + data_len = data_len / 8; +#else + data_len = SecKeyGetSize(publickey, kSecKeyEncryptedDataSize); +#endif + encKey->Data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len); encKey->Length = data_len; if (encKey->Data == NULL) @@ -648,59 +660,6 @@ typedef enum { CAT_Ptr } ContextAttrType; -static CSSM_RETURN cmsAddContextAttribute( - CSSM_CC_HANDLE CCHandle, - uint32 AttributeType, - uint32 AttributeLength, - ContextAttrType attrType, - /* specify exactly one of these */ - const void *AttributePtr, - uint32 attributeInt) -{ - CSSM_CONTEXT_ATTRIBUTE newAttr; - CSSM_RETURN crtn; - - newAttr.AttributeType = AttributeType; - newAttr.AttributeLength = AttributeLength; - if(attrType == CAT_Uint32) { - newAttr.Attribute.Uint32 = attributeInt; - } - else { - /* this is a union of a bunch of different pointers...*/ - newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; - } - crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); - if(crtn) { - CSSM_PERROR("CSSM_UpdateContextAttributes", crtn); - } - return crtn; -} - -static CSSM_RETURN cmsGenRand( - CSSM_CSP_HANDLE cspHand, - CSSM_SIZE len, - uint8 *randOut) -{ - CSSM_CC_HANDLE ccHand = 0; - CSSM_DATA randData = {len, randOut}; - - CSSM_RETURN crtn = CSSM_CSP_CreateRandomGenContext(cspHand, - CSSM_ALGID_APPLE_YARROW, - NULL, /* seed*/ - len, - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateRandomGenContext", crtn); - return crtn; - } - crtn = CSSM_GenerateRandom(ccHand, &randData); - CSSM_DeleteContext(ccHand); - if(crtn) { - CSSM_PERROR("CSSM_GenerateRandom", crtn); - } - return crtn; -} - /* convert uint32 to big-endian 4 bytes */ static void int32ToBytes( uint32_t i, @@ -713,68 +672,6 @@ static void int32ToBytes( } } -/* - * NULL wrap a ref key to raw key in default format. - */ -static OSStatus cmsNullWrapKey( - CSSM_CSP_HANDLE cspHand, - const CSSM_KEY *refKey, - CSSM_KEY_PTR rawKey) -{ - CSSM_DATA descData = {0, 0}; - CSSM_RETURN crtn; - CSSM_CC_HANDLE ccHand; - CSSM_ACCESS_CREDENTIALS creds; - uint32 keyAttr; - - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - memset(rawKey, 0, sizeof(CSSM_KEY)); - - crtn = CSSM_CSP_CreateSymmetricContext(cspHand, - CSSM_ALGID_NONE, - CSSM_ALGMODE_NONE, - &creds, - NULL, // unwrappingKey - NULL, // initVector - CSSM_PADDING_NONE, - 0, // Params - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn); - return crtn; - } - - keyAttr = rawKey->KeyHeader.KeyAttr; - keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | - CSSM_KEYATTR_MODIFIABLE); - keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; - crtn = CSSM_WrapKey(ccHand, - &creds, - refKey, - &descData, - rawKey); - if(crtn != CSSM_OK) { - CSSM_PERROR("CSSM_WrapKey", crtn); - } - CSSM_DeleteContext(ccHand); - return crtn; -} - -/* - * Free memory via specified plugin's app-level allocator - */ -static void cmsFreeCssmMemory( - CSSM_HANDLE hand, - void *p) -{ - CSSM_API_MEMORY_FUNCS memFuncs; - CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs); - if(crtn) { - return; - } - memFuncs.free_func(p, memFuncs.AllocRef); -} - /* * Given an OID tag, return key size and mode. * NOTE: ciphers with variable key sizes, like RC2, RC4, and RC5 cannot @@ -784,60 +681,63 @@ static void cmsFreeCssmMemory( static OSStatus encrAlgInfo( SECOidTag oidTag, uint32 *keySizeBits, /* RETURNED */ - CSSM_ENCRYPT_MODE *mode) /* RETURNED */ + CCAlgorithm *algorithm, /* RETURNED */ + CCOptions *options) /* RETURNED */ { *keySizeBits = 64; /* default */ - *mode = CSSM_ALGMODE_CBCPadIV8; /* default */ + *options = kCCOptionPKCS7Padding; /* default */ switch(oidTag) { - case SEC_OID_RC2_CBC: - case SEC_OID_RC4: - case SEC_OID_RC5_CBC_PAD: - dprintf("encrAlgInfo: key size unknowable\n"); - return errSecDataNotAvailable; - - case SEC_OID_DES_EDE3_CBC: - *keySizeBits = 192; - break; - case SEC_OID_DES_EDE: - /* Not sure about this; SecCmsCipherContextStart() treats this - * like SEC_OID_DES_EDE3_CBC... */ - case SEC_OID_DES_ECB: - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_DES_CBC: - *mode = CSSM_ALGMODE_CBC; - break; - case SEC_OID_AES_128_CBC: - *keySizeBits = 128; - break; - case SEC_OID_AES_192_CBC: - *keySizeBits = 192; - break; - case SEC_OID_AES_256_CBC: - *keySizeBits = 256; - break; - case SEC_OID_AES_128_ECB: - *keySizeBits = 128; - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_AES_192_ECB: - *keySizeBits = 192; - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_AES_256_ECB: - *keySizeBits = 256; - *mode = CSSM_ALGMODE_ECB; - break; - case SEC_OID_DES_OFB: - *mode = CSSM_ALGMODE_OFB; - break; - case SEC_OID_DES_CFB: - *mode = CSSM_ALGMODE_CFB; - break; - default: - dprintf("encrAlgInfo: unknown alg tag (%d)\n", (int)oidTag); - return errSecDataNotAvailable; + case SEC_OID_RC2_CBC: + case SEC_OID_RC4: + case SEC_OID_RC5_CBC_PAD: + dprintf("encrAlgInfo: key size unknowable\n"); + return errSecDataNotAvailable; + case SEC_OID_DES_EDE: + /* Not sure about this; SecCmsCipherContextStart() treats this + * like SEC_OID_DES_EDE3_CBC... */ + *options = kCCOptionECBMode; + // fall through + case SEC_OID_DES_EDE3_CBC: + *keySizeBits = 192; + *algorithm = kCCAlgorithm3DES; + break; + case SEC_OID_DES_ECB: + *options = kCCOptionECBMode; + // fall through + case SEC_OID_DES_CBC: + *algorithm = kCCAlgorithmDES; + break; + case SEC_OID_AES_128_CBC: + *keySizeBits = 128; + *algorithm = kCCAlgorithmAES; + break; + case SEC_OID_AES_192_CBC: + *keySizeBits = 192; + *algorithm = kCCAlgorithmAES; + break; + case SEC_OID_AES_256_CBC: + *keySizeBits = 256; + *algorithm = kCCAlgorithmAES; + break; + case SEC_OID_AES_128_ECB: + *keySizeBits = 128; + *algorithm = kCCAlgorithmAES; + *options = kCCOptionECBMode; + break; + case SEC_OID_AES_192_ECB: + *keySizeBits = 192; + *algorithm = kCCAlgorithmAES; + *options = kCCOptionECBMode; + break; + case SEC_OID_AES_256_ECB: + *keySizeBits = 256; + *algorithm = kCCAlgorithmAES; + *options = kCCOptionECBMode; + break; + default: + dprintf("encrAlgInfo: unknown alg tag (%d)\n", (int)oidTag); + return errSecDataNotAvailable; } return noErr; } @@ -861,216 +761,124 @@ SecCmsUtilEncryptSymKeyECDH( * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */ { OSStatus rv = noErr; - CSSM_KEY ourPrivKeyCssm; - CSSM_KEY ourPubKeyCssm; - SecKeyRef theirPubKeyRef = NULL; - CSSM_KEY_PTR theirPubKeyCssm = NULL; - const CSSM_KEY *cekCssmRef = NULL; - uint32 ecdhKeySizeBits; - CSSM_CSP_HANDLE rawCspHand = SecCspHandleForAlgorithm(CSSM_ALGID_ECDH); - CSSM_CC_HANDLE ccHand = 0; - CSSM_RETURN crtn; - CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"}; + SecKeyRef theirPubKey = NULL, ourPubKey = NULL, ourPrivKey = NULL; + CFDictionaryRef theirKeyAttrs = NULL, ourKeyParams = NULL, kekParams = NULL; + uint8_t iv[ECDH_KEK_IV_LEN_BYTES]; + CSSM_DATA ivData = { ECDH_KEK_IV_LEN_BYTES, iv }; SECAlgorithmID kekAlgId; - uint8 iv[ECDH_KEK_IV_LEN_BYTES]; - CSSM_DATA ivData = {ECDH_KEK_IV_LEN_BYTES, iv}; SECOidData *kekOid; ECC_CMS_SharedInfo sharedInfo; CSSM_DATA sharedInfoEnc = {0, NULL}; uint8 nullData[2] = {SEC_ASN1_NULL, 0}; uint8 keyLenAsBytes[4]; - CSSM_KEY kekDerive; - CSSM_DATA certData; - CSSM_CL_HANDLE clHand; - CSSM_ACCESS_CREDENTIALS creds; - CSSM_DATA paramData = {0, NULL}; - CSSM_KEY cekCssm; - CSSM_CSP_HANDLE refCspHand; - CSSM_SIZE bytesEncrypted; - CSSM_DATA remData = {0, NULL}; - CSSM_DATA ctext = {0, NULL}; - CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjPubKey; - - if(rawCspHand == 0) { - return internalComponentErr; - } - - memset(&ourPrivKeyCssm, 0, sizeof(CSSM_KEY)); - memset(&ourPubKeyCssm, 0, sizeof(CSSM_KEY)); - memset(&cekCssm, 0, sizeof(CSSM_KEY)); - memset(&kekDerive, 0, sizeof(kekDerive)); - + CFDataRef sharedInfoData = NULL, kekData = NULL, ourPubData = NULL; + CFNumberRef kekLen = NULL; + CFErrorRef error = NULL; + CCCryptorRef ciphercc = NULL; + encKey->Data = NULL; encKey->Length = 0; - - /* - * Create our ECDH key pair matching the recipient's key. - * Get the public key in "read-only" OCTET_STRING format, which - * is the ECPoint we put in - * KeyAgreeRecipientInfo.originator.OriginatorPublicKey. - */ - rv = SecCertificateGetData(cert, &certData); - if(rv) { - CSSM_PERROR("SecCertificateGetData", rv); - return rv; - } - rv = SecCertificateGetCLHandle(cert, &clHand); - if(rv) { - CSSM_PERROR("SecCertificateGetCLHandle", rv); - return rv; - } - rv = CSSM_CL_CertGetKeyInfo(clHand, &certData, &theirPubKeyCssm); - if(rv) { - CSSM_PERROR("CSSM_CL_CertGetKeyInfo", rv); - return rv; - } - - /* - * Verify the EC curve of the recipient's public key. It's in the - * public key's AlgId.parameters as an OID. The key we were - * given is in CSSM_X509_SUBJECT_PUBLIC_KEY_INFO form. - */ - memset(&subjPubKey, 0, sizeof(subjPubKey)); - if(SEC_ASN1DecodeItem(poolp, &subjPubKey, kSecAsn1SubjectPublicKeyInfoTemplate, - &theirPubKeyCssm->KeyData)) { - dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding SubjPubKey\n"); - /* oh well, keep going */ - } - else { - if(subjPubKey.algorithm.parameters.Data != NULL) { - CSSM_DATA curveOid; - if(SEC_ASN1DecodeItem(poolp, &curveOid, kSecAsn1ObjectIDTemplate, - &subjPubKey.algorithm.parameters)) { - dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding curveOid\n"); - /* oh well, keep going */ - } - else { - /* We have the curve OID. Any other errors are fatal. */ - SECOidTag oidTag = SECOID_FindOIDTag(&curveOid); - switch(oidTag) { - case SEC_OID_SECP_256_R1: - case SEC_OID_SECP_384_R1: - case SEC_OID_SECP_521_R1: - break; - default: - dprintf("SecCmsUtilEncryptSymKeyECDH: unsupported curveOid\n"); - rv = CSSMERR_CSP_INVALID_KEY; - goto loser; - } - } - } + + /* Copy the recipient's static public ECDH key */ +#if TARGET_OS_IPHONE + theirPubKey = SecCertificateCopyPublicKey(cert); +#else + rv = SecCertificateCopyPublicKey(cert, &theirPubKey); +#endif + if (rv || !theirPubKey) { + dprintf("SecCmsUtilEncryptSymKeyECDH: failed to get public key from cert, %d\n", (int)rv); + goto out; } - - ecdhKeySizeBits = theirPubKeyCssm->KeyHeader.LogicalKeySizeInBits; - crtn = CSSM_CSP_CreateKeyGenContext(rawCspHand, - CSSM_ALGID_ECDSA, - ecdhKeySizeBits, - NULL, // Seed - NULL, // Salt - NULL, // StartDate - NULL, // EndDate - NULL, // Params - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateKeyGenContext", crtn); - rv = crtn; - goto loser; + + theirKeyAttrs = SecKeyCopyAttributes(theirPubKey); + if (!theirKeyAttrs) { + dprintf("SecCmsUtilEncryptSymKeyECDH: failed to get key attributes\n"); + goto out; } - crtn = cmsAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT, - sizeof(uint32), - CAT_Uint32, - NULL, - CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING); - if(crtn) { - CSSM_PERROR("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn); - rv = crtn; - goto loser; + + CFStringRef keyType = NULL; + CFNumberRef keySizeNum = NULL; + keyType = CFDictionaryGetValue(theirKeyAttrs, kSecAttrKeyType); + keySizeNum = CFDictionaryGetValue(theirKeyAttrs, kSecAttrKeySizeInBits); + + if (!CFEqual(kSecAttrKeyTypeECSECPrimeRandom, keyType)) { + dprintf("SecCmsUtilEncryptSymKeyECDH: unsupported key type\n"); + rv = CSSMERR_CSP_INVALID_KEY; + goto out; } - crtn = CSSM_GenerateKeyPair(ccHand, - CSSM_KEYUSE_DERIVE, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - &ourPubKeyCssm, - CSSM_KEYUSE_DERIVE, - CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, // CredAndAclEntry - &ourPrivKeyCssm); - CSSM_DeleteContext(ccHand); - ccHand = 0; - if(crtn) { - CSSM_PERROR("CSSM_GenerateKeyPair", crtn); - rv = crtn; - goto loser; + /* Generate ephemeral ECDH key */ + const void *keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrNoLegacy}; + const void *values[] = { keyType, keySizeNum, kCFBooleanTrue }; + ourKeyParams = CFDictionaryCreate(NULL, keys, values, 3, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + rv = SecKeyGeneratePair(ourKeyParams, &ourPubKey, &ourPrivKey); + if (rv || !ourPubKey || !ourPrivKey) { + dprintf("SecKeyGeneratePair: unable to generate ECDH key pair, %d\n", (int)rv); + goto out; } - pubKey->Length = ourPubKeyCssm.KeyData.Length; - pubKey->Data = (uint8 *)PORT_ArenaAlloc(poolp, pubKey->Length); - memmove(pubKey->Data, ourPubKeyCssm.KeyData.Data, pubKey->Length); - dumpBuf("sender's public key", pubKey); - - /* - * Cook up random UKM - */ - ukm->Data = (uint8 *)PORT_ArenaAlloc(poolp, UKM_LENGTH); + + /* Generate UKM */ + ukm->Data = PORT_Alloc(UKM_LENGTH); ukm->Length = UKM_LENGTH; - crtn = cmsGenRand(rawCspHand, UKM_LENGTH, ukm->Data); - if(crtn) { - goto loser; + rv = CCRandomCopyBytes(kCCRandomDefault, ukm->Data, UKM_LENGTH); + if (rv || !ukm->Data) { + dprintf("CCRandomGenerateBytes failed, %d", (int)rv); + goto out; } - dumpBuf("sender UKM", ukm); - + /* * OK, we have to set up a weird SECAlgorithmID. * algorithm = dhSinglePass-stdDH-sha1kdf-scheme - * params = an encoded SECAlgorithmID representing the KEK algorithm, with + * params = an encoded SECAlgorithmID representing the KEK algorithm, with * algorithm = whatever we pick * parameters = IV as octet string (though I haven't seen that specified * anywhere; it's how the CEK IV is encoded) - * - * First, the 8-byte random IV, encoded as octet string */ - crtn = cmsGenRand(rawCspHand, ECDH_KEK_IV_LEN_BYTES, iv); - if(crtn) { - goto loser; + + /* Generate 8-byte IV */ + rv = CCRandomCopyBytes(kCCRandomDefault, iv, ECDH_KEK_IV_LEN_BYTES); + if (rv) { + dprintf("CCRandomGenerateBytes failed, %d", (int)rv); + goto out; } dumpBuf("sender IV", &ivData); - + memset(&kekAlgId, 0, sizeof(kekAlgId)); if (!SEC_ASN1EncodeItem(poolp, &kekAlgId.parameters, - &ivData, kSecAsn1OctetStringTemplate)) { - rv = internalComponentErr; - goto loser; + &ivData, kSecAsn1OctetStringTemplate)) { + rv = internalComponentErr; + goto out; } /* Drop in the KEK OID and encode the whole thing */ kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG); if(kekOid == NULL) { - dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); - rv = internalComponentErr; - goto loser; + dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); + rv = internalComponentErr; + goto out; } kekAlgId.algorithm = kekOid->oid; memset(keyEncAlg, 0, sizeof(*keyEncAlg)); if (!SEC_ASN1EncodeItem(poolp, &keyEncAlg->parameters, - &kekAlgId, SECOID_AlgorithmIDTemplate)) { - rv = internalComponentErr; - goto loser; + &kekAlgId, SECOID_AlgorithmIDTemplate)) { + rv = internalComponentErr; + goto out; } kekOid = SECOID_FindOIDByTag(SEC_OID_DH_SINGLE_STD_SHA1KDF); if(kekOid == NULL) { - dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); - rv = internalComponentErr; - goto loser; + dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n"); + rv = internalComponentErr; + goto out; } keyEncAlg->algorithm = kekOid->oid; - - /* - * Now in order to derive the KEK proper, we have to create a + + /* + * Now in order to derive the KEK proper, we have to create a * ECC-CMS-SharedInfo, which does not appear in the message, and DER - * encode that struct, the result of which is used as the - * SharedInfo value in the KEK key derive. + * encode that struct, the result of which is used as the + * SharedInfo value in the KEK key derive. */ memset(&sharedInfo, 0, sizeof(sharedInfo)); kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG); @@ -1082,146 +890,102 @@ SecCmsUtilEncryptSymKeyECDH( sharedInfo.suppPubInfo.Length = 4; sharedInfo.suppPubInfo.Data = keyLenAsBytes; if (!SEC_ASN1EncodeItem(poolp, &sharedInfoEnc, - &sharedInfo, ECC_CMS_SharedInfoTemplate)) { - rv = internalComponentErr; - goto loser; + &sharedInfo, ECC_CMS_SharedInfoTemplate)) { + rv = internalComponentErr; + goto out; } dumpBuf("sender encoded SharedInfo", &sharedInfoEnc); - - /* - * Since we're using the raw CSP here, we can provide the "other" public - * key as an actual CSSM_KEY. When unwrapping, we won't be able to do that - * since we'll be using our private key obtained from a SecIdentityRef. - */ - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - crtn = CSSM_CSP_CreateDeriveKeyContext(rawCspHand, - CSSM_ALGID_ECDH_X963_KDF, - ECDH_KEK_KEY_CSSM_ALGID, // algorithm of the KEK - ECDH_KEK_KEY_LEN_BYTES * 8, - &creds, - &ourPrivKeyCssm, // BaseKey - 0, // IterationCount - &sharedInfoEnc, // Salt - 0, // Seed - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn); - rv = crtn; - goto loser; - } - - /* add recipient's pub key as a context attr */ - crtn = cmsAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_PUBLIC_KEY, - sizeof(CSSM_KEY), - CAT_Ptr, - (void *)theirPubKeyCssm, - 0); - if(crtn) { - rv = crtn; - goto loser; - } - - /* Derive the KEK */ - crtn = CSSM_DeriveKey(ccHand, - ¶mData, - CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, // cread/acl - &kekDerive); - if(crtn) { - CSSM_PERROR("CSSM_DeriveKey", crtn); - rv = crtn; - goto loser; - } - CSSM_DeleteContext(ccHand); - ccHand = 0; - - /* - * Obtain the raw CEK bits. - */ - rv = SecKeyGetCSSMKey(key, &cekCssmRef); - if(rv) { - CSSM_PERROR("SecKeyGetCSSMKey", rv); - goto loser; - } - rv = SecKeyGetCSPHandle(key, &refCspHand); - if(rv) { - CSSM_PERROR("SecKeyGetCSPHandle", rv); - goto loser; - } - rv = cmsNullWrapKey(refCspHand, cekCssmRef, &cekCssm); - if(rv) { - goto loser; + + /* Derive KEK */ + sharedInfoData = CFDataCreate(NULL, sharedInfoEnc.Data, sharedInfoEnc.Length); + int32_t ecdh_key_key_len = ECDH_KEK_KEY_LEN_BYTES; + kekLen = CFNumberCreate(NULL, kCFNumberSInt32Type, &ecdh_key_key_len); + const void *kekKeys[] = { kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo }; + const void *kekValues[] = { kekLen, sharedInfoData }; + kekParams = CFDictionaryCreate(NULL, kekKeys, kekValues, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + kekData = SecKeyCopyKeyExchangeResult(ourPrivKey, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1, + theirPubKey, kekParams, &error); + if (error) { + dprintf("SecKeyCopyKeyExchangeResult: failed\n"); + goto out; } - - /* - * Finally, encrypt the raw CEK bits with the KEK we just derived + + /* + * Encrypt the raw CEK bits with the KEK we just derived */ - crtn = CSSM_CSP_CreateSymmetricContext(rawCspHand, - ECDH_KEK_ENCR_CSSM_ALGID, - CSSM_ALGMODE_CBCPadIV8, - NULL, // access cred - &kekDerive, - &ivData, // InitVector - CSSM_PADDING_PKCS7, - NULL, // Params - &ccHand); - if(rv) { - CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv); - goto loser; - } - rv = CSSM_EncryptData(ccHand, - &cekCssm.KeyData, - 1, - &ctext, - 1, - &bytesEncrypted, - &remData); - if(rv) { - CSSM_PERROR("CSSM_EncryptData", rv); - goto loser; - } - encKey->Data = PORT_ArenaAlloc(poolp, bytesEncrypted); - encKey->Length = bytesEncrypted; - memmove(encKey->Data, ctext.Data, ctext.Length); - if(bytesEncrypted != ctext.Length) { - memmove(encKey->Data + ctext.Length, remData.Data, remData.Length); - } - dumpBuf("sender encKey", encKey); - -loser: - if(ccHand) { - CSSM_DeleteContext(ccHand); - } - CFRELEASE(theirPubKeyRef); - if(ourPubKeyCssm.KeyData.Data) { - CSSM_FreeKey(rawCspHand, NULL, &ourPubKeyCssm, CSSM_FALSE); - } - if(ourPrivKeyCssm.KeyData.Data) { - CSSM_FreeKey(rawCspHand, NULL, &ourPrivKeyCssm, CSSM_FALSE); - } - if(ctext.Data) { - cmsFreeCssmMemory(rawCspHand, ctext.Data); - } - if(remData.Data) { - cmsFreeCssmMemory(rawCspHand, remData.Data); + rv = CCCryptorCreate(kCCEncrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding, + CFDataGetBytePtr(kekData), CFDataGetLength(kekData), iv, &ciphercc); + if (rv) { + dprintf("CCCryptorCreate failed: %d\n", (int)rv); + goto out; } - if(cekCssm.KeyData.Data) { - CSSM_FreeKey(refCspHand, NULL, &cekCssm, CSSM_FALSE); + CSSM_KEY cek; + rv = cmsNullWrapKey(key, &cek); + if (rv) { + dprintf("SecKeyGetCSSMKey failed: %d\n", (int)rv); + goto out; } - if(kekDerive.KeyData.Data) { - CSSM_FreeKey(rawCspHand, NULL, &kekDerive, CSSM_FALSE); + size_t expectedEncKeyLength = CCCryptorGetOutputLength(ciphercc, cek.KeyData.Length, true); + encKey->Data = PORT_ArenaAlloc(poolp, expectedEncKeyLength); + size_t bytes_output = 0; + rv = CCCryptorUpdate(ciphercc, cek.KeyData.Data, cek.KeyData.Length, encKey->Data, expectedEncKeyLength, &bytes_output); + if (rv) { + dprintf("CCCryptorUpdate failed: %d\n", (int)rv); + goto out; } - if(theirPubKeyCssm) { - /* Allocated by CL */ - cmsFreeCssmMemory(clHand, theirPubKeyCssm->KeyData.Data); - cmsFreeCssmMemory(clHand, theirPubKeyCssm); + size_t final_bytes_output = 0; + rv = CCCryptorFinal(ciphercc, encKey->Data+bytes_output, expectedEncKeyLength - bytes_output, &final_bytes_output); + if (rv) { + dprintf("CCCryptorFinal failed: %d\n", (int)rv); + goto out; + } + encKey->Length = bytes_output + final_bytes_output; + + /* Provide our ephemeral public key to the caller */ + ourPubData = SecKeyCopyExternalRepresentation(ourPubKey, &error); + if (error) { + dprintf("SecKeyCopyExternalRepresentation failed\n"); + goto out; + } + pubKey->Length = CFDataGetLength(ourPubData); + pubKey->Data = malloc(pubKey->Length); + if (pubKey->Data) { + memcpy(pubKey->Data, CFDataGetBytePtr(ourPubData), pubKey->Length); + } else { + rv = errSecAllocate; + } + /* pubKey is bit string, convert here */ + pubKey->Length <<= 3; + +out: + if (theirPubKey) { CFRelease(theirPubKey); } + if (theirKeyAttrs) { CFRelease(theirKeyAttrs); } + if (ourKeyParams) { CFRelease(ourKeyParams); } + if (ourPubKey) { CFRelease(ourPubKey); } + if (ourPrivKey) { CFRelease(ourPrivKey); } + if (sharedInfoData) { CFRelease(sharedInfoData); } + if (kekLen) { CFRelease(kekLen); } + if (kekParams) { CFRelease(kekParams); } + if (kekData) { CFRelease(kekData); } + if (error) { CFRelease(error); } + if (ciphercc) { CCCryptorRelease(ciphercc); } + if (ourPubData) { CFRelease(ourPubData); } + if (rv && encKey->Data) { + PORT_Free(encKey->Data); + encKey->Data = NULL; + encKey->Length = 0; + } + if (rv && ukm->Data) { + PORT_Free(ukm->Data); + ukm->Data = NULL; + ukm->Length = 0; } return rv; } + #pragma mark ---- ECDH CEK key unwrap ---- SecSymmetricKeyRef @@ -1234,11 +998,9 @@ SecCmsUtilDecryptSymKeyECDH( SECOidTag bulkalgtag, /* algorithm of returned key */ CSSM_DATA_PTR pubKey) /* sender's pub key as ECPoint from * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */ - { SecSymmetricKeyRef outKey = NULL; OSStatus rv = noErr; - const CSSM_KEY *ourPrivKeyCssm; PLArenaPool *pool = NULL; SECAlgorithmID keyAlgParam; SECOidData *kekOid = NULL; @@ -1247,70 +1009,58 @@ SecCmsUtilDecryptSymKeyECDH( CSSM_DATA sharedInfoEnc = {0, NULL}; uint8 nullData[2] = {SEC_ASN1_NULL, 0}; uint8 keyLenAsBytes[4]; - CSSM_ENCRYPT_MODE kekMode; uint32 kekSizeBits; - CSSM_KEY kekDerive; - CSSM_RETURN crtn; - CSSM_ACCESS_CREDENTIALS creds; - CSSM_CSP_HANDLE refCspHand; - CSSM_CC_HANDLE ccHand = 0; - CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"}; - const CSSM_ACCESS_CREDENTIALS *accessCred; - CSSM_KEY wrappedKey; - CSSM_KEY unwrappedKey; - CSSM_ALGORITHMS bulkAlg; - CSSM_DATA descriptiveData = {0, NULL}; - - dumpBuf("receiver encKey", encKey); - - memset(&kekDerive, 0, sizeof(kekDerive)); + SecKeyRef theirPubKey = NULL; + CFStringRef keyType = NULL; + CFDictionaryRef theirKeyAttrs = NULL, kekParams = NULL; + CFMutableDictionaryRef cekParams = NULL; + CFDataRef sharedInfoData = NULL, theirPubData= NULL, kekData = NULL, cekData = NULL; + CFNumberRef kekLen = NULL, theirKeyLen = NULL; + CFErrorRef error = NULL; + CCAlgorithm alg; + CCOptions options = 0; + CCCryptorRef ciphercc = NULL; + size_t theirKeySizeInBits = 0; - /* our private key in CSSM form */ - rv = SecKeyGetCSSMKey(privkey, &ourPrivKeyCssm); - if(rv) { - CSSM_PERROR("SecKeyGetCSSMKey", rv); - goto loser; - } - - /* + /* * Decode keyEncAlg.params to get KEK algorithm and IV - */ + */ pool = PORT_NewArena(1024); if(pool == NULL) { - goto loser; + goto out; } memset(&keyAlgParam, 0, sizeof(keyAlgParam)); - if(SEC_ASN1DecodeItem(pool, &keyAlgParam, SECOID_AlgorithmIDTemplate, - &keyEncAlg->parameters)) { - dprintf("SecCmsUtilDecryptSymKeyECDH: error decoding keyAlgParams\n"); - goto loser; + if(SEC_ASN1DecodeItem(pool, &keyAlgParam, SECOID_AlgorithmIDTemplate, + &keyEncAlg->parameters)) { + dprintf("SecCmsUtilDecryptSymKeyECDH: error decoding keyAlgParams\n"); + goto out; } kekOid = SECOID_FindOID(&keyAlgParam.algorithm); if(kekOid == NULL) { - dprintf("SecCmsUtilDecryptSymKeyECDH: unknown KEK enc OID\n"); - goto loser; + dprintf("SecCmsUtilDecryptSymKeyECDH: unknown KEK enc OID\n"); + goto out; } - rv = encrAlgInfo(kekOid->offset, &kekSizeBits, &kekMode); + rv = encrAlgInfo(kekOid->offset, &kekSizeBits, &alg, &options); if(rv) { - goto loser; + goto out; } /* IV is OCTET STRING in the alg params */ - if(SEC_ASN1DecodeItem(pool, &iv, kSecAsn1OctetStringTemplate, - &keyAlgParam.parameters)) { - /* - * Not sure here - is it legal to have no IV? I haven't seen this - * addressed in any spec. Maybe we should condition the behavior - * here on the KEK algorithm. - */ - dprintf("SecCmsUtilDecryptSymKeyECDH: no KEK IV\n"); - goto loser; + if(SEC_ASN1DecodeItem(pool, &iv, kSecAsn1OctetStringTemplate, + &keyAlgParam.parameters)) { + /* + * Not sure here - is it legal to have no IV? I haven't seen this + * addressed in any spec. Maybe we should condition the behavior + * here on the KEK algorithm. + */ + dprintf("SecCmsUtilDecryptSymKeyECDH: no KEK IV\n"); + goto out; } - - /* - * Now in order to derive the KEK proper, we have to create a + + /* + * Now in order to derive the KEK proper, we have to create a * ECC-CMS-SharedInfo, which does not appear in the message, and DER - * encode that struct, the result of which is used as the - * SharedInfo value in the KEK key derive. + * encode that struct, the result of which is used as the + * SharedInfo value in the KEK key derive. */ memset(&sharedInfo, 0, sizeof(sharedInfo)); sharedInfo.algId.algorithm = kekOid->oid; @@ -1321,129 +1071,107 @@ SecCmsUtilDecryptSymKeyECDH( sharedInfo.suppPubInfo.Length = 4; sharedInfo.suppPubInfo.Data = keyLenAsBytes; if (!SEC_ASN1EncodeItem(pool, &sharedInfoEnc, - &sharedInfo, ECC_CMS_SharedInfoTemplate)) { - rv = internalComponentErr; - goto loser; + &sharedInfo, ECC_CMS_SharedInfoTemplate)) { + rv = internalComponentErr; + goto out; } dumpBuf("receiver encoded SharedInfo", &sharedInfoEnc); dumpBuf("receiver IV", &iv); dumpBuf("receiver UKM", ukm); dumpBuf("sender's public key", pubKey); - /* - * Using the Sec-layer CSPDL, "other's" public key specified as ECPOint param. Which - * is fortunate because that's what we have... - */ - memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - rv = SecKeyGetCSPHandle(privkey, &refCspHand); - if(rv) { - CSSM_PERROR("SecKeyGetCSPHandle", rv); - goto loser; + /* pubKey is bit string, convert here */ + theirKeySizeInBits = pubKey->Length; + pubKey->Length = (theirKeySizeInBits + 7) >> 3; + theirPubData = CFDataCreate(NULL, pubKey->Data, pubKey->Length); + theirKeyLen = CFNumberCreate(NULL, kCFNumberSInt32Type, &theirKeySizeInBits); + const void *keys[] = { kSecAttrKeyType, kSecAttrKeyClass, kSecAttrKeySizeInBits }; + const void *values[] = { kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClassPublic, theirKeyLen}; + theirKeyAttrs = CFDictionaryCreate(NULL, keys, values, 3, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + theirPubKey = SecKeyCreateWithData(theirPubData, theirKeyAttrs, &error); + if (error) { + dprintf("SecKeyCreateWithData: failed\n"); + goto out; + } + + /* Derive KEK */ + sharedInfoData = CFDataCreate(NULL, sharedInfoEnc.Data, sharedInfoEnc.Length); + int32_t ecdh_key_key_len = (kekSizeBits + 7) >> 3; + kekLen = CFNumberCreate(NULL, kCFNumberSInt32Type, &ecdh_key_key_len); + const void *kekKeys[] = { kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo }; + const void *kekValues[] = { kekLen, sharedInfoData }; + kekParams = CFDictionaryCreate(NULL, kekKeys, kekValues, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + kekData = SecKeyCopyKeyExchangeResult(privkey, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1, + theirPubKey, kekParams, &error); + if (error) { + dprintf("SecKeyCopyKeyExchangeResult: failed\n"); + goto out; } - rv = SecKeyGetCredentials(privkey, - CSSM_ACL_AUTHORIZATION_DERIVE, - kSecCredentialTypeDefault, - &accessCred); + + /* + * Decrypt the raw CEK bits with the KEK we just derived + */ + CSSM_DATA cek = { 0, NULL }; + rv = CCCryptorCreate(kCCDecrypt, alg, options, + CFDataGetBytePtr(kekData), CFDataGetLength(kekData), iv.Data, &ciphercc); if (rv) { - CSSM_PERROR("SecKeyGetCredentials", rv); - goto loser; - } - crtn = CSSM_CSP_CreateDeriveKeyContext(refCspHand, - CSSM_ALGID_ECDH_X963_KDF, - kekOid->cssmAlgorithm, // algorithm of the KEK - kekSizeBits, - &creds, - ourPrivKeyCssm, // BaseKey - 0, // IterationCount - &sharedInfoEnc, // Salt - 0, // Seed - &ccHand); - if(crtn) { - CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn); - goto loser; + dprintf("CCCryptorCreate failed: %d\n", (int)rv); + goto out; } - crtn = CSSM_DeriveKey(ccHand, - pubKey, // param - CSSM_KEYUSE_ANY, - CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, // cred/acl - &kekDerive); - CSSM_DeleteContext(ccHand); - ccHand = 0; - if(crtn) { - CSSM_PERROR("CSSM_DeriveKey", crtn); - goto loser; + size_t expectedKeyLength = CCCryptorGetOutputLength(ciphercc, encKey->Length, true); + cek.Data = PORT_ArenaAlloc(pool, expectedKeyLength); + size_t bytes_output = 0; + rv = CCCryptorUpdate(ciphercc, encKey->Data, encKey->Length, cek.Data, expectedKeyLength, &bytes_output); + if (rv) { + dprintf("CCCryptorUpdate failed: %d\n", (int)rv); + goto out; } - - /* - * Decrypt the encrypted key bits with the KEK key. - */ - crtn = CSSM_CSP_CreateSymmetricContext(refCspHand, - kekOid->cssmAlgorithm, - kekMode, - NULL, // access cred - &kekDerive, - &iv, // InitVector - /* FIXME is this variable too? */ - CSSM_PADDING_PKCS7, - NULL, // Params - &ccHand); - if(rv) { - CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv); - goto loser; + size_t final_bytes_output = 0; + rv = CCCryptorFinal(ciphercc, cek.Data+bytes_output, expectedKeyLength - bytes_output, &final_bytes_output); + if (rv) { + dprintf("CCCryptorFinal failed: %d\n", (int)rv); + goto out; } - - memset(&wrappedKey, 0, sizeof(CSSM_KEY)); - memset(&unwrappedKey, 0, sizeof(CSSM_KEY)); + cek.Length = bytes_output + final_bytes_output; - bulkAlg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); - if(bulkAlg == CSSM_ALGID_NONE) { - dprintf("SecCmsUtilDecryptSymKeyECDH: unknown bulk alg\n"); - goto loser; - } - - wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; - wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; - wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; - wrappedKey.KeyHeader.AlgorithmId = bulkAlg; - wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; - wrappedKey.KeyHeader.WrapAlgorithmId = kekOid->cssmAlgorithm; - wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; - wrappedKey.KeyData = *encKey; - - crtn = CSSM_UnwrapKey(ccHand, - NULL, /* publicKey */ - &wrappedKey, - CSSM_KEYUSE_DECRYPT, - CSSM_KEYATTR_EXTRACTABLE, - &keyLabel, - NULL, /* rcc */ - &unwrappedKey, - &descriptiveData); - CSSM_DeleteContext(ccHand); - ccHand = 0; - if(crtn) { - CSSM_PERROR("CSSM_UnwrapKey", crtn); - goto loser; + /* create the SecSymmetricKeyRef */ + cekData = CFDataCreate(NULL, cek.Data, cek.Length); + keyType = SECOID_CopyKeyTypeByTag(bulkalgtag); + if (!keyType) { + goto out; } - rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &outKey); - if (rv) { - CSSM_PERROR("SecKeyCreateWithCSSMKey", rv); + cekParams = CFDictionaryCreateMutable(NULL, 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (!cekParams) { + goto out; } - -loser: + CFDictionaryAddValue(cekParams, kSecAttrKeyType, keyType); + outKey = SecKeyCreateFromData(cekParams, cekData, NULL); + +out: if(pool != NULL) { - PORT_FreeArena(pool, PR_FALSE); - } - if(kekDerive.KeyData.Data) { - CSSM_FreeKey(refCspHand, NULL, &kekDerive, CSSM_FALSE); - } + PORT_FreeArena(pool, PR_FALSE); + } + if (theirPubData) { CFRelease(theirPubData); } + if (theirKeyLen) { CFRelease(theirKeyLen); } + if (theirPubKey) { CFRelease(theirPubKey); } + if (theirKeyAttrs) { CFRelease(theirKeyAttrs); } + if (sharedInfoData) { CFRelease(sharedInfoData); } + if (kekLen) { CFRelease(kekLen); } + if (kekParams) { CFRelease(kekParams); } + if (kekData) { CFRelease(kekData); } + if (error) { CFRelease(error); } + if (ciphercc) { CCCryptorRelease(ciphercc); } + if (cekData) { CFRelease(cekData); } + if (keyType) { CFRelease(keyType); } + if (cekParams) { CFRelease(cekParams); } if(outKey == NULL) { - PORT_SetError(SEC_ERROR_NO_KEY); + PORT_SetError(SEC_ERROR_NO_KEY); } return outKey; } - - - diff --git a/OSX/libsecurity_smime/lib/cmsrecinfo.c b/OSX/libsecurity_smime/lib/cmsrecinfo.c index 2d5e39e2..3eb0effb 100644 --- a/OSX/libsecurity_smime/lib/cmsrecinfo.c +++ b/OSX/libsecurity_smime/lib/cmsrecinfo.c @@ -599,8 +599,6 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul &kari->ukm, &kari->keyEncAlg, &oiok->id.originatorPublicKey.publicKey); - /* this is a BIT STRING */ - oiok->id.originatorPublicKey.publicKey.Length <<= 3; break; default: @@ -688,8 +686,6 @@ SecCmsRecipientInfoUnwrapBulkKey(SecCmsRecipientInfoRef ri, int subIndex, SecCmsOriginatorPublicKey *opk = &oiok->id.originatorPublicKey; /* FIXME - verify opk->algorithmIdentifier here? */ CSSM_DATA senderPubKey = opk->publicKey; - /* Bit string, convert here */ - senderPubKey.Length = (senderPubKey.Length + 7) >> 3; CSSM_DATA_PTR ukm = &kari->ukm; bulkkey = SecCmsUtilDecryptSymKeyECDH(privkey, enckey, ukm, encalg, bulkalgtag, &senderPubKey); break; diff --git a/OSX/libsecurity_smime/lib/cmsreclist.c b/OSX/libsecurity_smime/lib/cmsreclist.c index f9b194bc..cfadee8c 100644 --- a/OSX/libsecurity_smime/lib/cmsreclist.c +++ b/OSX/libsecurity_smime/lib/cmsreclist.c @@ -172,6 +172,7 @@ nss_cms_recipient_list_destroy(SecCmsRecipient **recipient_list) PK11_FreeSlot(recipient->slot); #endif PORT_Free(recipient); + recipient_list[i] = NULL; } PORT_Free(recipient_list); } diff --git a/OSX/libsecurity_smime/lib/cmssigdata.c b/OSX/libsecurity_smime/lib/cmssigdata.c index 6e85d7b5..ebdc1bab 100644 --- a/OSX/libsecurity_smime/lib/cmssigdata.c +++ b/OSX/libsecurity_smime/lib/cmssigdata.c @@ -634,6 +634,10 @@ SecCmsSignedDataDecodeAfterEnd(SecCmsSignedDataRef sigd) SecCmsSignerInfoRef *signerinfos; int i; + if (!sigd) { + return SECFailure; + } + signerinfos = sigd->signerInfos; /* set cmsg and sigd backpointers for all the signerinfos */ @@ -772,16 +776,7 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, contentType = SecCmsContentInfoGetContentTypeOID(cinfo); /* verify signature */ -#if SECTRUST_OSX -#warning STU: - // timestamp policy is currently unsupported; use codesign policy only - #if !NDEBUG - syslog(LOG_ERR, "SecCmsSignedDataVerifySignerInfo: using codesign policy without timestamp verification"); - #endif - CFTypeRef timeStampPolicies=SecPolicyCreateWithProperties(kSecPolicyAppleCodeSigning, NULL); -#else CFTypeRef timeStampPolicies=SecPolicyCreateAppleTimeStampingAndRevocationPolicies(policies); -#endif status = SecCmsSignerInfoVerifyWithPolicy(signerinfo, timeStampPolicies, digest, contentType); CFReleaseSafe(timeStampPolicies); @@ -790,10 +785,6 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, status2 = SecCmsSignerInfoVerifyCertificate(signerinfo, keychainOrArray, policies, trustRef); dprintf("SecCmsSignedDataVerifySignerInfo: status %d status2 %d\n", (int) status, (int)status2); - if(status || status2) { - syslog(LOG_ERR,"SecCmsSignedDataVerifySignerInfo: status %d status2 %d.", (int) status, (int)status2); - syslog(LOG_ERR,"SecCmsSignedDataVerifySignerInfo: verify status %d", signerinfo->verificationStatus); - } /* The error from SecCmsSignerInfoVerify() supercedes error from SecCmsSignerInfoVerifyCertificate(). */ if (status) return status; @@ -969,7 +960,7 @@ SecCmsSignedDataGetDigestByAlgTag(SecCmsSignedDataRef sigd, SECOidTag algtag) return NULL; } idx = SecCmsAlgArrayGetIndexByAlgTag(sigd->digestAlgorithms, algtag); - return sigd->digests[idx]; + return (idx >= 0) ? sigd->digests[idx] : NULL; } /* diff --git a/OSX/libsecurity_smime/lib/cmssiginfo.c b/OSX/libsecurity_smime/lib/cmssiginfo.c index c2111395..1bc932dc 100644 --- a/OSX/libsecurity_smime/lib/cmssiginfo.c +++ b/OSX/libsecurity_smime/lib/cmssiginfo.c @@ -501,11 +501,6 @@ loser: SECITEM_FreeItem (&signature, PR_FALSE); if (privkey) SECKEY_DestroyPrivateKey(privkey); - if((algID != NULL) & (algID != &freeAlgID)) { - /* this is dicey - this was actually mallocd by either SecCertificate or - * by SecKey...it all boils down to a free() in the end though. */ - SECOID_DestroyAlgorithmID((SECAlgorithmID *)algID, PR_FALSE); - } if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE); return SECFailure; @@ -671,7 +666,6 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt } if ((poolp = PORT_NewArena (1024)) == NULL) { - syslog(LOG_ERR, "SecCmsSignerInfoVerifyWithPolicy: failed to make new Arena %d", PORT_GetError()); vs = SecCmsVSProcessingError; goto loser; } @@ -689,7 +683,6 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt if (SecCmsAttributeArrayEncode(poolp, &(signerinfo->authAttr), &encoded_attrs) == NULL || encoded_attrs.Data == NULL || encoded_attrs.Length == 0) { - syslog(LOG_ERR, "SecCmsSignerInfoVerifyWithPolicy: failed to encode attributes"); vs = SecCmsVSProcessingError; goto loser; } diff --git a/OSX/libsecurity_smime/lib/cmsutil.c b/OSX/libsecurity_smime/lib/cmsutil.c index 73587d85..c0f89054 100644 --- a/OSX/libsecurity_smime/lib/cmsutil.c +++ b/OSX/libsecurity_smime/lib/cmsutil.c @@ -269,12 +269,18 @@ SecCmsUtilMakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg) } case SEC_OID_EC_PUBLIC_KEY: switch(hashalg) { - /* + /* * Note this is only used when signing and verifying signed attributes, * In which case we really do want the combined ECDSA_WithSHA1 alg... */ case SEC_OID_SHA1: return SEC_OID_ECDSA_WithSHA1; + case SEC_OID_SHA256: + return SEC_OID_ECDSA_WITH_SHA256; + case SEC_OID_SHA384: + return SEC_OID_ECDSA_WITH_SHA384; + case SEC_OID_SHA512: + return SEC_OID_ECDSA_WITH_SHA512; default: return SEC_OID_UNKNOWN; } diff --git a/OSX/libsecurity_smime/lib/cryptohi.c b/OSX/libsecurity_smime/lib/cryptohi.c index d80963c0..4f39abf4 100644 --- a/OSX/libsecurity_smime/lib/cryptohi.c +++ b/OSX/libsecurity_smime/lib/cryptohi.c @@ -43,6 +43,18 @@ #include #include +#if !USE_CDSA_CRYPTO +#include +#endif + +#ifdef NDEBUG +#define CSSM_PERROR(f, r) +#define dprintf(args...) +#else +#define CSSM_PERROR(f, r) cssmPerror(f, r) +#define dprintf(args...) fprintf(stderr, args) +#endif + static CSSM_CSP_HANDLE gCsp = 0; static char gCssmInitialized = 0; @@ -92,6 +104,63 @@ loser: return gCsp; } +OSStatus cmsNullWrapKey(SecKeyRef refKey, + CSSM_KEY_PTR rawKey) +{ + CSSM_DATA descData = {0, 0}; + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + CSSM_ACCESS_CREDENTIALS creds; + CSSM_CSP_HANDLE refCspHand = CSSM_INVALID_HANDLE; + const CSSM_KEY *cssmKey = NULL; + uint32 keyAttr; + + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + memset(rawKey, 0, sizeof(CSSM_KEY)); + + crtn = SecKeyGetCSSMKey(refKey, &cssmKey); + if(crtn) { + CSSM_PERROR("SecKeyGetCSSMKey", crtn); + goto loser; + } + crtn = SecKeyGetCSPHandle(refKey, &refCspHand); + if(crtn) { + CSSM_PERROR("SecKeyGetCSPHandle", crtn); + goto loser; + } + + crtn = CSSM_CSP_CreateSymmetricContext(refCspHand, + CSSM_ALGID_NONE, + CSSM_ALGMODE_NONE, + &creds, + NULL, // unwrappingKey + NULL, // initVector + CSSM_PADDING_NONE, + 0, // Params + &ccHand); + if(crtn) { + CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn); + return crtn; + } + + keyAttr = rawKey->KeyHeader.KeyAttr; + keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE | + CSSM_KEYATTR_MODIFIABLE); + keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE; + crtn = CSSM_WrapKey(ccHand, + &creds, + cssmKey, + &descData, + rawKey); + if(crtn != CSSM_OK) { + CSSM_PERROR("CSSM_WrapKey", crtn); + } + CSSM_DeleteContext(ccHand); + +loser: + return crtn; +} + CSSM_ALGORITHMS SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag) { @@ -99,140 +168,263 @@ SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag) return oidData ? oidData->cssmAlgorithm : CSSM_ALGID_NONE; } -static SECStatus SEC_CssmRtnToSECStatus(CSSM_RETURN rv) -{ - CSSM_RETURN crtn = CSSM_ERRCODE(rv); - switch(crtn) { - case CSSM_ERRCODE_USER_CANCELED: - case CSSM_ERRCODE_OPERATION_AUTH_DENIED: - case CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED: - return SEC_ERROR_USER_CANCELLED; - case CSSM_ERRCODE_NO_USER_INTERACTION: - return SEC_ERROR_NO_USER_INTERACTION; - case CSSMERR_CSP_KEY_USAGE_INCORRECT: - return SEC_ERROR_INADEQUATE_KEY_USAGE; - default: - fprintf(stderr, "CSSM_SignData returned: %08X\n", (uint32_t)rv); - return SEC_ERROR_LIBRARY_FAILURE; + +static void SEC_PrintCFError(CFErrorRef CF_RELEASES_ARGUMENT error) { + if (error) { + CFStringRef errorDesc = CFErrorCopyDescription(error); + fprintf(stderr, "SecKey API returned: %ld, %s", CFErrorGetCode(error), + errorDesc ? CFStringGetCStringPtr(errorDesc, kCFStringEncodingUTF8) : ""); + CFRelease(error); + if (errorDesc) { CFRelease(errorDesc); } } -} -SECStatus -SEC_SignData(SECItem *result, unsigned char *buf, int len, - SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag) -{ - const CSSM_ACCESS_CREDENTIALS *accessCred; - CSSM_ALGORITHMS algorithm; - CSSM_CC_HANDLE cc = 0; - CSSM_CSP_HANDLE csp; - OSStatus rv; - CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; - CSSM_DATA sig = {}; - const CSSM_KEY *key; +} - algorithm = SECOID_FindyCssmAlgorithmByTag(SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag)); - if (!algorithm) - { - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - rv = SECFailure; - goto loser; +/* The new SecKey API has made this very painful */ +static SecKeyAlgorithm SECOID_FindSecKeyAlgorithmByTags(SECOidTag sigAlgTag, SECOidTag digAlgTag, bool isDigest) { + switch(sigAlgTag) { + case(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION): + if (digAlgTag == SEC_OID_MD5) { + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 : + kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5); + } + break; + case(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION): + if (digAlgTag == SEC_OID_SHA1) { + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1); + } + break; + case(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION): + if (digAlgTag == SEC_OID_SHA256) { + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256); + } + break; + case(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION): + if (digAlgTag == SEC_OID_SHA384) { + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384); + } + break; + case(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION): + if (digAlgTag == SEC_OID_SHA512) { + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512); + } + break; + case(SEC_OID_PKCS1_RSA_ENCRYPTION): + switch (digAlgTag) { + case (SEC_OID_MD5): + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 : + kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5); + case(SEC_OID_SHA1): + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1); + case(SEC_OID_SHA256): + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256); + case(SEC_OID_SHA384): + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384); + case(SEC_OID_SHA512): + return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 + : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512); + default: + return NULL; + } + case(SEC_OID_ECDSA_WithSHA1): + if (digAlgTag == SEC_OID_SHA1) { + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA1); + } + break; + case(SEC_OID_ECDSA_WITH_SHA256): + if (digAlgTag == SEC_OID_SHA256) { + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA256); + } + break; + case(SEC_OID_ECDSA_WITH_SHA384): + if (digAlgTag == SEC_OID_SHA384) { + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA384); + } + break; + case(SEC_OID_ECDSA_WITH_SHA512): + if (digAlgTag == SEC_OID_SHA512) { + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA512); + } + break; + case(SEC_OID_EC_PUBLIC_KEY): + case(SEC_OID_SECP_256_R1): + case(SEC_OID_SECP_384_R1): + case(SEC_OID_SECP_521_R1): + switch (digAlgTag) { + case(SEC_OID_SHA1): + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA1); + case(SEC_OID_SHA256): + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA256); + case(SEC_OID_SHA384): + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA384); + case(SEC_OID_SHA512): + return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962 + : kSecKeyAlgorithmECDSASignatureMessageX962SHA512); + default: + return NULL; + } + default: + return NULL; } + return NULL; +} - rv = SecKeyGetCSPHandle(pk, &csp); - if (rv) { - PORT_SetError(SEC_ERROR_BAD_KEY); - goto loser; +CFStringRef SECOID_CopyKeyTypeByTag(SECOidTag tag) { + CFStringRef keyType = NULL; + + switch(tag) { + case(SEC_OID_RC2_CBC): + case(SEC_OID_CMS_RC2_KEY_WRAP): + keyType = kSecAttrKeyTypeRC2; + break; + case(SEC_OID_RC4): + keyType = kSecAttrKeyTypeRC4; + break; + case(SEC_OID_DES_ECB): + case(SEC_OID_DES_CBC): + case(SEC_OID_DES_OFB): + case(SEC_OID_DES_CFB): + keyType = kSecAttrKeyTypeDES; + break; + case(SEC_OID_DES_EDE): + case(SEC_OID_DES_EDE3_CBC): + case(SEC_OID_CMS_3DES_KEY_WRAP): + keyType = kSecAttrKeyType3DES; + break; + case(SEC_OID_AES_128_ECB): + case(SEC_OID_AES_128_CBC): + case(SEC_OID_AES_192_ECB): + case(SEC_OID_AES_192_CBC): + case(SEC_OID_AES_256_ECB): + case(SEC_OID_AES_256_CBC): + case(SEC_OID_AES_128_KEY_WRAP): + case(SEC_OID_AES_192_KEY_WRAP): + case(SEC_OID_AES_256_KEY_WRAP): + keyType = kSecAttrKeyTypeAES; + break; + default: + keyType = NULL; } - rv = SecKeyGetCSSMKey(pk, &key); - if (rv) { - PORT_SetError(SEC_ERROR_BAD_KEY); - goto loser; + + return keyType; +} + +static SECStatus SGN_SignAll(uint8_t *buf, size_t len, + SecPrivateKeyRef pk, SECItem *resultSignature, + SECOidTag digAlgTag, SECOidTag sigAlgTag, + bool isDigest) { + OSStatus rv = SECFailure; + CFDataRef signature = NULL, dataToSign = NULL; + CFErrorRef error = NULL; + SecKeyAlgorithm keyAlg = NULL; + + keyAlg = SECOID_FindSecKeyAlgorithmByTags(sigAlgTag, digAlgTag, isDigest); + + /* we no longer support signing with MD5 */ + if (keyAlg == kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5 || + keyAlg == kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5) { + fprintf(stderr, "CMS signature failed: MD5 algorithm is disallowed for generating signatures."); + rv = SEC_ERROR_INVALID_ALGORITHM; + goto out; } - rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); - if (rv) { - PORT_SetError(SEC_ERROR_BAD_KEY); - goto loser; + + if (keyAlg == NULL) { + rv = SEC_ERROR_INVALID_ALGORITHM; + goto out; } - rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, accessCred, key, &cc); - if (rv) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; + dataToSign = CFDataCreate(NULL, buf, len); + if (!dataToSign) { + goto out; } - rv = CSSM_SignData(cc, &dataBuf, 1, CSSM_ALGID_NONE, &sig); - if (rv) { - SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); - PORT_SetError(code); - goto loser; + signature = SecKeyCreateSignature(pk, keyAlg, dataToSign, &error); + if (!signature) { + goto out; } - result->Length = sig.Length; - result->Data = sig.Data; + CFIndex signatureLength = CFDataGetLength(signature); + if (signatureLength < 0 || signatureLength > 1024) { + goto out; + } + resultSignature->Data = (uint8_t *)malloc(signatureLength); + if (!resultSignature->Data) { + goto out; + } -loser: - if (cc) - CSSM_DeleteContext(cc); + memcpy(resultSignature->Data, CFDataGetBytePtr(signature), signatureLength); + resultSignature->Length = signatureLength; + rv = SECSuccess; +out: + if (signature) { CFRelease(signature); } + if (dataToSign) {CFRelease(dataToSign); } + SEC_PrintCFError(error); + if (rv) { + PORT_SetError(rv); + } return rv; } +SECStatus +SEC_SignData(SECItem *result, unsigned char *buf, int len, + SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag) +{ + return SGN_SignAll(buf, len, pk, result, digAlgTag, sigAlgTag, false); +} + SECStatus SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest) { - const CSSM_ACCESS_CREDENTIALS *accessCred; - CSSM_ALGORITHMS digalg, sigalg; - CSSM_CC_HANDLE cc = 0; - CSSM_CSP_HANDLE csp; - const CSSM_KEY *key; - CSSM_DATA sig = {}; - OSStatus rv; + return SGN_SignAll(digest->Data, digest->Length, pk, result, digAlgTag, sigAlgTag, true); +} - digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); - sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); - if (!digalg || !sigalg) - { - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - rv = SECFailure; - goto loser; +static SECStatus VFY_VerifyAll(uint8_t *buf, size_t len, + SecPublicKeyRef pk, SECItem *sig, + SECOidTag digAlgTag, SECOidTag sigAlgTag, + bool isDigest) { + OSStatus rv = SECFailure; + CFDataRef signature = NULL, data = NULL; + CFErrorRef error = NULL; + SecKeyAlgorithm keyAlg = NULL; + + signature = CFDataCreate(NULL, sig->Data, sig->Length); + data = CFDataCreate(NULL, buf, len); + if (!signature || !data) { + goto out; } - rv = SecKeyGetCSPHandle(pk, &csp); - if (rv) { - PORT_SetError(SEC_ERROR_BAD_KEY); - goto loser; - } - rv = SecKeyGetCSSMKey(pk, &key); - if (rv) { - PORT_SetError(SEC_ERROR_BAD_KEY); - goto loser; - } - rv = SecKeyGetCredentials(pk, CSSM_ACL_AUTHORIZATION_SIGN, kSecCredentialTypeDefault, &accessCred); - if (rv) { - PORT_SetError(SEC_ERROR_BAD_KEY); - goto loser; + keyAlg = SECOID_FindSecKeyAlgorithmByTags(sigAlgTag, digAlgTag, isDigest); + if (keyAlg == NULL) { + rv = SEC_ERROR_INVALID_ALGORITHM; + goto out; } - rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, accessCred, key, &cc); - if (rv) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; + if(SecKeyVerifySignature(pk, keyAlg, data, signature, &error)) { + rv = SECSuccess; } - rv = CSSM_SignData(cc, digest, 1, digalg, &sig); +out: + if (signature) { CFRelease(signature); } + if (data) { CFRelease(data); } + SEC_PrintCFError(error); if (rv) { - SECErrorCodes code = SEC_CssmRtnToSECStatus(rv); - PORT_SetError(code); - goto loser; + PORT_SetError(rv); } - - result->Length = sig.Length; - result->Data = sig.Data; - -loser: - if (cc) - CSSM_DeleteContext(cc); - return rv; } @@ -241,78 +433,16 @@ VFY_VerifyData(unsigned char *buf, int len, SecPublicKeyRef pk, SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) { - SECOidTag algTag; - CSSM_ALGORITHMS algorithm; - CSSM_CC_HANDLE cc = 0; - CSSM_CSP_HANDLE csp; - OSStatus rv = SECFailure; - CSSM_DATA dataBuf = { (uint32)len, (uint8 *)buf }; - const CSSM_KEY *key; - - algTag = SecCmsUtilMakeSignatureAlgorithm(digAlgTag, sigAlgTag); - algorithm = SECOID_FindyCssmAlgorithmByTag(algTag); - if (!algorithm) - { - rv = algTag == SEC_OID_UNKNOWN ? SecCmsVSSignatureAlgorithmUnknown : SecCmsVSSignatureAlgorithmUnsupported; - goto loser; - } - - rv = SecKeyGetCSPHandle(pk, &csp); - if (rv) - goto loser; - rv = SecKeyGetCSSMKey(pk, &key); - if (rv) - goto loser; - - rv = CSSM_CSP_CreateSignatureContext(csp, algorithm, NULL, key, &cc); - if (rv) - goto loser; - - rv = CSSM_VerifyData(cc, &dataBuf, 1, CSSM_ALGID_NONE, sig); - -loser: - if (cc) - CSSM_DeleteContext(cc); - - return rv; + return VFY_VerifyAll(buf, len, pk, sig, + digAlgTag, sigAlgTag, false); } SECStatus VFY_VerifyDigest(SECItem *digest, SecPublicKeyRef pk, SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx) { - CSSM_ALGORITHMS sigalg, digalg; - CSSM_CC_HANDLE cc = 0; - CSSM_CSP_HANDLE csp; - const CSSM_KEY *key; - OSStatus rv; - - digalg = SECOID_FindyCssmAlgorithmByTag(digAlgTag); - sigalg = SECOID_FindyCssmAlgorithmByTag(sigAlgTag); - if (!digalg || !sigalg) - { - rv = digAlgTag == SEC_OID_UNKNOWN || sigAlgTag == SEC_OID_UNKNOWN ? SecCmsVSSignatureAlgorithmUnknown : SecCmsVSSignatureAlgorithmUnsupported; - goto loser; - } - - rv = SecKeyGetCSPHandle(pk, &csp); - if (rv) - goto loser; - rv = SecKeyGetCSSMKey(pk, &key); - if (rv) - goto loser; - - rv = CSSM_CSP_CreateSignatureContext(csp, sigalg, NULL, key, &cc); - if (rv) - goto loser; - - rv = CSSM_VerifyData(cc, digest, 1, digalg, sig); - -loser: - if (cc) - CSSM_DeleteContext(cc); - - return rv; + return VFY_VerifyAll(digest->Data, digest->Length, pk, sig, + digAlgTag, sigAlgTag, true); } SECStatus @@ -320,233 +450,61 @@ WRAP_PubWrapSymKey(SecPublicKeyRef publickey, SecSymmetricKeyRef bulkkey, CSSM_DATA_PTR encKey) { - CSSM_WRAP_KEY wrappedKey = {}; - //CSSM_WRAP_KEY wrappedPk = {} - //CSSM_KEY upk = {}; - CSSM_CC_HANDLE cc = 0; - CSSM_CSP_HANDLE pkCsp, bkCsp; - const CSSM_KEY *pk, *bk, *pubkey; OSStatus rv; - CSSM_ACCESS_CREDENTIALS accessCred = {}; - - rv = SecKeyGetCSPHandle(publickey, &pkCsp); - if (rv) - goto loser; - rv = SecKeyGetCSSMKey(publickey, &pk); - if (rv) - goto loser; - - rv = SecKeyGetCSPHandle(bulkkey, &bkCsp); - if (rv) - goto loser; - rv = SecKeyGetCSSMKey(bulkkey, &bk); - if (rv) - goto loser; - -#if 1 - pubkey = pk; -#else - /* We need to get the publickey out of it's pkCsp and into the bkCsp so we can operate with it. */ - - /* Make a NULL wrap symmetric context to extract the public key from pkCsp. */ - rv = CSSM_CSP_CreateSymmetricContext(pkCsp, - CSSM_ALGID_NONE, - CSSM_MODE_NONE, - NULL, /* accessCred */ - NULL, /* key */ - NULL, /* iv */ - CSSM_PADDING_NONE, - NULL, /* reserved */ - &cc); - if (rv) - goto loser; - rv = CSSM_WrapKey(cc, - NULL /* accessCred */, - pk, - NULL /* descriptiveData */, - &wrappedPk); - CSSM_DeleteContext(cc); - cc = 0; - - /* Make a NULL unwrap symmetric context to import the public key into bkCsp. */ - rv = CSSM_CSP_CreateSymmetricContext(bkCsp, - CSSM_ALGID_NONE, - CSSM_MODE_NONE, - NULL, /* accessCred */ - NULL, /* key */ - NULL, /* iv */ - CSSM_PADDING_NONE, - NULL, /* reserved */ - &cc); - if (rv) - goto loser; - rv = CSSM_UnwrapKey(cc, NULL, &wrappedPk, usage, attr, NULL /* label */, NULL /* rcc */, &upk, NULL /* descriptiveData */); - CSSM_DeleteContext(cc); - cc = 0; - - pubkey = &upk; -#endif + CSSM_KEY bk; - rv = CSSM_CSP_CreateAsymmetricContext(bkCsp, - pubkey->KeyHeader.AlgorithmId, - &accessCred, - pubkey, - CSSM_PADDING_PKCS1, - &cc); - if (rv) - goto loser; - - { - /* Set the wrapped key format to indicate we want just the raw bits encrypted. */ - CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, sizeof(uint32) }; - contextAttribute.Attribute.Uint32 = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; - rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); - if (rv) - goto loser; - } - - { - /* Set the mode to CSSM_ALGMODE_PKCS1_EME_V15. */ - CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_MODE, sizeof(uint32) }; - contextAttribute.Attribute.Uint32 = CSSM_ALGMODE_NONE; /* CSSM_ALGMODE_PKCS1_EME_V15 */ - rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); - if (rv) - goto loser; - } - - { - // @@@ Stick in an empty initVector to work around a csp bug. - CSSM_DATA initVector = {}; - CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; - contextAttribute.Attribute.Data = &initVector; - rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); - if (rv) - goto loser; + rv = cmsNullWrapKey(bulkkey, &bk); + if (rv) { + return rv; } - rv = CSSM_WrapKey(cc, - &accessCred, - bk, - NULL, /* descriptiveData */ - &wrappedKey); - if (rv) - goto loser; - - // @@@ Fix leaks! - if (encKey->Length < wrappedKey.KeyData.Length) - abort(); - encKey->Length = wrappedKey.KeyData.Length; - memcpy(encKey->Data, wrappedKey.KeyData.Data, encKey->Length); - CSSM_FreeKey(bkCsp, NULL /* credentials */, &wrappedKey, FALSE); - -loser: - if (cc) - CSSM_DeleteContext(cc); - - return rv; + return SecKeyEncrypt(publickey, kSecPaddingPKCS1, + bk.KeyData.Data, bk.KeyData.Length, + encKey->Data, &encKey->Length); } + SecSymmetricKeyRef WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) { - SecSymmetricKeyRef bulkkey = NULL; - CSSM_WRAP_KEY wrappedKey = {}; - CSSM_CC_HANDLE cc = 0; - CSSM_CSP_HANDLE pkCsp; - const CSSM_KEY *pk; - CSSM_KEY unwrappedKey = {}; - const CSSM_ACCESS_CREDENTIALS *accessCred; - CSSM_DATA descriptiveData = {}; - CSSM_ALGORITHMS bulkalg; - OSStatus rv; - - rv = SecKeyGetCSPHandle(privkey, &pkCsp); - if (rv) - goto loser; - rv = SecKeyGetCSSMKey(privkey, &pk); - if (rv) - goto loser; - rv = SecKeyGetCredentials(privkey, - CSSM_ACL_AUTHORIZATION_DECRYPT, /* @@@ Should be UNWRAP */ - kSecCredentialTypeDefault, - &accessCred); - if (rv) - goto loser; - - bulkalg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag); - if (!bulkalg) - { - rv = SEC_ERROR_INVALID_ALGORITHM; - goto loser; + CFDataRef encryptedKey = NULL, bulkkey = NULL; + CFMutableDictionaryRef keyparams = NULL; + CFStringRef keyType = NULL; + CFErrorRef error = NULL; + SecSymmetricKeyRef bk = NULL; + + /* decrypt the key */ + encryptedKey = CFDataCreate(NULL, encKey->Data, encKey->Length); + if (!encryptedKey) { + goto out; } - rv = CSSM_CSP_CreateAsymmetricContext(pkCsp, - pk->KeyHeader.AlgorithmId, - accessCred, - pk, - CSSM_PADDING_PKCS1, - &cc); - if (rv) - goto loser; - - { - // @@@ Stick in an empty initvector to work around a csp bug. - CSSM_DATA initVector = {}; - CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_INIT_VECTOR, sizeof(CSSM_DATA_PTR) }; - contextAttribute.Attribute.Data = &initVector; - rv = CSSM_UpdateContextAttributes(cc, 1, &contextAttribute); - if (rv) - goto loser; + bulkkey = SecKeyCreateDecryptedData(privkey, kSecKeyAlgorithmRSAEncryptionPKCS1, encryptedKey, &error); + if (!bulkkey) { + goto out; } - wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; - wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED; - wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; - wrappedKey.KeyHeader.AlgorithmId = bulkalg; - wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY; - wrappedKey.KeyHeader.WrapAlgorithmId = pk->KeyHeader.AlgorithmId; - wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; /* CSSM_ALGMODE_PKCS1_EME_V15 */ - wrappedKey.KeyData = *encKey; - - rv = CSSM_UnwrapKey(cc, - NULL, /* publicKey */ - &wrappedKey, - CSSM_KEYUSE_DECRYPT, - CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */, - NULL, /* keyLabel */ - NULL, /* rcc */ - &unwrappedKey, - &descriptiveData); - if (rv) { - SECErrorCodes code; - if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_USER_CANCELED - || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OPERATION_AUTH_DENIED - || CSSM_ERRCODE(rv) == CSSM_ERRCODE_OBJECT_USE_AUTH_DENIED) - code = SEC_ERROR_USER_CANCELLED; - else if (CSSM_ERRCODE(rv) == CSSM_ERRCODE_NO_USER_INTERACTION - || rv == CSSMERR_CSP_KEY_USAGE_INCORRECT) - code = SEC_ERROR_INADEQUATE_KEY_USAGE; - else - { - fprintf(stderr, "CSSM_UnwrapKey returned: %08X\n", (uint32_t)rv); - code = SEC_ERROR_LIBRARY_FAILURE; - } - - PORT_SetError(code); - goto loser; + /* create the SecSymmetricKeyRef */ + keyType = SECOID_CopyKeyTypeByTag(bulkalgtag); + if (!keyType) { + goto out; } - // @@@ Export this key from the csp/dl and import it to the standard csp - rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &bulkkey); - if (rv) - goto loser; - -loser: - if (rv) - PORT_SetError(rv); + keyparams = CFDictionaryCreateMutable(NULL, 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + if (!keyparams) { + goto out; + } - if (cc) - CSSM_DeleteContext(cc); + CFDictionaryAddValue(keyparams, kSecAttrKeyType, keyType); + bk = SecKeyCreateFromData(keyparams, bulkkey, NULL); - return bulkkey; +out: + if (encryptedKey) { CFRelease(encryptedKey); } + if (bulkkey) { CFRelease(bulkkey); } + if (keyparams) { CFRelease(keyparams); } + if (keyType) { CFRelease(keyType); } + SEC_PrintCFError(error); + return bk; } diff --git a/OSX/libsecurity_smime/lib/cryptohi.h b/OSX/libsecurity_smime/lib/cryptohi.h index f140c4ca..749c755a 100644 --- a/OSX/libsecurity_smime/lib/cryptohi.h +++ b/OSX/libsecurity_smime/lib/cryptohi.h @@ -137,6 +137,14 @@ extern SECStatus WRAP_PubWrapSymKey(SecPublicKeyRef publickey, extern SecSymmetricKeyRef WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag); +CFStringRef SECOID_CopyKeyTypeByTag(SECOidTag tag); + +/* + * NULL wrap a ref key to raw key in default format. + * The utility of this function is that it rescues the actual data content + * of the SecSymmetricKeyRef so that we can encrypt it. + */ +OSStatus cmsNullWrapKey(SecKeyRef refKey, CSSM_KEY_PTR rawKey); SEC_END_PROTOS diff --git a/OSX/libsecurity_smime/lib/smimeutil.c b/OSX/libsecurity_smime/lib/smimeutil.c index eacec1a0..989d27d5 100644 --- a/OSX/libsecurity_smime/lib/smimeutil.c +++ b/OSX/libsecurity_smime/lib/smimeutil.c @@ -366,6 +366,8 @@ nss_SMIME_FindCipherForSMIMECap(NSSSMIMECapability *cap) return smime_cipher_map[i].cipher; /* match found, point to cipher */ } +static int smime_keysize_by_cipher (unsigned long which); + /* * smime_choose_cipher - choose a cipher that works for all the recipients * @@ -509,6 +511,10 @@ done: if (poolp != NULL) PORT_FreeArena (poolp, PR_FALSE); + if (smime_keysize_by_cipher(chosen_cipher) < 128) { + /* you're going to use strong(er) crypto whether you like it or not */ + chosen_cipher = SMIME_DES_EDE3_168; + } return chosen_cipher; } diff --git a/OSX/libsecurity_smime/lib/tsaSupport.c b/OSX/libsecurity_smime/lib/tsaSupport.c index 46c3eee3..df2be402 100644 --- a/OSX/libsecurity_smime/lib/tsaSupport.c +++ b/OSX/libsecurity_smime/lib/tsaSupport.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "tsaSupport.h" #include "tsaSupportPriv.h" @@ -90,16 +91,16 @@ extern OSStatus impExpImportCertCommon( fprintf(stderr, "%s " fmt, buf, ## __VA_ARGS__); \ syslog(LOG_ERR, " " fmt, ## __VA_ARGS__); \ } } while (0) - #define tsa_secdebug(scope, format...) \ + #define tsa_secinfo(scope, format...) \ { \ syslog(LOG_NOTICE, format); \ - secdebug(scope, format); \ + secinfo(scope, format); \ printf(format); \ } #else - #define tsaDebug(args...) tsa_secdebug("tsa", ## args) -#define tsa_secdebug(scope, format...) \ - secdebug(scope, format) + #define tsaDebug(args...) tsa_secinfo("tsa", ## args) +#define tsa_secinfo(scope, format...) \ + secinfo(scope, format) #endif #ifndef NDEBUG @@ -524,9 +525,9 @@ static OSStatus sendTSARequestWithXPC(const unsigned char *tsaReq, size_t tsaReq xpc_connection_send_message_with_reply(con, message, xpc_queue, ^(xpc_object_t reply) { tsaDebug("xpc_connection_send_message_with_reply handler called back\n"); - dispatch_retain(waitSemaphore); + dispatch_retain_safe(waitSemaphore); - xpc_type_t xtype = xpc_get_type(reply); + xpc_type_t xtype = xpc_get_type(reply); if (XPC_TYPE_ERROR == xtype) { tsaDebug("message error: %s\n", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); } else if (XPC_TYPE_CONNECTION == xtype) @@ -595,15 +596,13 @@ static OSStatus sendTSARequestWithXPC(const unsigned char *tsaReq, size_t tsaReq } else { tsaDebug("unexpected message reply type %p\n", xtype); } - - dispatch_semaphore_signal(waitSemaphore); - dispatch_release(waitSemaphore); + if (waitSemaphore) { dispatch_semaphore_signal(waitSemaphore); } + dispatch_release_null(waitSemaphore); }); - { tsaDebug("waiting up to %d seconds for response from XPC\n", timeoutInSeconds); } - dispatch_semaphore_wait(waitSemaphore, finishTime); + if (waitSemaphore) { dispatch_semaphore_wait(waitSemaphore, finishTime); } - dispatch_release(waitSemaphore); + dispatch_release_null(waitSemaphore); xpc_release(tsaReqData); xpc_release(message); @@ -780,13 +779,22 @@ OSStatus SecCmsTSADefaultCallback(CFTypeRef context, void *messageImprintV, uint #endif } - CFStringRef url = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)context, kTSAContextKeyURL); + CFTypeRef url = CFDictionaryGetValue((CFDictionaryRef)context, kTSAContextKeyURL); if (!url) { tsaDebug("[TSA] missing URL for TSA (key: %s)\n", "kTSAContextKeyURL"); goto xit; } + CFStringRef urlStr = NULL; + if (CFURLGetTypeID() == CFGetTypeID(url)) { + urlStr = CFURLGetString(url); + } else { + require_quiet(CFStringGetTypeID() == CFGetTypeID(url), xit); + urlStr = url; + } + require_quiet(urlStr, xit); + /* If debugging, look at special values in the context to mess things up */ @@ -799,9 +807,9 @@ OSStatus SecCmsTSADefaultCallback(CFTypeRef context, void *messageImprintV, uint } // need to extract into buffer - CFIndex length = CFStringGetLength(url); // in 16-bit character units + CFIndex length = CFStringGetLength(urlStr); // in 16-bit character units tsaURL = malloc(6 * length + 1); // pessimistic - if (!CFStringGetCString(url, (char *)tsaURL, 6 * length + 1, kCFStringEncodingUTF8)) + if (!CFStringGetCString(urlStr, (char *)tsaURL, 6 * length + 1, kCFStringEncodingUTF8)) goto xit; tsaDebug("[TSA] URL for timestamp server: %s\n", tsaURL); diff --git a/OSX/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj b/OSX/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj index 101f10bc..0ea47bb6 100644 --- a/OSX/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj @@ -80,6 +80,8 @@ ACA9CE4A18BC4543005AD855 /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = ACBEE90D18B415B60021712D /* SecCMS.h */; }; ACBEE90C18B403470021712D /* SecCMS.c in Sources */ = {isa = PBXBuildFile; fileRef = ACBEE90B18B403470021712D /* SecCMS.c */; }; ACBEE90E18B415B60021712D /* SecCMS.h in Headers */ = {isa = PBXBuildFile; fileRef = ACBEE90D18B415B60021712D /* SecCMS.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D421AF641CA45E8C00A8E512 /* cms-01-basic.c in Sources */ = {isa = PBXBuildFile; fileRef = D421AF601CA45E4900A8E512 /* cms-01-basic.c */; }; + D421AF651CA45E9700A8E512 /* cms-01-basic.h in Headers */ = {isa = PBXBuildFile; fileRef = D421AF611CA45E4900A8E512 /* cms-01-basic.h */; }; F64399010420118A01CA2DCC /* cert.h in Headers */ = {isa = PBXBuildFile; fileRef = F64398FF0420118A01CA2DCC /* cert.h */; }; F64399020420118A01CA2DCC /* cert.c in Sources */ = {isa = PBXBuildFile; fileRef = F64399000420118A01CA2DCC /* cert.c */; }; /* End PBXBuildFile section */ @@ -177,13 +179,15 @@ 5232A821150AD71A00E6BB48 /* tsaSupportPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaSupportPriv.h; sourceTree = ""; }; 52B609D314F4665700134209 /* tsaTemplates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaTemplates.c; sourceTree = ""; }; 52B609D414F4665700134209 /* tsaTemplates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tsaTemplates.h; sourceTree = ""; }; - 52D7A24915092A0600CF48F7 /* tsaSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tsaSupport.c; sourceTree = ""; }; + 52D7A24915092A0600CF48F7 /* tsaSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = tsaSupport.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; 52D7A24C15092AAD00CF48F7 /* tsaSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tsaSupport.h; sourceTree = ""; }; AC62F5F018B4356A00704BBD /* libsecurity_smime_regressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_smime_regressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; ACBEE90B18B403470021712D /* SecCMS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecCMS.c; sourceTree = ""; }; ACBEE90D18B415B60021712D /* SecCMS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCMS.h; sourceTree = ""; }; ACBEE91018B420BC0021712D /* smime-cms-test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "smime-cms-test.c"; sourceTree = ""; }; ACBEE91318B421890021712D /* smime_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = smime_regressions.h; sourceTree = ""; }; + D421AF601CA45E4900A8E512 /* cms-01-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "cms-01-basic.c"; sourceTree = ""; }; + D421AF611CA45E4900A8E512 /* cms-01-basic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cms-01-basic.h"; sourceTree = ""; }; F64398FF0420118A01CA2DCC /* cert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cert.h; sourceTree = ""; tabWidth = 8; }; F64399000420118A01CA2DCC /* cert.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cert.c; sourceTree = ""; tabWidth = 8; }; /* End PBXFileReference section */ @@ -315,6 +319,8 @@ ACBEE90F18B41FB80021712D /* regressions */ = { isa = PBXGroup; children = ( + D421AF601CA45E4900A8E512 /* cms-01-basic.c */, + D421AF611CA45E4900A8E512 /* cms-01-basic.h */, ACBEE91018B420BC0021712D /* smime-cms-test.c */, ACBEE91318B421890021712D /* smime_regressions.h */, ); @@ -362,6 +368,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + D421AF651CA45E9700A8E512 /* cms-01-basic.h in Headers */, ACA9CE4A18BC4543005AD855 /* SecCMS.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -411,7 +418,7 @@ 4C2741E803E9FBAF00A80181 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C23B0CD909A298C100B7FCED /* Build configuration list for PBXProject "libsecurity_smime" */; compatibilityVersion = "Xcode 3.2"; @@ -476,6 +483,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D421AF641CA45E8C00A8E512 /* cms-01-basic.c in Sources */, AC62F5F418B4358B00704BBD /* smime-cms-test.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -582,7 +590,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", - "SECTRUST_OSX=0", + "SECTRUST_OSX=1", ); }; name = Debug; @@ -594,7 +602,7 @@ COMBINE_HIDPI_IMAGES = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", - "SECTRUST_OSX=0", + "SECTRUST_OSX=1", ); }; name = Release; @@ -603,6 +611,21 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; @@ -610,6 +633,19 @@ isa = XCBuildConfiguration; baseConfigurationReference = 182BB3A0146F1A68000BF1F3 /* lib.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; }; name = Release; }; diff --git a/OSX/libsecurity_smime/regressions/cms-01-basic.c b/OSX/libsecurity_smime/regressions/cms-01-basic.c new file mode 100644 index 00000000..40f66899 --- /dev/null +++ b/OSX/libsecurity_smime/regressions/cms-01-basic.c @@ -0,0 +1,501 @@ +/* + * 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 "cms-01-basic.h" +#include "smime_regressions.h" + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TMP_KEYCHAIN_PATH "/tmp/cms_01_test.keychain" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +#define kNumberSetupTests 10 +static SecKeychainRef setup_keychain(const uint8_t *p12, size_t p12_len, SecIdentityRef *identity, SecCertificateRef *cert) { + CFDataRef p12Data = NULL; + CFArrayRef imported_items = NULL, oldSearchList = NULL; + CFMutableArrayRef newSearchList = NULL; + SecKeychainRef keychain = NULL; + SecExternalFormat sef = kSecFormatPKCS12; + SecItemImportExportKeyParameters keyParams = { + .passphrase = CFSTR("password") + }; + + /* Create keychain and add to search list (for decryption) */ + unlink(TMP_KEYCHAIN_PATH); + ok_status(SecKeychainCopySearchList(&oldSearchList), + "Copy keychain search list"); + require(oldSearchList, out); + ok(newSearchList = CFArrayCreateMutableCopy(NULL, CFArrayGetCount(oldSearchList)+1, oldSearchList), + "Create new search list"); + ok_status(SecKeychainCreate(TMP_KEYCHAIN_PATH, 8, "password", false, NULL, &keychain), + "Create keychain for identity"); + require(keychain, out); + CFArrayAppendValue(newSearchList, keychain); + ok_status(SecKeychainSetSearchList(newSearchList), + "Set keychain search list"); + + /* Load identity and set as signer */ + ok(p12Data = CFDataCreate(NULL, p12, p12_len), + "Create p12 data"); + ok_status(SecItemImport(p12Data, NULL, &sef, NULL, 0, &keyParams, keychain, &imported_items), + "Import identity"); + is(CFArrayGetCount(imported_items),1,"Imported 1 items"); + is(CFGetTypeID(CFArrayGetValueAtIndex(imported_items, 0)), SecIdentityGetTypeID(), + "Got back an identity"); + ok(*identity = (SecIdentityRef) CFRetainSafe(CFArrayGetValueAtIndex(imported_items, 0)), + "Retrieve identity"); + ok_status(SecIdentityCopyCertificate(*identity, cert), + "Copy certificate"); + + CFReleaseNull(p12Data); + CFReleaseNull(imported_items); + +out: + return keychain; +} + +#define kNumberCleanupTests 1 +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); +} + +static OSStatus sign_please(SecIdentityRef identity, SECOidTag digestAlgTag, bool withAttrs, uint8_t *expected_output, size_t expected_len) { + + OSStatus status = SECFailure; + + SecCmsMessageRef cmsg = NULL; + SecCmsSignedDataRef sigd = NULL; + SecCmsContentInfoRef cinfo = NULL; + SecCmsSignerInfoRef signerInfo = NULL; + SecCmsEncoderRef encoder = NULL; + SecArenaPoolRef arena = NULL; + CSSM_DATA cms_data = { + .Data = NULL, + .Length = 0 + }; + uint8_t string_to_sign[] = "This message is signed. Ain't it pretty?"; + + /* setup the message */ + require_action_string(cmsg = SecCmsMessageCreate(NULL), out, + status = errSecAllocate, "Failed to create message"); + require_action_string(sigd = SecCmsSignedDataCreate(cmsg), out, + status = errSecAllocate, "Failed to create signed data"); + require_action_string(cinfo = SecCmsMessageGetContentInfo(cmsg), out, + status = errSecParam, "Failed to get cms content info"); + require_noerr_string(status = SecCmsContentInfoSetContentSignedData(cmsg, cinfo, sigd), out, + "Failed to set signed data into content info"); + require_action_string(cinfo = SecCmsSignedDataGetContentInfo(sigd), out, + status = errSecParam, "Failed to get content info from signed data"); + require_noerr_string(status = SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, false), out, + "Failed to set signed data content info"); + require_action_string(signerInfo = SecCmsSignerInfoCreate(cmsg, identity, digestAlgTag), out, + status = errSecAllocate, "Failed to create signer info"); + require_noerr_string(status = SecCmsSignerInfoIncludeCerts(signerInfo, SecCmsCMCertOnly, + certUsageEmailSigner), out, + "Failed to put certs in signer info"); + + if(withAttrs) { + require_noerr_string(status = SecCmsSignerInfoAddSigningTime(signerInfo, 480000000.0), out, + "Couldn't add an attribute"); + } + require_noerr_string(status = SecCmsSignedDataAddSignerInfo(sigd, signerInfo), out, + "Couldn't add signer info to signed data"); + + /* encode now */ + require_noerr_string(status = SecArenaPoolCreate(1024, &arena), out, + "Failed to create arena"); + require_noerr_string(status = SecCmsEncoderCreate(cmsg, NULL, NULL, &cms_data, arena, NULL, NULL, + NULL, NULL, NULL, NULL, &encoder), out, + "Failed to create encoder"); + require_noerr_string(status = SecCmsEncoderUpdate(encoder, string_to_sign, sizeof(string_to_sign)), out, + "Failed to add data "); + status = SecCmsEncoderFinish(encoder); + encoder = NULL; // SecCmsEncoderFinish always frees the encoder but doesn't NULL it. + require_noerr_quiet(status, out); + + /* verify the output matches expected results */ + if (expected_output) { + require_action_string(expected_len == cms_data.Length, out, + status = -1, "Output size differs from expected"); + require_noerr_action_string(memcmp(expected_output, cms_data.Data, expected_len), out, + status = -1, "Output differs from expected"); + } + +out: + if (encoder) { + SecCmsEncoderDestroy(encoder); + } + if (arena) { + SecArenaPoolFree(arena, false); + } + if (cmsg) { + SecCmsMessageDestroy(cmsg); + } + return status; + +} + +static OSStatus verify_please(SecKeychainRef keychain, uint8_t *data_to_verify, size_t length) { + OSStatus status = SECFailure; + SecCmsDecoderRef decoder = NULL; + SecCmsMessageRef cmsg = NULL; + SecCmsContentInfoRef cinfo = NULL; + SecCmsSignedDataRef sigd = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + + if (!data_to_verify) { + return errSecSuccess; // reasons... + } + + require_noerr_string(status = SecCmsDecoderCreate(NULL, NULL, NULL, NULL, NULL, + NULL, NULL, &decoder), out, + "Failed to create decoder"); + require_noerr_string(status = SecCmsDecoderUpdate(decoder, data_to_verify, length), out, + "Failed to add data "); + status = SecCmsDecoderFinish(decoder, &cmsg); + decoder = NULL; // SecCmsDecoderFinish always frees the decoder + require_noerr_quiet(status, out); + + require_action_string(cinfo = SecCmsMessageContentLevel(cmsg, 0), out, + status = errSecDecode, "Failed to get content info"); + require_action_string(SEC_OID_PKCS7_SIGNED_DATA == SecCmsContentInfoGetContentTypeTag(cinfo), out, + status = errSecDecode, "Content type was pkcs7 signed data"); + require_action_string(sigd = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(cinfo), out, + status = errSecDecode, "Failed to get signed data"); + require_action_string(policy = SecPolicyCreateBasicX509(), out, + status = errSecAllocate, "Failed to create basic policy"); + status = SecCmsSignedDataVerifySignerInfo(sigd, 0, keychain, policy, &trust); + +out: + if (decoder) { + SecCmsDecoderDestroy(decoder); + } + if (cmsg) { + SecCmsMessageDestroy(cmsg); + } + CFReleaseNull(policy); + CFReleaseNull(trust); + return status; +} + +static uint8_t *invalidate_signature(uint8_t *cms_data, size_t length) { + if (!cms_data || !length || (length < 10)) { + return NULL; + } + uint8_t *invalid_cms = NULL; + + invalid_cms = malloc(length); + if (invalid_cms) { + memcpy(invalid_cms, cms_data, length); + /* This modifies the signature part of the test cms binaries */ + invalid_cms[length - 10] = 0x00; + } + + return invalid_cms; +} + +static OSStatus invalidate_and_verify(SecKeychainRef kc, uint8_t *cms_data, size_t length) { + OSStatus status = SECFailure; + uint8_t *invalid_cms_data = NULL; + + if (!cms_data) { + return SECFailure; // reasons... + } + + require_action_string(invalid_cms_data = invalidate_signature(cms_data, length), out, + status = errSecAllocate, "Unable to allocate buffer for invalid cms data"); + status = verify_please(kc, invalid_cms_data, length); + +out: + if (invalid_cms_data) { + free(invalid_cms_data); + } + return status; +} + +/* forward declaration */ +static OSStatus decrypt_please(uint8_t *data_to_decrypt, size_t length); + +static OSStatus encrypt_please(SecCertificateRef recipient, SECOidTag encAlg, int keysize) { + OSStatus status = SECFailure; + SecCmsMessageRef cmsg = NULL; + SecCmsEnvelopedDataRef envd = NULL; + SecCmsContentInfoRef cinfo = NULL; + SecCmsRecipientInfoRef rinfo = NULL; + SecArenaPoolRef arena = NULL; + SecCmsEncoderRef encoder = NULL; + CSSM_DATA cms_data = { + .Data = NULL, + .Length = 0 + }; + const uint8_t data_to_encrypt[] = "This data is encrypted. Is cool, no?"; + + /* set up the message */ + require_action_string(cmsg = SecCmsMessageCreate(NULL), out, + status = errSecAllocate, "Failed to create message"); + require_action_string(envd = SecCmsEnvelopedDataCreate(cmsg, encAlg, keysize), out, + status = errSecAllocate, "Failed to create enveloped data"); + require_action_string(cinfo = SecCmsMessageGetContentInfo(cmsg), out, + status = errSecParam, "Failed to get content info from cms message"); + require_noerr_string(status = SecCmsContentInfoSetContentEnvelopedData(cmsg, cinfo, envd), out, + "Failed to set enveloped data in cms message"); + require_action_string(cinfo = SecCmsEnvelopedDataGetContentInfo(envd), out, + status = errSecParam, "Failed to get content info from enveloped data"); + require_noerr_string(status = SecCmsContentInfoSetContentData(cmsg, cinfo, NULL, false), out, + "Failed to set data type in envelope"); + require_action_string(rinfo = SecCmsRecipientInfoCreate(cmsg, recipient), out, + status = errSecAllocate, "Failed to create recipient info"); + require_noerr_string(status = SecCmsEnvelopedDataAddRecipient(envd, rinfo), out, + "Failed to add recipient info to envelope"); + + /* encode the message */ + require_noerr_string(status = SecArenaPoolCreate(1024, &arena), out, + "Failed to create arena"); + require_noerr_string(status = SecCmsEncoderCreate(cmsg, NULL, NULL, &cms_data, arena, NULL, NULL, + NULL, NULL, NULL, NULL, &encoder), out, + "Failed to create encoder"); + require_noerr_string(status = SecCmsEncoderUpdate(encoder, data_to_encrypt, sizeof(data_to_encrypt)), out, + "Failed to update encoder with data"); + status = SecCmsEncoderFinish(encoder); + encoder = NULL; // SecCmsEncoderFinish always frees the encoder but doesn't NULL it. + require_noerr_quiet(status, out); + + require_noerr_string(status = decrypt_please(cms_data.Data, cms_data.Length), out, + "Failed to decrypt the data we just encrypted"); + +out: + if (encoder) { + SecCmsEncoderDestroy(encoder); + } + if (arena) { + SecArenaPoolFree(arena, false); + } + if (cmsg) { + SecCmsMessageDestroy(cmsg); + } + return status; +} + +static OSStatus decrypt_please(uint8_t *data_to_decrypt, size_t length) { + OSStatus status = SECFailure; + SecCmsDecoderRef decoder = NULL; + SecCmsMessageRef cmsg = NULL; + CSSM_DATA_PTR content = NULL; + const uint8_t encrypted_string[] = "This data is encrypted. Is cool, no?"; + + require_noerr_string(status = SecCmsDecoderCreate(NULL, NULL, NULL, NULL, NULL, + NULL, NULL, &decoder), out, + "Failed to create decoder"); + require_noerr_string(status = SecCmsDecoderUpdate(decoder, data_to_decrypt, length), out, + "Failed to add data "); + status = SecCmsDecoderFinish(decoder, &cmsg); + decoder = NULL; // SecCmsDecoderFinish always frees the decoder + require_noerr_quiet(status, out); + require_action_string(content = SecCmsMessageGetContent(cmsg), out, + status = errSecDecode, "Unable to get message contents"); + + /* verify the output matches expected results */ + require_action_string(sizeof(encrypted_string) == content->Length, out, + status = -1, "Output size differs from expected"); + require_noerr_action_string(memcmp(encrypted_string, content->Data, content->Length), out, + status = -1, "Output differs from expected"); + +out: + if (cmsg) { + SecCmsMessageDestroy(cmsg); + } + return status; +} + +/* Signing with attributes goes through a different code path than signing without, + * so we need to test both. */ +#define kNumberSignTests 10 +static void sign_tests(SecIdentityRef identity, bool isRSA) { + + /* no attributes */ + is(sign_please(identity, SEC_OID_MD5, false, NULL, 0), + SEC_ERROR_INVALID_ALGORITHM, "Signed with MD5. Not cool."); + 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, + (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"); + is(sign_please(identity, SEC_OID_SHA512, false, NULL, 0), errSecSuccess, "Signed with SHA-512"); + + /* with attributes */ + is(sign_please(identity, SEC_OID_MD5, true, NULL, 0), + SEC_ERROR_INVALID_ALGORITHM, "Signed with MD5 and attributes. Not cool."); + is(sign_please(identity, SEC_OID_SHA1, true, (isRSA) ? rsa_sha1_attr : NULL, + (isRSA) ? sizeof(rsa_sha1_attr) : 0), + errSecSuccess, "Signed with SHA-1 and attributes"); + is(sign_please(identity, SEC_OID_SHA256, true, (isRSA) ? rsa_sha256_attr : NULL, + (isRSA) ? sizeof(rsa_sha256_attr) : 0), + errSecSuccess, "Signed with SHA-256 and attributes"); + is(sign_please(identity, SEC_OID_SHA384, true, NULL, 0), + errSecSuccess, "Signed with SHA-384 and attributes"); + is(sign_please(identity, SEC_OID_SHA512, true, NULL, 0), + errSecSuccess, "Signed with SHA-512 and attributes"); +} + +/* Verifying with attributes goes through a different code path than verifying without, + * so we need to test both. */ +#define kNumberVerifyTests 12 +static void verify_tests(SecKeychainRef kc, bool isRsa) { + /* no attributes */ + is(verify_please(kc, (isRsa) ? rsa_md5 : ec_md5, + (isRsa) ? sizeof(rsa_md5) : sizeof(ec_md5)), + (isRsa) ? errSecSuccess : SECFailure, + "Verify MD5, no attributes"); + is(verify_please(kc, (isRsa) ? rsa_sha1 : ec_sha1, + (isRsa) ? sizeof(rsa_sha1) : sizeof(ec_sha1)), + errSecSuccess, "Verify SHA1, no attributes"); + is(verify_please(kc, (isRsa) ? rsa_sha256 : ec_sha256, + (isRsa) ? sizeof(rsa_sha256) : sizeof(ec_sha256)), + errSecSuccess, "Verify SHA256, no attributes"); + + /* with attributes */ + is(verify_please(kc, (isRsa) ? rsa_md5_attr : NULL, + (isRsa) ? sizeof(rsa_md5_attr) : 0), + errSecSuccess, "Verify MD5, with attributes"); + is(verify_please(kc, (isRsa) ? rsa_sha1_attr : ec_sha1_attr, + (isRsa) ? sizeof(rsa_sha1_attr) : sizeof(ec_sha1_attr)), + errSecSuccess, "Verify SHA1, with attributes"); + is(verify_please(kc, (isRsa) ? rsa_sha256_attr : ec_sha256_attr, + (isRsa) ? sizeof(rsa_sha256_attr) : sizeof(ec_sha256_attr)), + errSecSuccess, "Verify SHA256, with attributes"); + + /***** Once more, with validation errors *****/ + + /* no attributes */ + is(invalidate_and_verify(kc, (isRsa) ? rsa_md5 : ec_md5, + (isRsa) ? sizeof(rsa_md5) : sizeof(ec_md5)), + SECFailure, "Verify invalid MD5, no attributes"); + is(invalidate_and_verify(kc, (isRsa) ? rsa_sha1 : ec_sha1, + (isRsa) ? sizeof(rsa_sha1) : sizeof(ec_sha1)), + SECFailure, "Verify invalid SHA1, no attributes"); + is(invalidate_and_verify(kc, (isRsa) ? rsa_sha256 : ec_sha256, + (isRsa) ? sizeof(rsa_sha256) : sizeof(ec_sha256)), + SECFailure, "Verify invalid SHA256, no attributes"); + + /* with attributes */ + is(invalidate_and_verify(kc, (isRsa) ? rsa_md5_attr : NULL, + (isRsa) ? sizeof(rsa_md5_attr) : 0), + SECFailure, "Verify invalid MD5, with attributes"); + is(invalidate_and_verify(kc, (isRsa) ? rsa_sha1_attr : ec_sha1_attr, + (isRsa) ? sizeof(rsa_sha1_attr) : sizeof(ec_sha1_attr)), + SECFailure, "Verify invalid SHA1, with attributes"); + is(invalidate_and_verify(kc, (isRsa) ? rsa_sha256_attr : ec_sha256_attr, + (isRsa) ? sizeof(rsa_sha256_attr) : sizeof(ec_sha256_attr)), + SECFailure, "Verify invalid SHA256, with attributes"); +} + +#define kNumberEncryptTests 5 +static void encrypt_tests(SecCertificateRef certificate) { + is(encrypt_please(certificate, SEC_OID_DES_EDE3_CBC, 192), + errSecSuccess, "Encrypt with 3DES"); + is(encrypt_please(certificate, SEC_OID_RC2_CBC, 128), + errSecSuccess, "Encrypt with 128-bit RC2"); + is(encrypt_please(certificate, SEC_OID_AES_128_CBC, 128), + errSecSuccess, "Encrypt with 128-bit AES"); + is(encrypt_please(certificate, SEC_OID_AES_192_CBC, 192), + errSecSuccess, "Encrypt with 192-bit AES"); + is(encrypt_please(certificate, SEC_OID_AES_256_CBC, 256), + errSecSuccess, "Encrypt with 256-bit AES"); +} + +#define kNumberDecryptTests 5 +static void decrypt_tests(bool isRsa) { + is(decrypt_please((isRsa) ? rsa_3DES : ec_3DES, + (isRsa) ? sizeof(rsa_3DES) : sizeof(ec_3DES)), + errSecSuccess, "Decrypt 3DES"); + is(decrypt_please((isRsa) ? rsa_RC2 : ec_RC2, + (isRsa) ? sizeof(rsa_RC2) : sizeof(ec_RC2)), + errSecSuccess, "Decrypt 128-bit RC2"); + is(decrypt_please((isRsa) ? rsa_AES_128 : ec_AES_128, + (isRsa) ? sizeof(rsa_AES_128) : sizeof(ec_AES_128)), + errSecSuccess, "Decrypt 128-bit AES"); + is(decrypt_please((isRsa) ? rsa_AES_192 : ec_AES_192, + (isRsa) ? sizeof(rsa_AES_192) : sizeof(ec_AES_192)), + errSecSuccess, "Decrypt 192-bit AES"); + is(decrypt_please((isRsa) ? rsa_AES_256 : ec_AES_256, + (isRsa) ? sizeof(rsa_AES_256) : sizeof(ec_AES_256)), + errSecSuccess, "Decrypt 256-bit AES"); +} + +int cms_01_basic(int argc, char *const *argv) +{ + plan_tests(2*(kNumberSetupTests + kNumberSignTests + kNumberVerifyTests + + kNumberEncryptTests + kNumberDecryptTests + kNumberCleanupTests)); + + SecKeychainRef kc = NULL; + SecIdentityRef identity = NULL; + SecCertificateRef certificate = NULL; + + /* RSA tests */ + kc = setup_keychain(_rsa_identity, sizeof(_rsa_identity), &identity, &certificate); + sign_tests(identity, true); + verify_tests(kc, true); + encrypt_tests(certificate); + decrypt_tests(true); + cleanup_keychain(kc, identity, certificate); + + /* EC tests */ + kc = setup_keychain(_ec_identity, sizeof(_ec_identity), &identity, &certificate); + sign_tests(identity, false); + verify_tests(kc, false); + encrypt_tests(certificate); + decrypt_tests(false); + cleanup_keychain(kc, identity, certificate); + + return 0; +} \ No newline at end of file diff --git a/OSX/libsecurity_smime/regressions/cms-01-basic.h b/OSX/libsecurity_smime/regressions/cms-01-basic.h new file mode 100644 index 00000000..dc46feeb --- /dev/null +++ b/OSX/libsecurity_smime/regressions/cms-01-basic.h @@ -0,0 +1,1341 @@ +/* + * 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@ + */ + + +#ifndef cms_01_test_h +#define cms_01_test_h + +/* + * MARK: Identities + */ +unsigned char _rsa_identity[] = { + 0x30, 0x82, 0x0a, 0x83, 0x02, 0x01, 0x03, 0x30, 0x82, 0x0a, 0x4a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x82, 0x0a, 0x3b, 0x04, 0x82, 0x0a, 0x37, 0x30, 0x82, 0x0a, 0x33, 0x30, 0x82, 0x04, 0xbf, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x04, 0xb0, 0x30, 0x82, 0x04, 0xac, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x04, 0xa5, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0xef, 0x13, 0x69, 0xa2, 0xe0, 0xb7, 0x4d, + 0xf3, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x04, 0x78, 0x24, 0x38, 0x74, 0x0e, 0x93, 0x67, 0x0b, 0xc4, 0x24, 0x58, 0x1c, + 0x1c, 0x63, 0x3a, 0xcb, 0xfb, 0x88, 0x8b, 0x95, 0xe8, 0x8b, 0x40, 0x33, 0xa1, 0x10, 0x72, 0xd6, 0x3b, 0x36, 0x52, 0xef, + 0xe8, 0xec, 0x27, 0xf1, 0xe2, 0xb6, 0x3d, 0x7a, 0x67, 0x28, 0x59, 0xf2, 0xa9, 0x9f, 0xf2, 0x33, 0x21, 0x26, 0xe6, 0x2f, + 0xbc, 0xeb, 0x39, 0xa2, 0x8a, 0x8d, 0xa0, 0xd8, 0x6e, 0xfc, 0xf9, 0x80, 0x63, 0x02, 0x68, 0x6c, 0x97, 0x43, 0x56, 0x8b, + 0xab, 0x1e, 0xac, 0xea, 0x6d, 0x9a, 0xdd, 0xdf, 0x67, 0x4d, 0xfb, 0xf0, 0x0b, 0x58, 0x9e, 0xc0, 0x2b, 0x06, 0x8b, 0xca, + 0x01, 0xcd, 0xcc, 0x79, 0xb6, 0xb1, 0xa1, 0x22, 0x00, 0x22, 0x46, 0x9f, 0x20, 0x7d, 0xd4, 0x3e, 0x1a, 0x16, 0x73, 0xfa, + 0x61, 0xaa, 0xaa, 0xc9, 0x9e, 0xc1, 0x66, 0x17, 0x74, 0xc8, 0x96, 0xc8, 0xab, 0x0d, 0xb3, 0x41, 0x11, 0xe6, 0x1b, 0x3d, + 0x1f, 0xad, 0x02, 0x0d, 0x7d, 0x68, 0xbc, 0x80, 0xeb, 0xaf, 0x1e, 0x77, 0x9e, 0xc8, 0x8c, 0xc2, 0xce, 0x15, 0x4a, 0xba, + 0xa3, 0xba, 0x11, 0x82, 0xcc, 0xc4, 0x8e, 0x47, 0xa4, 0x2d, 0x95, 0x00, 0x46, 0xcb, 0x45, 0x19, 0x8d, 0x8f, 0xa7, 0x47, + 0x4b, 0xb6, 0xd6, 0x0f, 0x33, 0x5a, 0xf6, 0xba, 0x2d, 0x6a, 0xde, 0x19, 0x22, 0x4e, 0x48, 0xf4, 0x98, 0x54, 0x6e, 0xed, + 0xd6, 0xf4, 0xd8, 0xaf, 0x63, 0x83, 0x72, 0x01, 0x43, 0x0d, 0x33, 0x06, 0x30, 0x15, 0x3f, 0x0b, 0xc8, 0x4f, 0x8f, 0x8f, + 0x04, 0x6c, 0x1c, 0x92, 0xf3, 0xb3, 0x4e, 0xb0, 0xaa, 0x19, 0x27, 0x84, 0xfc, 0xb5, 0xde, 0xed, 0xb0, 0xea, 0x42, 0xc0, + 0xb0, 0x25, 0xfc, 0x25, 0x59, 0xf5, 0x8a, 0xfc, 0x35, 0x8c, 0xe3, 0x47, 0xab, 0x9f, 0xd7, 0x52, 0xac, 0x57, 0x5d, 0x0f, + 0xc8, 0x28, 0x19, 0xf7, 0x11, 0xe5, 0x34, 0xfb, 0x80, 0x32, 0xa1, 0x63, 0xa8, 0x79, 0xcf, 0xc2, 0xbd, 0xe3, 0x9e, 0x7e, + 0xf1, 0x62, 0xa4, 0x38, 0x3a, 0x6a, 0xf2, 0xd5, 0xdb, 0xe2, 0x01, 0x4e, 0x58, 0x1c, 0xb1, 0x8c, 0xf4, 0x71, 0x9c, 0x1b, + 0xdf, 0x32, 0xa8, 0xab, 0xa0, 0xd9, 0xe3, 0x10, 0x9e, 0xe8, 0x70, 0x7f, 0x1d, 0x8d, 0x2b, 0xe4, 0x70, 0x21, 0x01, 0x88, + 0x26, 0x1a, 0x53, 0xcd, 0x62, 0xf2, 0x18, 0xa1, 0xe5, 0xfa, 0xbb, 0x59, 0x77, 0x46, 0xac, 0xda, 0xbe, 0x38, 0xe9, 0x69, + 0x48, 0x24, 0x86, 0x82, 0x8a, 0x21, 0xce, 0xbc, 0xe1, 0xef, 0xfc, 0x35, 0xd2, 0x17, 0x8e, 0x34, 0xf2, 0x52, 0x8a, 0x74, + 0x5d, 0x0e, 0xff, 0xf4, 0x79, 0x7b, 0x97, 0x43, 0xc2, 0xc7, 0x50, 0x70, 0x14, 0x9d, 0xc2, 0xb4, 0x42, 0xb2, 0xc2, 0xdb, + 0x5c, 0x99, 0xf1, 0x6f, 0xe2, 0x4f, 0xc0, 0xd3, 0xc3, 0x4a, 0xe0, 0xdf, 0xfc, 0x0a, 0xd3, 0xfb, 0x4d, 0x5f, 0x5f, 0xbe, + 0x68, 0x88, 0x36, 0xd8, 0x29, 0x83, 0xa6, 0x44, 0xb7, 0x13, 0x60, 0x3e, 0xb2, 0xc0, 0xce, 0xb9, 0x0a, 0xb3, 0xd3, 0xd7, + 0x6b, 0xa0, 0xae, 0x2c, 0x54, 0x96, 0xa6, 0x57, 0x54, 0x52, 0xe2, 0xe5, 0xd9, 0x11, 0xff, 0x94, 0xd7, 0x06, 0x87, 0x67, + 0x80, 0xb5, 0x44, 0xea, 0x9b, 0xfd, 0x77, 0x28, 0x57, 0x72, 0xd3, 0x6d, 0x8b, 0x0a, 0xbc, 0x94, 0xa6, 0xd6, 0x23, 0xfa, + 0xf3, 0x58, 0x18, 0x28, 0x6d, 0x81, 0x56, 0x05, 0x0a, 0x9c, 0x34, 0xf7, 0xb1, 0x64, 0xa4, 0xe1, 0x0b, 0x50, 0x39, 0x4b, + 0xfb, 0x51, 0xa1, 0x29, 0x19, 0x61, 0x6c, 0x72, 0xc9, 0xf6, 0xd3, 0xa0, 0x98, 0x66, 0x4b, 0x14, 0xd5, 0x26, 0x41, 0xd1, + 0x03, 0x47, 0x02, 0xde, 0x9c, 0x5f, 0x72, 0x9c, 0xbb, 0x68, 0x47, 0x23, 0xfb, 0xd7, 0xfc, 0x85, 0xa7, 0x01, 0xd8, 0x48, + 0x94, 0xc3, 0xf1, 0x67, 0xd9, 0xa0, 0xce, 0x1b, 0x66, 0x80, 0x70, 0x52, 0x99, 0x9c, 0x82, 0x27, 0xec, 0x65, 0x0a, 0x72, + 0x3e, 0xf8, 0xd1, 0x70, 0xd3, 0xce, 0x3d, 0x52, 0x1f, 0xbb, 0x18, 0x1f, 0x10, 0x49, 0x4c, 0x42, 0x67, 0x0c, 0xa3, 0xaa, + 0x58, 0xdb, 0x56, 0xcf, 0x39, 0x68, 0x43, 0x8e, 0xc9, 0x8d, 0xaa, 0xeb, 0x94, 0x4a, 0x1f, 0x96, 0x98, 0xa2, 0xd1, 0xcf, + 0x1f, 0xc5, 0xe0, 0xcf, 0x5f, 0x29, 0xf6, 0xe5, 0x80, 0x89, 0xb9, 0xb1, 0x4c, 0x2e, 0x6e, 0xbb, 0xeb, 0x43, 0xdf, 0xff, + 0x24, 0x42, 0xc9, 0x08, 0x98, 0x42, 0x55, 0xcb, 0x4c, 0x9e, 0xae, 0x02, 0x57, 0x81, 0x10, 0xb4, 0x2b, 0xc4, 0xfc, 0xd8, + 0xd2, 0x6c, 0x5c, 0x47, 0xe9, 0xc3, 0x49, 0x8b, 0x1f, 0x8e, 0xbe, 0x78, 0x08, 0x06, 0xe2, 0xab, 0xa7, 0x5c, 0x22, 0xa1, + 0x5a, 0xb2, 0x38, 0x8a, 0xc4, 0xd7, 0x73, 0x28, 0xe2, 0x87, 0x80, 0xac, 0x1c, 0x73, 0xdf, 0x06, 0xa0, 0xfe, 0x59, 0x30, + 0xd4, 0x9f, 0x58, 0x93, 0xc1, 0xbd, 0x54, 0xdb, 0xbc, 0xb1, 0x19, 0x6a, 0x57, 0x25, 0x73, 0xab, 0xd0, 0xcf, 0x26, 0x9c, + 0x1c, 0x6b, 0xe6, 0x89, 0x16, 0x9b, 0x34, 0x63, 0xfe, 0x95, 0x47, 0x5e, 0x3b, 0x78, 0x29, 0xda, 0x1f, 0x6f, 0xb0, 0x7a, + 0x5c, 0x07, 0xa8, 0x8f, 0x83, 0xc6, 0x69, 0x18, 0x12, 0x39, 0x7a, 0xb3, 0x61, 0xe4, 0x86, 0x76, 0xbf, 0xe1, 0x99, 0xc7, + 0xc7, 0x4c, 0x9f, 0x95, 0xc5, 0xe7, 0x88, 0x97, 0xcf, 0xd7, 0xf5, 0x20, 0xbf, 0x97, 0x6c, 0xec, 0x04, 0xb5, 0x3d, 0x07, + 0xc8, 0x0e, 0xe9, 0x51, 0xe2, 0x93, 0x35, 0x57, 0xdf, 0xe9, 0xfd, 0x5f, 0x83, 0x95, 0x75, 0xb1, 0xa5, 0xbe, 0xdc, 0xc1, + 0xa0, 0x60, 0x93, 0x38, 0xae, 0xa6, 0x20, 0xf0, 0xb5, 0x32, 0x58, 0xb2, 0x04, 0x59, 0x24, 0x5f, 0x5b, 0xd7, 0x4b, 0x45, + 0x9b, 0x37, 0x39, 0x95, 0xd9, 0x85, 0x2a, 0xdc, 0xe9, 0xd8, 0x09, 0xc4, 0x99, 0x41, 0x28, 0xb1, 0x97, 0x48, 0x62, 0xd0, + 0xc5, 0xb2, 0x75, 0x64, 0x47, 0x02, 0xec, 0x72, 0x40, 0xd1, 0x2c, 0x07, 0x0e, 0x91, 0x3e, 0x70, 0x17, 0x75, 0xb0, 0x9f, + 0x81, 0xcd, 0x1a, 0x03, 0xb6, 0x64, 0xd0, 0xe2, 0x62, 0x3a, 0x92, 0x7c, 0xc1, 0x0d, 0x4a, 0xfa, 0x55, 0xf8, 0xa2, 0xb7, + 0xf7, 0xa5, 0xaf, 0xb6, 0xd6, 0xce, 0xe9, 0x9f, 0x06, 0x15, 0x41, 0x4e, 0x50, 0x43, 0x98, 0x4c, 0xe3, 0x20, 0x83, 0x37, + 0xaf, 0x93, 0x6a, 0xe6, 0xc0, 0x4b, 0x93, 0x06, 0x0c, 0x2f, 0xc7, 0x10, 0x4d, 0x2e, 0x55, 0x3f, 0xd8, 0xdf, 0xab, 0x74, + 0x4e, 0xcc, 0x09, 0x42, 0xa3, 0x18, 0x7a, 0x55, 0x84, 0xa7, 0xba, 0x74, 0xe5, 0x29, 0xcb, 0x37, 0x19, 0xe3, 0xd8, 0x02, + 0xcc, 0xf4, 0x18, 0x3e, 0x58, 0x52, 0x41, 0xde, 0xba, 0x12, 0x5c, 0x89, 0xb4, 0x28, 0x04, 0x33, 0x8d, 0xe5, 0x1a, 0x30, + 0x97, 0x05, 0x3f, 0x19, 0xaf, 0xef, 0x07, 0x3a, 0xe2, 0xa5, 0x71, 0xfb, 0xb5, 0x87, 0x00, 0x3d, 0x53, 0x6b, 0x4c, 0x3d, + 0x4d, 0xc8, 0x4c, 0x94, 0xd5, 0xa5, 0x14, 0x29, 0x53, 0x80, 0x99, 0x70, 0xcf, 0x11, 0x8b, 0xb0, 0x19, 0x38, 0x0d, 0x04, + 0x4f, 0x47, 0xc7, 0x4c, 0x20, 0x8f, 0x06, 0xf0, 0x49, 0xc2, 0x4a, 0xc8, 0xe6, 0x95, 0x27, 0x6c, 0xd4, 0xbb, 0x2e, 0x8c, + 0x1b, 0xd6, 0x83, 0xa6, 0x26, 0x1d, 0x69, 0x8a, 0xf5, 0x7d, 0x34, 0x4c, 0xeb, 0xf4, 0x66, 0x70, 0x4d, 0x41, 0xa5, 0xce, + 0x1e, 0xbc, 0xa0, 0xc5, 0xed, 0x48, 0x1a, 0xcb, 0xf7, 0xae, 0x66, 0x5d, 0x12, 0x83, 0xa2, 0xf3, 0x4b, 0x8b, 0xa6, 0x88, + 0x90, 0x4f, 0x70, 0x3b, 0xbd, 0x9a, 0x8a, 0x82, 0x33, 0x40, 0x32, 0x15, 0x0b, 0x3b, 0x3d, 0xac, 0x83, 0xd9, 0xde, 0x0a, + 0x94, 0x13, 0x53, 0x17, 0xba, 0xdb, 0x73, 0x4f, 0xf2, 0xec, 0x56, 0xce, 0x32, 0xd6, 0x9a, 0xf7, 0xda, 0x35, 0x00, 0x46, + 0x0f, 0x74, 0xa5, 0x71, 0x4b, 0x4f, 0x0d, 0x8a, 0xa2, 0xd3, 0xbb, 0x2c, 0xb5, 0xe9, 0x75, 0x08, 0x94, 0xfc, 0xcb, 0xdf, + 0x05, 0x48, 0x32, 0x56, 0x57, 0x39, 0xfb, 0xfa, 0xe5, 0xbd, 0x85, 0x3f, 0xb2, 0xd4, 0x9e, 0xf3, 0xd6, 0x71, 0xf3, 0x33, + 0x60, 0x46, 0x32, 0xbc, 0x52, 0x6d, 0xfd, 0x9e, 0x71, 0xdb, 0x6d, 0x27, 0xe4, 0xc3, 0x9e, 0x99, 0x07, 0x3c, 0x49, 0x91, + 0xce, 0x01, 0x7f, 0x47, 0x26, 0x35, 0xd0, 0x21, 0x3c, 0x97, 0x81, 0x1e, 0x22, 0x4e, 0xb6, 0x79, 0x9c, 0x61, 0x51, 0xaf, + 0x3c, 0x27, 0x03, 0x6b, 0xb1, 0x4c, 0xe0, 0x21, 0x87, 0x4e, 0x03, 0xf1, 0xf5, 0x30, 0x82, 0x05, 0x6c, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x5d, 0x04, 0x82, 0x05, 0x59, 0x30, 0x82, 0x05, 0x55, + 0x30, 0x82, 0x05, 0x51, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, + 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, + 0x0e, 0x04, 0x08, 0xe9, 0xa1, 0x13, 0x54, 0xfb, 0x10, 0xe0, 0x7d, 0x02, 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0x69, + 0x8d, 0x27, 0x9a, 0xd6, 0x8e, 0xa9, 0xe1, 0x3f, 0xd4, 0x8c, 0xb8, 0x48, 0xbb, 0x4e, 0xb6, 0x7f, 0xc6, 0x01, 0x54, 0x23, + 0x72, 0x8b, 0x5f, 0x1d, 0x1a, 0x0c, 0x4a, 0xbd, 0x89, 0x76, 0x00, 0x98, 0x9c, 0xbd, 0xbc, 0x54, 0x16, 0x5f, 0x86, 0xea, + 0x73, 0x74, 0x27, 0x1b, 0x63, 0x69, 0xdb, 0xed, 0xd4, 0x79, 0xd6, 0xef, 0x33, 0x50, 0x4a, 0x36, 0x57, 0x5c, 0xca, 0xa6, + 0x17, 0xc4, 0x12, 0x84, 0x42, 0xf7, 0x1b, 0x7c, 0xd8, 0x5e, 0x6e, 0x7e, 0x86, 0x21, 0x6c, 0xeb, 0xe9, 0xb9, 0xf4, 0x77, + 0xe3, 0xf4, 0x3d, 0x50, 0x09, 0x86, 0x24, 0xca, 0x98, 0x3d, 0x88, 0x28, 0xc6, 0x5a, 0xfe, 0x52, 0x86, 0x14, 0xe1, 0x36, + 0x46, 0x6f, 0xa9, 0x55, 0xf9, 0x8b, 0xfb, 0x49, 0xa1, 0xe5, 0x52, 0xc6, 0x19, 0x25, 0x7e, 0x96, 0x26, 0xaf, 0xf3, 0x84, + 0x44, 0x3b, 0x8a, 0xe5, 0x0a, 0xf6, 0x86, 0xcd, 0x20, 0xf4, 0x4f, 0x78, 0xfc, 0x04, 0x15, 0xf3, 0x47, 0x80, 0x5e, 0x1b, + 0x25, 0x9a, 0x85, 0xf0, 0xc3, 0x1c, 0xd3, 0x45, 0xb5, 0xe2, 0x6c, 0xd8, 0xd0, 0x50, 0x50, 0xa0, 0xc2, 0x55, 0xc1, 0xab, + 0x4b, 0x07, 0xa2, 0xec, 0x00, 0xe7, 0x80, 0xe8, 0xc9, 0x1a, 0xb8, 0xab, 0xe1, 0x0c, 0x9e, 0x3b, 0x7e, 0xf7, 0x64, 0xae, + 0x03, 0x92, 0x40, 0x72, 0x24, 0x94, 0x0c, 0x27, 0xe6, 0x88, 0x44, 0x84, 0x29, 0x8d, 0xe1, 0x18, 0xab, 0xf5, 0xef, 0xaf, + 0xdb, 0x70, 0xf7, 0x81, 0xf6, 0x9f, 0x97, 0x8c, 0xb0, 0x70, 0xf5, 0xb3, 0x8c, 0x0e, 0xda, 0xd0, 0xb0, 0x75, 0x93, 0x39, + 0x9c, 0x5d, 0xe4, 0x42, 0xfa, 0x37, 0x24, 0x3f, 0x57, 0xba, 0x0b, 0xc6, 0x3f, 0x92, 0x5c, 0x93, 0x80, 0x7e, 0xe3, 0x3f, + 0x7a, 0xc8, 0x40, 0x9c, 0xe8, 0xf7, 0x3a, 0x66, 0xe6, 0x75, 0x0e, 0x7d, 0x20, 0x7b, 0xf5, 0xa1, 0x6f, 0x8b, 0x8b, 0xb8, + 0x56, 0xf8, 0x96, 0xb4, 0xab, 0xf9, 0xcc, 0x4f, 0x8a, 0x92, 0x64, 0x1e, 0x90, 0xe0, 0xee, 0x08, 0xc9, 0xf9, 0x71, 0x73, + 0x9b, 0x25, 0x4c, 0x6c, 0xef, 0x61, 0x31, 0x24, 0x98, 0x69, 0x3f, 0xdb, 0x10, 0x24, 0xdc, 0xfd, 0x2a, 0x54, 0xbf, 0xa5, + 0x76, 0xfc, 0xab, 0xe1, 0xf2, 0x72, 0x87, 0x74, 0xb1, 0x9d, 0x98, 0xcf, 0xe8, 0x3c, 0xf4, 0x03, 0x3f, 0x6b, 0x69, 0xa5, + 0x79, 0x4a, 0xb8, 0xbf, 0x5d, 0xb7, 0x89, 0xcc, 0x44, 0xc7, 0x7e, 0x11, 0x8e, 0x46, 0xb2, 0x47, 0x80, 0xbe, 0xc5, 0xfc, + 0x64, 0x35, 0x1d, 0x6b, 0x77, 0xe6, 0x01, 0x51, 0xbc, 0x6e, 0xab, 0xf5, 0x2b, 0x35, 0x65, 0x41, 0x44, 0x54, 0x60, 0x82, + 0xbe, 0x09, 0x53, 0x5e, 0xa0, 0x4f, 0xf7, 0xe6, 0x8b, 0xed, 0x33, 0xd4, 0x8a, 0xf8, 0x61, 0x87, 0x13, 0x2e, 0xdb, 0x4b, + 0x5a, 0x9d, 0xee, 0xd5, 0x2d, 0x58, 0xa7, 0xb4, 0x0b, 0xf4, 0x3b, 0xf8, 0x2f, 0xbf, 0xe7, 0x47, 0xde, 0xc0, 0x33, 0x0c, + 0xab, 0x44, 0xd7, 0x6e, 0x71, 0x49, 0xd4, 0x4f, 0x9b, 0x1b, 0xf2, 0xac, 0xa2, 0x35, 0x77, 0x6e, 0x71, 0xa9, 0xc3, 0xfc, + 0xa3, 0x66, 0x19, 0x58, 0x3d, 0xbc, 0x41, 0xfa, 0x8f, 0x15, 0x36, 0xb4, 0x04, 0x2e, 0x21, 0x7d, 0x6a, 0x25, 0xcd, 0xca, + 0x82, 0x11, 0x05, 0x64, 0x07, 0x94, 0x45, 0xf3, 0x9b, 0xbc, 0x95, 0xa7, 0x3e, 0x0a, 0x78, 0xad, 0x28, 0x62, 0x13, 0xff, + 0x38, 0x10, 0x03, 0x1a, 0x9f, 0xed, 0xc5, 0x78, 0xa2, 0xd3, 0xb0, 0x3c, 0x8f, 0x4f, 0xf6, 0x93, 0x7b, 0xf2, 0xdc, 0xe5, + 0xe3, 0xe2, 0x56, 0x26, 0x74, 0xb1, 0xef, 0x26, 0xc5, 0x66, 0x55, 0xb2, 0x03, 0xba, 0x58, 0x87, 0x4e, 0x7d, 0x32, 0xa5, + 0x78, 0x82, 0x6c, 0x49, 0x5c, 0xc7, 0xee, 0x32, 0x4a, 0x15, 0x82, 0x9e, 0xee, 0xb0, 0xc6, 0xf4, 0xf3, 0x23, 0x84, 0x09, + 0x76, 0xb3, 0xa4, 0x7f, 0xe9, 0x7a, 0xd3, 0x75, 0xc9, 0x18, 0x5e, 0xb1, 0x56, 0x38, 0x25, 0x6e, 0xcd, 0x7d, 0x97, 0x57, + 0xbd, 0x5f, 0xf1, 0x14, 0xbc, 0x37, 0xf1, 0x42, 0x23, 0x1b, 0xaf, 0x67, 0x55, 0x77, 0xff, 0x5f, 0xe2, 0x0a, 0x05, 0x09, + 0x23, 0xfd, 0x75, 0xcd, 0xde, 0x6a, 0x36, 0x06, 0x89, 0x69, 0x3d, 0x3c, 0x80, 0x26, 0x71, 0xce, 0x74, 0xdf, 0xff, 0x42, + 0x1e, 0xcc, 0x49, 0x60, 0x43, 0x98, 0x50, 0x7d, 0x4d, 0xbd, 0x1c, 0x6f, 0x89, 0xe6, 0xba, 0x82, 0x8c, 0x64, 0x57, 0x24, + 0x10, 0x7d, 0xb1, 0x1a, 0x17, 0x48, 0x55, 0xdd, 0x1b, 0xc8, 0xfb, 0xd6, 0x8b, 0xe5, 0x1e, 0x62, 0xdc, 0x7d, 0xfe, 0x5c, + 0x3e, 0x9b, 0xcd, 0x20, 0x6f, 0xa0, 0xae, 0x85, 0x39, 0xcd, 0xf4, 0xae, 0x66, 0x7d, 0x54, 0xe3, 0x16, 0x87, 0x13, 0x28, + 0xd2, 0x8c, 0x67, 0x20, 0xbb, 0x9e, 0x76, 0x3a, 0x3b, 0x89, 0xf2, 0xd2, 0xe3, 0xd0, 0xbe, 0xb8, 0x03, 0xfa, 0x11, 0x88, + 0x5e, 0x47, 0x0b, 0xba, 0xfa, 0x69, 0x73, 0x14, 0x30, 0xb3, 0xcb, 0x77, 0x4f, 0x24, 0x57, 0xcb, 0xd4, 0x1b, 0x62, 0x60, + 0xdf, 0xcb, 0xf8, 0x5d, 0x3c, 0xa4, 0xd9, 0xb5, 0xa4, 0xaa, 0x44, 0x0a, 0x9e, 0x99, 0x03, 0xab, 0xdd, 0xbc, 0xe3, 0x32, + 0xd7, 0x24, 0x19, 0x59, 0x8f, 0x28, 0x55, 0x1b, 0x53, 0x29, 0xb5, 0xbc, 0xbd, 0x8b, 0x20, 0x25, 0xf0, 0x49, 0xee, 0x3f, + 0xaf, 0x74, 0xad, 0x9a, 0x10, 0x2a, 0x04, 0xab, 0x5a, 0x40, 0xf3, 0x2f, 0x37, 0x57, 0xe7, 0xdb, 0x6b, 0x8e, 0x19, 0xab, + 0x29, 0x78, 0x37, 0x04, 0xdb, 0xe5, 0x7b, 0x5a, 0x80, 0x74, 0xae, 0x50, 0xef, 0x25, 0xf3, 0xb5, 0xf2, 0xc8, 0x4b, 0xf6, + 0x67, 0x91, 0xd5, 0x95, 0xe1, 0x96, 0x65, 0xf3, 0xe3, 0x92, 0xb6, 0xd8, 0x6d, 0xf6, 0xf0, 0x2a, 0x6d, 0x5f, 0xfd, 0x16, + 0x11, 0x43, 0x22, 0x7b, 0xa3, 0x5c, 0x05, 0xdc, 0x68, 0x21, 0x50, 0x54, 0xe0, 0x37, 0x41, 0x9e, 0x20, 0x4d, 0x72, 0xfb, + 0xee, 0x91, 0x9d, 0x72, 0xa9, 0xc6, 0x7d, 0x77, 0x30, 0xe2, 0x1e, 0xec, 0xad, 0x1e, 0x5c, 0xe3, 0x0a, 0xb7, 0x32, 0xcf, + 0x90, 0x12, 0x14, 0xcf, 0x19, 0xdf, 0xf8, 0x76, 0x93, 0x27, 0x4a, 0xeb, 0x44, 0x85, 0xc7, 0xfd, 0x60, 0x72, 0xa3, 0x60, + 0x78, 0x4d, 0x0c, 0xec, 0xfa, 0xee, 0x57, 0xf6, 0xe2, 0x0f, 0x2b, 0xcf, 0x83, 0x5d, 0xae, 0xe5, 0x77, 0x59, 0xc9, 0x57, + 0xa9, 0x9e, 0x07, 0x08, 0xf5, 0x06, 0x27, 0x82, 0x92, 0x3e, 0x62, 0xbf, 0xdb, 0xa3, 0x94, 0xc1, 0xee, 0xf6, 0x59, 0xe5, + 0xaf, 0x67, 0x78, 0x51, 0x0d, 0x76, 0xaa, 0x0e, 0x96, 0xf3, 0xe3, 0x22, 0x7a, 0x51, 0x01, 0xcb, 0x11, 0x60, 0x0e, 0x02, + 0x9a, 0x32, 0xcf, 0xb2, 0x75, 0x69, 0x53, 0x89, 0x1c, 0x7a, 0x27, 0x93, 0xd0, 0x80, 0x82, 0xf1, 0x5e, 0x64, 0xe0, 0xc4, + 0xc6, 0x34, 0x59, 0x4d, 0xe2, 0xb7, 0xf0, 0x1c, 0xf6, 0x2a, 0xdb, 0x25, 0xf7, 0x10, 0xe0, 0x25, 0x56, 0x25, 0x74, 0xa2, + 0xbe, 0xec, 0x1e, 0x46, 0xe9, 0x42, 0x0a, 0x5f, 0x46, 0xf3, 0xa8, 0xd6, 0x6e, 0x59, 0x77, 0x11, 0xde, 0x60, 0x17, 0x5d, + 0xce, 0xa5, 0x94, 0x4b, 0x93, 0x6f, 0x01, 0xe6, 0xcb, 0x3f, 0xfb, 0x58, 0x10, 0xea, 0xae, 0xd6, 0x37, 0xa9, 0xd1, 0x12, + 0x98, 0xc7, 0x86, 0xd4, 0xc1, 0x03, 0x33, 0x8d, 0x41, 0xc2, 0x38, 0x2c, 0xc4, 0x4b, 0x22, 0xc5, 0xb6, 0x48, 0x38, 0x29, + 0xe8, 0xe7, 0x5d, 0x22, 0x5f, 0x74, 0x1a, 0xdb, 0x51, 0xda, 0x1d, 0x41, 0xcb, 0x89, 0xc8, 0xd4, 0x44, 0x58, 0x72, 0x3b, + 0x84, 0x39, 0xd3, 0x6f, 0x66, 0x40, 0xbb, 0xe0, 0xe6, 0xfd, 0x6f, 0xcf, 0x6b, 0xcb, 0x9e, 0x02, 0x7d, 0xf2, 0xe0, 0x9e, + 0x65, 0xa9, 0xb7, 0xea, 0x57, 0x8a, 0xbc, 0x99, 0xc0, 0xfc, 0x3e, 0x74, 0xe1, 0x2a, 0x48, 0x96, 0xc0, 0xd3, 0x85, 0x76, + 0xf4, 0x63, 0x3e, 0x2e, 0x24, 0xdd, 0x4c, 0x50, 0x4e, 0x6e, 0x5c, 0x0d, 0x45, 0x6d, 0x55, 0x77, 0x28, 0x37, 0x62, 0x85, + 0x85, 0x9d, 0xf4, 0x2f, 0x09, 0xad, 0x6a, 0xc4, 0x0d, 0xa1, 0x8b, 0x63, 0x49, 0xc9, 0x2f, 0x05, 0x28, 0x80, 0x4c, 0xc3, + 0x30, 0xf3, 0x4f, 0xa8, 0xea, 0xf7, 0xcc, 0xe7, 0xe6, 0x95, 0xb1, 0x35, 0x63, 0x3e, 0xfd, 0xd2, 0x8e, 0xf6, 0x59, 0xaf, + 0x8a, 0xbc, 0x57, 0x89, 0x8b, 0x3d, 0x61, 0x60, 0x59, 0x44, 0xc6, 0xc1, 0x37, 0x34, 0x5c, 0x22, 0x32, 0x9f, 0x82, 0xde, + 0x22, 0x70, 0x9b, 0x94, 0x3c, 0x39, 0x3a, 0xa4, 0x7f, 0xc2, 0x28, 0x21, 0x2b, 0xbe, 0xf2, 0xe2, 0xfa, 0x28, 0xc2, 0xaa, + 0x9f, 0xb8, 0x77, 0x8e, 0x0a, 0x76, 0xf9, 0xe0, 0x9d, 0x62, 0x56, 0x78, 0xf4, 0xa4, 0x1c, 0x8c, 0xd0, 0x34, 0x37, 0x5d, + 0x24, 0x65, 0x91, 0x42, 0xaf, 0x90, 0xda, 0xb8, 0xee, 0x6e, 0x84, 0xd6, 0x47, 0x4f, 0x72, 0xf1, 0xcc, 0x38, 0x3c, 0x5f, + 0x88, 0xf1, 0xef, 0xfb, 0xae, 0xcb, 0xc3, 0xca, 0x1d, 0xd0, 0x0a, 0xf6, 0xc4, 0x7e, 0x7d, 0xc3, 0x2d, 0xf9, 0xb5, 0x51, + 0xe6, 0x18, 0xb4, 0x31, 0x50, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x1c, + 0x1e, 0x1a, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x53, 0x00, 0x20, 0x00, 0x52, 0x00, 0x53, 0x00, 0x41, 0x00, 0x20, 0x00, 0x74, + 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x00, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, + 0x15, 0x31, 0x16, 0x04, 0x14, 0x32, 0xee, 0x79, 0x16, 0x2f, 0x60, 0x4a, 0xad, 0x6c, 0xf7, 0xcd, 0x55, 0x45, 0x5b, 0x1a, + 0x44, 0x40, 0x97, 0x4d, 0x10, 0x30, 0x30, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, + 0x04, 0x14, 0xe0, 0x6f, 0xbb, 0xf2, 0x68, 0xc1, 0x65, 0xf7, 0xe4, 0x60, 0xe3, 0x17, 0xce, 0x09, 0xfb, 0xe9, 0x35, 0x92, + 0x95, 0x91, 0x04, 0x08, 0xb7, 0x0b, 0x82, 0x9e, 0xd4, 0x9f, 0x8e, 0xfd, 0x02, 0x01, 0x01 +}; + +unsigned char _ec_identity[] = { + 0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x03, 0x30, 0x82, 0x04, 0x85, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x82, 0x04, 0x76, 0x04, 0x82, 0x04, 0x72, 0x30, 0x82, 0x04, 0x6e, 0x30, 0x82, 0x03, 0x2f, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x03, 0x20, 0x30, 0x82, 0x03, 0x1c, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x03, 0x15, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x82, 0x45, 0xec, 0x50, 0xa0, 0x4e, 0xec, + 0x6d, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x02, 0xe8, 0x88, 0xd8, 0xd8, 0xc0, 0x6a, 0x39, 0x55, 0x4a, 0x65, 0x53, 0x7a, + 0x44, 0x9d, 0x95, 0x87, 0x84, 0x46, 0xc5, 0xa8, 0x94, 0xd3, 0xd4, 0x8f, 0xfe, 0x69, 0x13, 0x0e, 0xb0, 0x55, 0x4b, 0x88, + 0x7a, 0x37, 0x5d, 0x17, 0x97, 0x03, 0x47, 0x65, 0x83, 0x41, 0x2b, 0xbc, 0xbc, 0x22, 0x3e, 0xe9, 0x62, 0xbe, 0x51, 0x72, + 0x39, 0x7d, 0xfd, 0x96, 0x40, 0x85, 0x6b, 0x28, 0xee, 0xf6, 0x0c, 0x87, 0xeb, 0xd6, 0x19, 0x42, 0xfa, 0xcf, 0x30, 0x74, + 0xba, 0xca, 0x87, 0xf3, 0x0f, 0x83, 0x28, 0xc5, 0xbf, 0xbe, 0x29, 0x4b, 0x5d, 0x70, 0xcc, 0x9d, 0x26, 0x88, 0xe2, 0x84, + 0xbf, 0x11, 0x3e, 0x42, 0x23, 0x78, 0x46, 0x4f, 0x8b, 0xf3, 0xaf, 0xc7, 0x33, 0x6e, 0x4b, 0x83, 0x85, 0x44, 0xe3, 0x03, + 0xd1, 0xb5, 0x98, 0xad, 0x36, 0x5b, 0x37, 0xf0, 0x15, 0x12, 0xfb, 0x17, 0xa7, 0x92, 0xf9, 0x90, 0x5e, 0x8e, 0x12, 0xea, + 0x02, 0xbd, 0x9b, 0x9c, 0x9e, 0x29, 0x4d, 0x80, 0x13, 0x94, 0xcf, 0xf5, 0xc4, 0x12, 0x54, 0x87, 0x50, 0x90, 0x2b, 0xc7, + 0x43, 0x58, 0x2a, 0x85, 0xf3, 0x36, 0xb7, 0x88, 0xfb, 0x63, 0xe6, 0x58, 0xac, 0xd5, 0x22, 0xdc, 0x1c, 0x43, 0x2a, 0x0d, + 0x28, 0xb7, 0x14, 0x93, 0x2a, 0x5d, 0x41, 0x6d, 0xcb, 0xc8, 0xcb, 0xed, 0x17, 0x81, 0xd9, 0x73, 0x1b, 0xe1, 0x26, 0x69, + 0x5a, 0x52, 0x7f, 0x60, 0x08, 0x52, 0x85, 0x08, 0xe5, 0x3b, 0x66, 0x70, 0x0d, 0x84, 0x29, 0x34, 0xb4, 0xf4, 0x62, 0x41, + 0xca, 0xc2, 0xf8, 0x4b, 0xcd, 0x29, 0xcd, 0xb7, 0xc8, 0x7c, 0x3c, 0x8b, 0x28, 0x3e, 0x5d, 0xa8, 0x23, 0xab, 0xe6, 0x73, + 0x9e, 0x83, 0xc8, 0x81, 0xd0, 0x51, 0x16, 0xd0, 0xaf, 0x1d, 0xc8, 0x86, 0xb8, 0x9f, 0x08, 0x26, 0x20, 0x97, 0x69, 0xdf, + 0x30, 0x34, 0xd6, 0x00, 0xcd, 0x40, 0x7f, 0xe4, 0x97, 0x0c, 0x3b, 0x48, 0xa4, 0x81, 0x18, 0xca, 0x63, 0x09, 0xf8, 0xf0, + 0x4e, 0x95, 0x67, 0x65, 0x0a, 0xb5, 0xd6, 0xc7, 0xf7, 0xdf, 0x8d, 0x08, 0xb3, 0x10, 0x8f, 0xd2, 0x0f, 0xa9, 0x58, 0x20, + 0x75, 0x9e, 0xbb, 0x28, 0x70, 0x38, 0x45, 0x74, 0xc4, 0x8c, 0xa4, 0x31, 0x09, 0x2c, 0x17, 0x8a, 0xea, 0xcb, 0xff, 0x5d, + 0x3a, 0xd6, 0x13, 0x40, 0xd4, 0x51, 0x85, 0x9b, 0x7f, 0xe4, 0x0f, 0xc1, 0xf9, 0x51, 0xae, 0x26, 0x0f, 0x58, 0x31, 0x55, + 0x1f, 0x87, 0x08, 0x0d, 0x96, 0x4b, 0x1f, 0xf4, 0xa4, 0x3b, 0xa2, 0x31, 0x24, 0x93, 0x1d, 0xbf, 0xa8, 0xc7, 0x19, 0x77, + 0xef, 0xc4, 0xf5, 0xf5, 0x94, 0xbc, 0x24, 0xfa, 0xf5, 0x18, 0xb3, 0xe6, 0x33, 0x5c, 0x3d, 0xed, 0x30, 0xac, 0x4b, 0x8b, + 0x13, 0x5f, 0x8e, 0x0f, 0xb5, 0xd1, 0x25, 0x19, 0x06, 0x09, 0x4f, 0x35, 0xb9, 0x74, 0x00, 0x1c, 0x51, 0xc6, 0xd9, 0xdf, + 0x68, 0xbd, 0x3f, 0x83, 0x02, 0xc1, 0xf9, 0xfc, 0x9e, 0x6c, 0xce, 0xf5, 0x18, 0xd1, 0xe6, 0x07, 0x0d, 0x5d, 0x44, 0x68, + 0xc3, 0xe3, 0x4a, 0x22, 0x17, 0x56, 0xff, 0xe1, 0xa6, 0x19, 0x92, 0x8e, 0x82, 0x39, 0x07, 0xd7, 0xf1, 0xfc, 0x21, 0x54, + 0x3c, 0x39, 0x01, 0x76, 0x09, 0xe6, 0xf8, 0xd9, 0x1d, 0x28, 0x1e, 0xa6, 0x54, 0xc4, 0xe8, 0x49, 0x20, 0x7b, 0x01, 0x58, + 0xa9, 0x78, 0x1e, 0x49, 0x35, 0x84, 0x16, 0x04, 0x74, 0x73, 0x5f, 0xa6, 0xc9, 0xe0, 0xb5, 0x59, 0x70, 0x13, 0x9c, 0x52, + 0x11, 0x59, 0x76, 0x9f, 0x29, 0x68, 0x47, 0x78, 0xb3, 0x11, 0xdc, 0xcc, 0xb2, 0xd8, 0xa9, 0x8f, 0x4f, 0xa9, 0xa5, 0xa5, + 0x6c, 0x6d, 0x89, 0xa2, 0x53, 0x40, 0xed, 0x74, 0xf4, 0x78, 0xb4, 0x7c, 0xc1, 0x79, 0x41, 0x38, 0xe7, 0xea, 0xb3, 0x21, + 0xfd, 0x9c, 0x43, 0x98, 0x13, 0x05, 0x6b, 0x35, 0x77, 0xd9, 0x49, 0xa6, 0x3e, 0x89, 0x9b, 0x97, 0x03, 0x40, 0x91, 0xaa, + 0x9f, 0x10, 0xf7, 0xd7, 0x99, 0xc2, 0xa0, 0x58, 0x74, 0xae, 0x77, 0x5f, 0xba, 0x72, 0x1d, 0xbb, 0xd5, 0x93, 0x0c, 0x52, + 0x85, 0xe2, 0x79, 0x06, 0x43, 0x0e, 0xb7, 0x98, 0xd6, 0x5b, 0xa8, 0x67, 0x1b, 0xe2, 0x33, 0xd7, 0x05, 0xb7, 0x30, 0x30, + 0x2a, 0xb7, 0x9d, 0xcb, 0x68, 0xc8, 0x9a, 0xc7, 0xa2, 0x4e, 0x6c, 0x92, 0x5e, 0x93, 0x45, 0x6a, 0x40, 0x4a, 0xb9, 0xcf, + 0x54, 0x93, 0xf8, 0x29, 0xdd, 0x50, 0x34, 0x22, 0xec, 0xfe, 0xc5, 0xa5, 0x17, 0x8b, 0x2a, 0x9c, 0x10, 0xd5, 0x8f, 0x61, + 0x65, 0x8d, 0x02, 0x8c, 0x0a, 0x59, 0x85, 0x23, 0x24, 0x87, 0xab, 0x14, 0xa4, 0x5e, 0x7a, 0xfc, 0xab, 0x09, 0x52, 0x1a, + 0x8f, 0xd4, 0x43, 0x88, 0xbe, 0xc3, 0x40, 0xfe, 0xde, 0xad, 0x58, 0x79, 0x22, 0xb8, 0xe0, 0xdf, 0xfc, 0xf6, 0x41, 0xe0, + 0xc4, 0x5f, 0x9b, 0xca, 0xfb, 0x3a, 0x82, 0xc5, 0xbf, 0x87, 0x68, 0x62, 0x7e, 0x77, 0xb3, 0xf1, 0xcf, 0x4e, 0x99, 0x75, + 0x73, 0xf0, 0x14, 0x62, 0x92, 0x82, 0xb0, 0x6b, 0x61, 0xb5, 0xb4, 0x0c, 0x3b, 0x2c, 0xe4, 0x72, 0x3e, 0xd9, 0xce, 0xab, + 0xce, 0x3b, 0x43, 0x1f, 0xe0, 0xa9, 0xc3, 0x51, 0xf4, 0x65, 0xae, 0xcc, 0x41, 0x5e, 0xc6, 0xdc, 0x75, 0x70, 0xb9, 0xd9, + 0x4b, 0x91, 0xfb, 0x8a, 0x07, 0xf8, 0x8a, 0xe5, 0x9e, 0x7e, 0x7b, 0x6f, 0x0b, 0x44, 0x68, 0x85, 0xa2, 0x0e, 0xa6, 0xaa, + 0x3e, 0x02, 0x79, 0xaa, 0x80, 0x13, 0x0e, 0x7c, 0x63, 0xb7, 0x37, 0x6c, 0x2a, 0x30, 0x82, 0x01, 0x37, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x28, 0x04, 0x82, 0x01, 0x24, 0x30, 0x82, 0x01, 0x20, + 0x30, 0x82, 0x01, 0x1c, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x81, 0xbc, + 0x30, 0x81, 0xb9, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, + 0x08, 0xfc, 0x17, 0x87, 0x42, 0xb4, 0x69, 0xe7, 0x51, 0x02, 0x02, 0x08, 0x00, 0x04, 0x81, 0x98, 0xf6, 0xe7, 0x7c, 0x12, + 0x5f, 0x2a, 0x64, 0xc2, 0x3e, 0xa5, 0xd5, 0xe8, 0xd5, 0xc3, 0x5b, 0x8b, 0xbb, 0xbe, 0x7d, 0xd3, 0xc3, 0xfe, 0xed, 0x56, + 0xb4, 0x0f, 0x8a, 0xa3, 0x9e, 0x76, 0xb4, 0x6c, 0xec, 0x39, 0x23, 0xce, 0xa6, 0x4d, 0x4a, 0x9a, 0x9a, 0x50, 0x4f, 0x51, + 0xbd, 0x40, 0x95, 0x5a, 0x1c, 0x7d, 0x78, 0xd2, 0xc1, 0x2c, 0xeb, 0x03, 0x39, 0x9c, 0xa6, 0x96, 0x3f, 0xff, 0x1f, 0x6d, + 0x25, 0xf1, 0x6b, 0x17, 0xb6, 0x46, 0xbb, 0x8d, 0xc5, 0xd8, 0x52, 0x4a, 0x81, 0x14, 0xc8, 0xfd, 0x37, 0x9a, 0x89, 0x28, + 0x21, 0x61, 0xa1, 0x5e, 0xc1, 0x2e, 0x60, 0x82, 0xc0, 0x84, 0x37, 0x9f, 0xa8, 0xa5, 0x60, 0xba, 0x5e, 0x0b, 0x68, 0x0e, + 0x7e, 0x12, 0xa1, 0x83, 0x45, 0x16, 0x32, 0x0b, 0x01, 0xc6, 0x91, 0x4b, 0xcd, 0x47, 0x5a, 0xe5, 0x34, 0x57, 0x43, 0x6f, + 0xd5, 0x5e, 0x76, 0x99, 0xe3, 0x9e, 0xc3, 0xa7, 0xf5, 0xb3, 0x7b, 0x49, 0x2d, 0x74, 0x17, 0x70, 0xaf, 0x24, 0xc9, 0x0e, + 0xcc, 0x23, 0xe6, 0x80, 0xfc, 0x2e, 0x0b, 0xa7, 0x31, 0x4e, 0x30, 0x27, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x14, 0x31, 0x1a, 0x1e, 0x18, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x53, 0x00, 0x20, 0x00, 0x45, 0x00, 0x43, 0x00, + 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x00, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x23, 0xa4, 0x22, 0x91, 0xad, 0x83, 0x47, 0x86, 0xf2, 0x1f, 0x18, 0x0d, + 0x62, 0x70, 0x5c, 0x45, 0x40, 0x00, 0x30, 0xc6, 0x30, 0x30, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, + 0x1a, 0x05, 0x00, 0x04, 0x14, 0xf6, 0xff, 0x21, 0x16, 0x00, 0x67, 0x5b, 0xc1, 0x78, 0xcc, 0x05, 0x18, 0x77, 0x60, 0x45, + 0xa4, 0xd9, 0x79, 0xcf, 0xea, 0x04, 0x08, 0x3d, 0x07, 0x4e, 0x1e, 0xcb, 0x39, 0xda, 0x8a, 0x02, 0x01, 0x01 +}; + +/* + * MARK: RSA-signed messages (no attributes) + */ +unsigned char rsa_md5[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41, + 0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x82, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, + 0x30, 0x30, 0x31, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x38, 0x32, + 0x39, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, + 0x52, 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, + 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x9b, 0xcb, 0x6c, 0x77, 0xb7, 0xd1, 0x05, 0xa0, 0xae, 0x86, 0x20, 0x45, 0xd3, 0xf4, + 0x24, 0x8d, 0x25, 0x34, 0x31, 0xa9, 0xe2, 0x10, 0x36, 0xf5, 0x0a, 0x0b, 0x90, 0x4a, 0xa5, 0x6b, 0x5c, 0x16, 0xcd, 0xb0, + 0x72, 0xe9, 0xa9, 0x80, 0x5f, 0x6d, 0xb2, 0x4d, 0xd9, 0x58, 0x16, 0x9f, 0x68, 0x81, 0x9a, 0x6b, 0xeb, 0xd5, 0x4b, 0xf7, + 0x7d, 0x59, 0xe9, 0x46, 0x2b, 0x5b, 0x8f, 0xe4, 0xec, 0xab, 0x5c, 0x07, 0x74, 0xa2, 0x0e, 0x59, 0xbb, 0xfc, 0xd3, 0xcf, + 0xf7, 0x21, 0x88, 0x6c, 0x88, 0xd9, 0x6b, 0xa3, 0xa3, 0x4e, 0x5b, 0xd1, 0x1c, 0xfb, 0x04, 0xf5, 0xb2, 0x12, 0x0e, 0x54, + 0x59, 0x4d, 0xce, 0x0a, 0xe0, 0x26, 0x24, 0x06, 0xeb, 0xc8, 0xa2, 0xc6, 0x41, 0x28, 0xf9, 0x79, 0xe4, 0xb1, 0x4e, 0x00, + 0x6f, 0x6e, 0xf8, 0x96, 0x9e, 0x45, 0x28, 0x70, 0xec, 0xc7, 0xdc, 0xa2, 0xdd, 0x92, 0xab, 0xdd, 0x6f, 0xd8, 0x57, 0xba, + 0xcc, 0x29, 0xbe, 0xb7, 0x00, 0x1e, 0x8d, 0x13, 0x3f, 0x47, 0x34, 0x3c, 0xd0, 0xc6, 0xc8, 0x17, 0xdf, 0x74, 0x8a, 0xb1, + 0xc3, 0x68, 0xd5, 0xba, 0x76, 0x60, 0x55, 0x5f, 0x8d, 0xfa, 0xbd, 0xe7, 0x11, 0x9e, 0x59, 0x96, 0xe5, 0x93, 0x70, 0xad, + 0x41, 0xfb, 0x61, 0x46, 0x70, 0xc4, 0x05, 0x12, 0x23, 0x23, 0xc0, 0x9d, 0xc8, 0xc5, 0xf5, 0x96, 0xe5, 0x48, 0x10, 0x86, + 0x8a, 0x1e, 0x3b, 0x83, 0xd1, 0x47, 0x3a, 0x27, 0x00, 0x71, 0x10, 0xa3, 0x52, 0xba, 0xae, 0x01, 0x43, 0x87, 0x9c, 0x6a, + 0x1b, 0xea, 0x1a, 0x44, 0x4f, 0x4a, 0xac, 0xd4, 0x82, 0x55, 0xee, 0x1f, 0x25, 0x9c, 0x55, 0xca, 0xd2, 0xd0, 0x3a, 0x0b, + 0x70, 0x90, 0x60, 0x49, 0x47, 0x02, 0xfd, 0x89, 0x2c, 0x9a, 0x26, 0x36, 0x34, 0x8f, 0x24, 0x39, 0x8c, 0xe9, 0xa2, 0x52, + 0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0xed, 0x5b, 0xaf, 0x13, 0x16, 0x5d, 0xe2, 0xdd, 0x5c, 0x48, 0x1c, 0xd5, + 0x6e, 0x8b, 0x04, 0x51, 0xd6, 0x38, 0x80, 0xfd, 0x52, 0x4a, 0x34, 0xdc, 0x13, 0x35, 0x6e, 0x64, 0x39, 0x39, 0x39, 0x09, + 0xa7, 0x6c, 0x2d, 0x39, 0xf2, 0x04, 0x21, 0xe3, 0xea, 0x8f, 0xf8, 0xbe, 0x46, 0x0e, 0x20, 0x82, 0xd0, 0xc5, 0x60, 0xbf, + 0x57, 0x6f, 0xd8, 0x29, 0xb4, 0x66, 0xdb, 0xbf, 0x92, 0xc9, 0xdc, 0x90, 0x97, 0x0f, 0x2f, 0x59, 0xa0, 0x13, 0xf3, 0xa4, + 0xca, 0xde, 0x3f, 0x80, 0x2a, 0x99, 0xb4, 0xee, 0x71, 0xc3, 0x56, 0x71, 0x51, 0x37, 0x55, 0xa1, 0x60, 0x89, 0xab, 0x94, + 0x0e, 0xb9, 0x70, 0xa5, 0x55, 0xf3, 0x1a, 0x87, 0xa4, 0x41, 0x4c, 0x45, 0xba, 0xb6, 0x56, 0xd6, 0x45, 0x56, 0x12, 0x60, + 0xe5, 0x91, 0xec, 0xf7, 0xbe, 0x39, 0xa4, 0x80, 0x08, 0x9f, 0xea, 0x17, 0x12, 0x0e, 0xa6, 0xe6, 0xef, 0x09, 0xf7, 0x61, + 0x51, 0x57, 0x73, 0xe3, 0x57, 0x88, 0xd7, 0xf8, 0x5f, 0xaf, 0x5d, 0xaf, 0x88, 0x32, 0xb4, 0x09, 0x3e, 0x7c, 0x25, 0x77, + 0x35, 0xe9, 0x3e, 0x6e, 0x0a, 0xb9, 0xb4, 0xa3, 0x06, 0x07, 0x0f, 0x7e, 0x93, 0x26, 0x16, 0x38, 0x1e, 0x4e, 0x72, 0xaf, + 0x06, 0x44, 0x1e, 0x8d, 0x96, 0xa6, 0x15, 0x9c, 0x82, 0x6d, 0x71, 0x99, 0x84, 0x8d, 0x12, 0x46, 0xf2, 0xbb, 0xa7, 0x63, + 0x7a, 0x32, 0xda, 0xa9, 0xde, 0xb6, 0x34, 0x14, 0xfb, 0x07, 0x0c, 0xab, 0x3b, 0x0a, 0xa1, 0x8b, 0xda, 0x15, 0xb3, 0x63, + 0xf3, 0x5c, 0x45, 0x2f, 0x0b, 0x6e, 0xc7, 0x27, 0x72, 0xc1, 0x37, 0x56, 0x30, 0xe3, 0x26, 0xbb, 0x19, 0x4f, 0x91, 0xa1, + 0xd0, 0x30, 0x29, 0x5b, 0x79, 0x79, 0x5c, 0xe6, 0x4f, 0xed, 0xcf, 0x81, 0xb2, 0x50, 0x35, 0x96, 0x23, 0xb2, 0x9f, 0xca, + 0x3f, 0xb5, 0x54, 0x31, 0x82, 0x01, 0xdb, 0x30, 0x82, 0x01, 0xd7, 0x02, 0x01, 0x01, 0x30, 0x81, 0xb0, 0x30, 0x81, 0xa7, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x44, 0x4f, 0x1c, 0x4f, 0x73, 0x46, 0xb4, 0x67, 0x86, 0x53, 0x6e, 0x09, 0x4a, 0x18, + 0x89, 0x82, 0xb0, 0x9d, 0xf5, 0xa9, 0x81, 0x21, 0x97, 0x2d, 0x1c, 0x61, 0x4a, 0xa0, 0x9a, 0xa1, 0x6d, 0xb0, 0xb2, 0xbe, + 0xc8, 0x27, 0x4a, 0x0e, 0xbd, 0x52, 0xf2, 0x56, 0x8a, 0xb6, 0x41, 0x45, 0xfc, 0xf6, 0x09, 0xb7, 0x83, 0x89, 0x87, 0xc6, + 0x5c, 0xfb, 0xe0, 0x22, 0x75, 0x9b, 0xa2, 0x24, 0x65, 0xd0, 0x51, 0xe0, 0xc6, 0x00, 0xad, 0x39, 0x50, 0x84, 0x31, 0x5c, + 0x63, 0x54, 0x8c, 0x3c, 0xa3, 0x69, 0x7f, 0xb2, 0x2c, 0x60, 0xa1, 0x5d, 0x6a, 0xac, 0xb2, 0x02, 0x26, 0x5b, 0x82, 0x61, + 0x2e, 0xb0, 0x32, 0xf7, 0x4e, 0xa3, 0x31, 0x00, 0xa7, 0x29, 0x4b, 0xdc, 0x30, 0x7f, 0x33, 0x14, 0x5a, 0xf1, 0x58, 0x5e, + 0x90, 0x77, 0xf3, 0x9c, 0x68, 0xbe, 0xe9, 0x4c, 0xf6, 0x33, 0x64, 0xdf, 0x3f, 0xf4, 0xb9, 0x6b, 0xd5, 0x54, 0xb8, 0x4a, + 0x8f, 0xbb, 0xce, 0xde, 0x4a, 0x58, 0x9e, 0xad, 0x67, 0x99, 0xbe, 0xe7, 0x0a, 0x54, 0x2b, 0x19, 0x0c, 0x45, 0x45, 0x41, + 0x9e, 0x56, 0x07, 0x45, 0x95, 0x56, 0x92, 0xa8, 0xd6, 0x8f, 0xab, 0xb0, 0x9b, 0x39, 0xcb, 0x5a, 0x0d, 0x29, 0x2d, 0x8b, + 0x53, 0xf4, 0x85, 0xb1, 0xec, 0x6f, 0x95, 0xd2, 0x6e, 0xd5, 0x36, 0x65, 0xd4, 0x30, 0x4d, 0x26, 0x37, 0x8b, 0x06, 0x39, + 0xf5, 0xe6, 0xde, 0x8c, 0xf0, 0x84, 0x69, 0x96, 0xd7, 0xb9, 0x22, 0x24, 0xf5, 0x74, 0x69, 0x4e, 0x2b, 0xea, 0x9d, 0x5a, + 0xd7, 0xfc, 0xea, 0x7d, 0x8f, 0xd7, 0x34, 0x7f, 0x4f, 0x8a, 0x5c, 0xb6, 0x73, 0x9a, 0x8f, 0xa0, 0x74, 0x5e, 0xca, 0xdc, + 0xc9, 0x78, 0x85, 0x46, 0xb8, 0x79, 0x29, 0x10, 0xa5, 0x6c, 0x1e, 0x4e, 0xac, 0xba, 0x8e, 0xa2, 0x2d, 0xf8, 0x40, 0x2d, + 0xde, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char rsa_sha1[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 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, 0xd8, 0x30, 0x82, 0x01, 0xd4, 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, 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, + 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, + 0xda, 0x00, 0x5d, 0x7f, 0xf3, 0x2e, 0xea, 0x6f, 0x8b, 0x98, 0xb6, 0x7e, 0x63, 0x75, 0x3b, 0xd0, 0xfc, 0x69, 0xa8, 0x0d, + 0x8f, 0xe3, 0xc0, 0x7c, 0xc4, 0xa4, 0x2e, 0x66, 0x63, 0x7f, 0xae, 0x4e, 0xb8, 0xc3, 0xcd, 0x53, 0xf6, 0x7b, 0xf1, 0x7b, + 0xfa, 0x89, 0x6f, 0xb6, 0x81, 0x65, 0x13, 0xc4, 0x2d, 0xdd, 0x7a, 0x52, 0x3d, 0x77, 0xd1, 0x78, 0x48, 0x70, 0x17, 0x58, + 0x1e, 0x58, 0x5c, 0xb8, 0xcf, 0x22, 0x3a, 0x1f, 0x95, 0x99, 0xe5, 0x5e, 0x91, 0xb4, 0x0f, 0x2e, 0x17, 0xeb, 0x5d, 0x20, + 0x80, 0xfe, 0x75, 0x07, 0x75, 0x9b, 0xda, 0x26, 0xa0, 0xb4, 0x1f, 0xe2, 0x8b, 0x94, 0x90, 0xad, 0x05, 0x75, 0xef, 0xe3, + 0x35, 0xa4, 0x6f, 0x50, 0x11, 0x40, 0xd5, 0x20, 0x1c, 0x32, 0xed, 0x24, 0xd6, 0x1e, 0x76, 0x95, 0x96, 0x35, 0xa2, 0x7c, + 0x81, 0x42, 0x95, 0x32, 0x58, 0xd8, 0x68, 0xf8, 0x2e, 0x06, 0x5e, 0x99, 0x8f, 0xc2, 0x43, 0x5e, 0x84, 0x21, 0x8a, 0x87, + 0xfc, 0x36, 0xff, 0x10, 0x81, 0x52, 0xe7, 0xb0, 0xbd, 0x5d, 0x5e, 0xb3, 0x24, 0xb2, 0x06, 0x04, 0xb7, 0x6f, 0xb2, 0x6d, + 0x83, 0x3f, 0xe0, 0xc6, 0x3d, 0x29, 0xf3, 0x90, 0xa3, 0x3a, 0xcc, 0x5c, 0x64, 0x34, 0x22, 0x9c, 0xfb, 0x86, 0x83, 0xd1, + 0x48, 0x6f, 0xea, 0x1d, 0xca, 0x2c, 0x4f, 0x13, 0xc7, 0x94, 0x82, 0x38, 0xc2, 0xbd, 0x6b, 0xd4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; + +unsigned char 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, 0x01, 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) + */ +unsigned char rsa_md5_attr[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41, + 0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x82, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, + 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, + 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, + 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, + 0x30, 0x30, 0x31, 0x38, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x38, 0x32, + 0x39, 0x5a, 0x30, 0x81, 0xa7, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, + 0x52, 0x53, 0x41, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, + 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x9b, 0xcb, 0x6c, 0x77, 0xb7, 0xd1, 0x05, 0xa0, 0xae, 0x86, 0x20, 0x45, 0xd3, 0xf4, + 0x24, 0x8d, 0x25, 0x34, 0x31, 0xa9, 0xe2, 0x10, 0x36, 0xf5, 0x0a, 0x0b, 0x90, 0x4a, 0xa5, 0x6b, 0x5c, 0x16, 0xcd, 0xb0, + 0x72, 0xe9, 0xa9, 0x80, 0x5f, 0x6d, 0xb2, 0x4d, 0xd9, 0x58, 0x16, 0x9f, 0x68, 0x81, 0x9a, 0x6b, 0xeb, 0xd5, 0x4b, 0xf7, + 0x7d, 0x59, 0xe9, 0x46, 0x2b, 0x5b, 0x8f, 0xe4, 0xec, 0xab, 0x5c, 0x07, 0x74, 0xa2, 0x0e, 0x59, 0xbb, 0xfc, 0xd3, 0xcf, + 0xf7, 0x21, 0x88, 0x6c, 0x88, 0xd9, 0x6b, 0xa3, 0xa3, 0x4e, 0x5b, 0xd1, 0x1c, 0xfb, 0x04, 0xf5, 0xb2, 0x12, 0x0e, 0x54, + 0x59, 0x4d, 0xce, 0x0a, 0xe0, 0x26, 0x24, 0x06, 0xeb, 0xc8, 0xa2, 0xc6, 0x41, 0x28, 0xf9, 0x79, 0xe4, 0xb1, 0x4e, 0x00, + 0x6f, 0x6e, 0xf8, 0x96, 0x9e, 0x45, 0x28, 0x70, 0xec, 0xc7, 0xdc, 0xa2, 0xdd, 0x92, 0xab, 0xdd, 0x6f, 0xd8, 0x57, 0xba, + 0xcc, 0x29, 0xbe, 0xb7, 0x00, 0x1e, 0x8d, 0x13, 0x3f, 0x47, 0x34, 0x3c, 0xd0, 0xc6, 0xc8, 0x17, 0xdf, 0x74, 0x8a, 0xb1, + 0xc3, 0x68, 0xd5, 0xba, 0x76, 0x60, 0x55, 0x5f, 0x8d, 0xfa, 0xbd, 0xe7, 0x11, 0x9e, 0x59, 0x96, 0xe5, 0x93, 0x70, 0xad, + 0x41, 0xfb, 0x61, 0x46, 0x70, 0xc4, 0x05, 0x12, 0x23, 0x23, 0xc0, 0x9d, 0xc8, 0xc5, 0xf5, 0x96, 0xe5, 0x48, 0x10, 0x86, + 0x8a, 0x1e, 0x3b, 0x83, 0xd1, 0x47, 0x3a, 0x27, 0x00, 0x71, 0x10, 0xa3, 0x52, 0xba, 0xae, 0x01, 0x43, 0x87, 0x9c, 0x6a, + 0x1b, 0xea, 0x1a, 0x44, 0x4f, 0x4a, 0xac, 0xd4, 0x82, 0x55, 0xee, 0x1f, 0x25, 0x9c, 0x55, 0xca, 0xd2, 0xd0, 0x3a, 0x0b, + 0x70, 0x90, 0x60, 0x49, 0x47, 0x02, 0xfd, 0x89, 0x2c, 0x9a, 0x26, 0x36, 0x34, 0x8f, 0x24, 0x39, 0x8c, 0xe9, 0xa2, 0x52, + 0x8f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x4c, 0xed, 0x5b, 0xaf, 0x13, 0x16, 0x5d, 0xe2, 0xdd, 0x5c, 0x48, 0x1c, 0xd5, + 0x6e, 0x8b, 0x04, 0x51, 0xd6, 0x38, 0x80, 0xfd, 0x52, 0x4a, 0x34, 0xdc, 0x13, 0x35, 0x6e, 0x64, 0x39, 0x39, 0x39, 0x09, + 0xa7, 0x6c, 0x2d, 0x39, 0xf2, 0x04, 0x21, 0xe3, 0xea, 0x8f, 0xf8, 0xbe, 0x46, 0x0e, 0x20, 0x82, 0xd0, 0xc5, 0x60, 0xbf, + 0x57, 0x6f, 0xd8, 0x29, 0xb4, 0x66, 0xdb, 0xbf, 0x92, 0xc9, 0xdc, 0x90, 0x97, 0x0f, 0x2f, 0x59, 0xa0, 0x13, 0xf3, 0xa4, + 0xca, 0xde, 0x3f, 0x80, 0x2a, 0x99, 0xb4, 0xee, 0x71, 0xc3, 0x56, 0x71, 0x51, 0x37, 0x55, 0xa1, 0x60, 0x89, 0xab, 0x94, + 0x0e, 0xb9, 0x70, 0xa5, 0x55, 0xf3, 0x1a, 0x87, 0xa4, 0x41, 0x4c, 0x45, 0xba, 0xb6, 0x56, 0xd6, 0x45, 0x56, 0x12, 0x60, + 0xe5, 0x91, 0xec, 0xf7, 0xbe, 0x39, 0xa4, 0x80, 0x08, 0x9f, 0xea, 0x17, 0x12, 0x0e, 0xa6, 0xe6, 0xef, 0x09, 0xf7, 0x61, + 0x51, 0x57, 0x73, 0xe3, 0x57, 0x88, 0xd7, 0xf8, 0x5f, 0xaf, 0x5d, 0xaf, 0x88, 0x32, 0xb4, 0x09, 0x3e, 0x7c, 0x25, 0x77, + 0x35, 0xe9, 0x3e, 0x6e, 0x0a, 0xb9, 0xb4, 0xa3, 0x06, 0x07, 0x0f, 0x7e, 0x93, 0x26, 0x16, 0x38, 0x1e, 0x4e, 0x72, 0xaf, + 0x06, 0x44, 0x1e, 0x8d, 0x96, 0xa6, 0x15, 0x9c, 0x82, 0x6d, 0x71, 0x99, 0x84, 0x8d, 0x12, 0x46, 0xf2, 0xbb, 0xa7, 0x63, + 0x7a, 0x32, 0xda, 0xa9, 0xde, 0xb6, 0x34, 0x14, 0xfb, 0x07, 0x0c, 0xab, 0x3b, 0x0a, 0xa1, 0x8b, 0xda, 0x15, 0xb3, 0x63, + 0xf3, 0x5c, 0x45, 0x2f, 0x0b, 0x6e, 0xc7, 0x27, 0x72, 0xc1, 0x37, 0x56, 0x30, 0xe3, 0x26, 0xbb, 0x19, 0x4f, 0x91, 0xa1, + 0xd0, 0x30, 0x29, 0x5b, 0x79, 0x79, 0x5c, 0xe6, 0x4f, 0xed, 0xcf, 0x81, 0xb2, 0x50, 0x35, 0x96, 0x23, 0xb2, 0x9f, 0xca, + 0x3f, 0xb5, 0x54, 0x31, 0x82, 0x02, 0x36, 0x30, 0x82, 0x02, 0x32, 0x02, 0x01, 0x01, 0x30, 0x81, 0xb0, 0x30, 0x81, 0xa7, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x11, 0x43, 0x4d, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x74, 0x3f, 0x1d, 0x98, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0xa0, 0x59, 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, 0x36, 0x30, 0x33, 0x31, 0x38, 0x31, 0x33, + 0x32, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x12, + 0x04, 0x10, 0xed, 0xa3, 0x75, 0x22, 0xef, 0xdc, 0x73, 0x52, 0x7f, 0xff, 0x56, 0x77, 0xdd, 0x1b, 0xaa, 0xae, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x8f, 0x71, 0x05, + 0x7b, 0x53, 0xb1, 0x1d, 0xd3, 0xc5, 0x17, 0xc1, 0x65, 0x6d, 0xa6, 0xa2, 0x14, 0xd6, 0x07, 0xaa, 0xa1, 0x33, 0x3d, 0x30, + 0x4c, 0x2e, 0x62, 0x66, 0x5f, 0x43, 0x7e, 0x57, 0x65, 0x5f, 0xa2, 0x71, 0x2a, 0x20, 0x48, 0xc3, 0xef, 0x82, 0x6b, 0xcb, + 0xb9, 0xf4, 0xae, 0x8d, 0x90, 0x7a, 0x47, 0x1d, 0x28, 0xec, 0x66, 0x3c, 0x2a, 0x5c, 0xa1, 0x74, 0xce, 0x85, 0x8e, 0x37, + 0x45, 0x9e, 0xf0, 0xed, 0x67, 0x4a, 0xf8, 0x3e, 0xa4, 0xcb, 0xac, 0xdb, 0x35, 0x82, 0x71, 0xbf, 0xfb, 0xc6, 0xcc, 0x89, + 0x17, 0xb6, 0xaf, 0xfb, 0x1c, 0x4b, 0x92, 0x21, 0x88, 0xc1, 0x8e, 0x0e, 0xf6, 0x05, 0xb6, 0x70, 0x7b, 0x34, 0x98, 0x27, + 0xe2, 0xa9, 0x3b, 0xf2, 0x72, 0xba, 0xd4, 0x33, 0x21, 0x72, 0x55, 0x91, 0x4c, 0x03, 0xda, 0x18, 0x36, 0xe7, 0xdb, 0x77, + 0x9e, 0xdb, 0x0f, 0x0a, 0x0c, 0xff, 0x45, 0x46, 0x5e, 0x8b, 0xd8, 0x4b, 0x5f, 0xdd, 0xa0, 0x16, 0xc8, 0xdd, 0xf2, 0x30, + 0xea, 0x54, 0x6a, 0x05, 0x94, 0x4e, 0x75, 0xc6, 0x38, 0x96, 0xd2, 0x73, 0x92, 0xff, 0xe3, 0xc6, 0x73, 0xd4, 0xb2, 0x9e, + 0xf8, 0xc1, 0xa5, 0x4d, 0x0a, 0x49, 0xdd, 0x41, 0x8f, 0x06, 0xd5, 0x6e, 0xe1, 0x51, 0x4a, 0xb7, 0x88, 0xec, 0xe3, 0x3e, + 0xcd, 0xfd, 0x54, 0x0d, 0x91, 0x75, 0xa2, 0xa0, 0x77, 0x82, 0x2b, 0xa1, 0xb6, 0x4f, 0x15, 0x44, 0xa2, 0xdf, 0xd2, 0x5b, + 0xf7, 0xd1, 0x91, 0xf3, 0x24, 0x29, 0x0b, 0xef, 0x71, 0xf5, 0xee, 0xfa, 0x21, 0xa1, 0xfb, 0xab, 0x78, 0x4d, 0x87, 0x97, + 0xb8, 0x91, 0x9d, 0xd9, 0x9e, 0x3b, 0x9f, 0xcc, 0xcb, 0x0b, 0x38, 0xd9, 0x84, 0xf4, 0xd4, 0x1d, 0xee, 0xab, 0x88, 0x9d, + 0xd5, 0xff, 0xe3, 0x2f, 0x93, 0x75, 0xfd, 0x77, 0xff, 0xab, 0x41, 0x55, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char rsa_sha1_attr[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 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, 0x02, 0x37, 0x30, 0x82, 0x02, 0x33, 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, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0xa0, 0x5d, 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, 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, + 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, + 0x02, 0x19, 0x3d, 0xfc, 0xdd, 0xab, 0x45, 0xe7, 0xf4, 0xeb, 0xfd, 0xa2, 0x17, 0x3e, 0xf2, 0xae, 0x8a, 0x07, 0x84, 0x98, + 0xe7, 0xee, 0x42, 0x0c, 0x74, 0x08, 0xf6, 0xc0, 0xfc, 0x29, 0xc3, 0x8a, 0xbe, 0x6c, 0x0b, 0x1e, 0x4a, 0xa8, 0x43, 0x3c, + 0x94, 0xdb, 0x26, 0xdb, 0x8c, 0x28, 0x68, 0xea, 0x53, 0x39, 0x89, 0xe8, 0xfe, 0x94, 0x60, 0x1f, 0x23, 0xf7, 0x1f, 0x3a, + 0x40, 0xdf, 0xe1, 0x4b, 0x9a, 0x66, 0x11, 0x9e, 0x45, 0x68, 0x85, 0x15, 0x64, 0x5f, 0xe6, 0xc8, 0x2a, 0xca, 0x07, 0x66, + 0x23, 0x01, 0x00, 0xa8, 0x90, 0x68, 0x05, 0xfd, 0x3a, 0x96, 0x7f, 0x86, 0x55, 0x6d, 0xe4, 0x92, 0x12, 0xe9, 0x07, 0x51, + 0x54, 0xfb, 0x79, 0x55, 0x13, 0xca, 0xdf, 0xb9, 0xb5, 0x79, 0x9f, 0xf0, 0x5d, 0xb0, 0xfd, 0xe8, 0xa2, 0xf3, 0x15, 0x02, + 0xfb, 0xe0, 0x25, 0xd6, 0xd6, 0x9c, 0x87, 0xfd, 0xee, 0x11, 0x5a, 0x62, 0xe3, 0xfe, 0xea, 0xff, 0xd2, 0xde, 0x4c, 0x03, + 0xfe, 0x3c, 0x66, 0xcc, 0x54, 0x3c, 0xe2, 0x0d, 0xde, 0x3e, 0x0e, 0x38, 0x7b, 0x67, 0xe5, 0xd1, 0xea, 0x78, 0x4f, 0xb2, + 0x8e, 0x8f, 0x2b, 0xc9, 0x76, 0x2c, 0xa9, 0xcc, 0x1d, 0xdb, 0x71, 0x40, 0x8a, 0x67, 0xbe, 0x6f, 0x3d, 0xa3, 0xba, 0x9a, + 0xa4, 0x4b, 0x74, 0x57, 0xd9, 0xcb, 0x4e, 0xff, 0xc2, 0xb4, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char rsa_sha256_attr[] = { + 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, 0x02, 0x47, 0x30, 0x82, 0x02, 0x43, 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, 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, 0x36, 0x30, 0x33, 0x31, 0x38, + 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, + 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, + 0xb7, 0x72, 0x7b, 0x32, 0xa1, 0xff, 0x69, 0x51, 0xd4, 0xc9, 0x3e, 0x1f, 0x89, 0x71, 0x39, 0xd9, 0x99, 0x1e, 0xa9, 0x33, + 0x83, 0xc1, 0x37, 0x3e, 0xf2, 0xbd, 0xad, 0x8f, 0xa9, 0x24, 0x82, 0xad, 0x7d, 0x54, 0x8f, 0x6f, 0x8a, 0xdb, 0xbf, 0xd4, + 0xd4, 0x9c, 0x0a, 0x11, 0x8a, 0xb2, 0x0c, 0xd9, 0x32, 0xf1, 0xe6, 0x76, 0x4a, 0x09, 0x1a, 0x6a, 0xdf, 0x48, 0x2f, 0xf4, + 0x89, 0x73, 0xc8, 0x37, 0xb0, 0x14, 0xa9, 0x59, 0xc3, 0x94, 0x63, 0x6c, 0xfd, 0x90, 0x2c, 0x3a, 0x58, 0xa4, 0x5e, 0xbb, + 0x2f, 0x5e, 0x1d, 0xdc, 0x57, 0x47, 0x09, 0x77, 0xbc, 0x2b, 0x76, 0xfa, 0x97, 0x85, 0x63, 0x4b, 0xd6, 0x32, 0xac, 0x7e, + 0xa0, 0x41, 0xd1, 0xc7, 0x1a, 0x59, 0x3f, 0x39, 0xd1, 0xa7, 0x3f, 0xa7, 0x3f, 0x23, 0x11, 0x3e, 0x19, 0x6d, 0x63, 0xa1, + 0x4c, 0xcd, 0x03, 0x22, 0x07, 0x72, 0x4c, 0x44, 0x07, 0xd9, 0x85, 0x18, 0x63, 0x8c, 0x96, 0x29, 0x20, 0xc4, 0x1b, 0xac, + 0x6e, 0x4f, 0x95, 0x7d, 0x97, 0x9f, 0xcc, 0x94, 0xf4, 0xfe, 0x8b, 0x08, 0x1c, 0x8a, 0x9d, 0x19, 0x6d, 0x42, 0x92, 0x73, + 0xa9, 0xd0, 0xb3, 0x4c, 0x46, 0x40, 0x88, 0xcb, 0x51, 0x2f, 0x73, 0xec, 0x43, 0x4c, 0x09, 0xa7, 0xb5, 0x89, 0x4b, 0xe4, + 0xbc, 0xdc, 0x1d, 0x17, 0xf9, 0x55, 0xe5, 0x59, 0xea, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * MARK: EC-signed messages (no attributes) + */ +unsigned char ec_md5[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41, + 0x69, 0x6e, 0x27, 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xa0, 0x82, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0xa6, + 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, + 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, + 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, 0x39, + 0x35, 0x36, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, 0x88, + 0x07, 0x03, 0x42, 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, 0x81, + 0xa1, 0x4e, 0xc5, 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, 0x6c, + 0xc4, 0xcd, 0x8c, 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, 0x13, + 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x81, + 0x1b, 0xed, 0x5a, 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, 0x85, + 0x7a, 0x2f, 0x65, 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, 0xcb, + 0xeb, 0xf7, 0x1c, 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, 0xf5, + 0xbe, 0x85, 0x40, 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x1b, 0x30, 0x82, 0x01, 0x17, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, 0x30, + 0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x04, + 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xa2, 0x9f, 0x73, 0x2d, 0x2a, 0xa0, 0xca, 0xb4, 0xf6, 0xc9, 0xfd, 0x68, 0xd2, 0xe7, + 0x8d, 0x07, 0xdd, 0x60, 0xcc, 0xe1, 0xb6, 0xfe, 0xa9, 0x11, 0xd8, 0xb7, 0x68, 0xa4, 0xe3, 0xed, 0x1b, 0x42, 0x02, 0x20, + 0x4b, 0x64, 0x3e, 0xe0, 0x50, 0x29, 0x89, 0x30, 0xd0, 0x32, 0x2d, 0xfc, 0xd3, 0x6b, 0xe8, 0x06, 0x15, 0xe2, 0x91, 0x99, + 0x7b, 0x26, 0xc4, 0xa3, 0x85, 0xf0, 0x05, 0x95, 0x4d, 0xf9, 0x51, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_sha1[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41, 0x69, 0x6e, 0x27, + 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x82, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x50, 0x2b, + 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0xa6, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, + 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, + 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, + 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, 0x81, 0xa6, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, + 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, + 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, 0x88, 0x07, 0x03, 0x42, + 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, 0x81, 0xa1, 0x4e, 0xc5, + 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, 0x6c, 0xc4, 0xcd, 0x8c, + 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, 0x13, 0x30, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x81, 0x1b, 0xed, 0x5a, + 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, 0x85, 0x7a, 0x2f, 0x65, + 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, 0xcb, 0xeb, 0xf7, 0x1c, + 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, 0xf5, 0xbe, 0x85, 0x40, + 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x19, 0x30, 0x82, 0x01, 0x15, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, 0x30, 0x81, 0xa6, 0x31, + 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, + 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, + 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x04, 0x48, 0x30, 0x46, 0x02, 0x21, 0x00, + 0xd4, 0xce, 0xa5, 0xcc, 0x15, 0x91, 0x6e, 0xa9, 0x98, 0x77, 0xaa, 0xda, 0x65, 0xa0, 0xf6, 0xa0, 0xcc, 0xb1, 0xcc, 0x2c, + 0x26, 0x9f, 0xd0, 0x05, 0x17, 0x90, 0xed, 0x57, 0xb0, 0x2d, 0x59, 0xfb, 0x02, 0x21, 0x00, 0x8d, 0xc2, 0x5c, 0x85, 0xbb, + 0x13, 0x25, 0x8f, 0x8e, 0x6a, 0x9b, 0x81, 0x80, 0x5b, 0x13, 0xec, 0x2c, 0x2d, 0xc1, 0x3b, 0x14, 0x03, 0x19, 0x03, 0xdd, + 0x5c, 0xa8, 0x8e, 0x79, 0x5d, 0xa6, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_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, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, + 0x39, 0x35, 0x36, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, + 0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, + 0x88, 0x07, 0x03, 0x42, 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, + 0x81, 0xa1, 0x4e, 0xc5, 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, + 0x6c, 0xc4, 0xcd, 0x8c, 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, + 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, + 0x81, 0x1b, 0xed, 0x5a, 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, + 0x85, 0x7a, 0x2f, 0x65, 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, + 0xcb, 0xeb, 0xf7, 0x1c, 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, + 0xf5, 0xbe, 0x85, 0x40, 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x1c, 0x30, 0x82, 0x01, 0x18, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, + 0x30, 0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xa7, 0xb6, 0xd0, 0x7d, 0x38, 0x8c, 0x77, 0x1d, 0xa9, 0x57, 0x99, 0x8f, + 0x4b, 0x13, 0xca, 0x9d, 0x6d, 0xf7, 0x41, 0x3f, 0xd7, 0xa8, 0x7e, 0x53, 0x90, 0x53, 0x87, 0x4f, 0x9e, 0x23, 0xdb, 0x47, + 0x02, 0x20, 0x25, 0xe4, 0xca, 0x33, 0x86, 0x21, 0x65, 0xc2, 0x2a, 0xc7, 0x8d, 0x58, 0x36, 0x50, 0x07, 0xf3, 0x6b, 0x35, + 0x2e, 0xd5, 0x4d, 0x31, 0xa3, 0x87, 0x30, 0xf8, 0x72, 0x99, 0x39, 0x2a, 0xba, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * MARK: EC-signed messages (with attributes) + */ +unsigned char ec_sha1_attr[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x29, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x73, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x41, 0x69, 0x6e, 0x27, + 0x74, 0x20, 0x69, 0x74, 0x20, 0x70, 0x72, 0x65, 0x74, 0x74, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, + 0x82, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x50, 0x2b, + 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0xa6, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, + 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, + 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, + 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, + 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, 0x81, 0xa6, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, + 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, 0x68, + 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, + 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, 0x88, 0x07, 0x03, 0x42, + 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, 0x81, 0xa1, 0x4e, 0xc5, + 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, 0x6c, 0xc4, 0xcd, 0x8c, + 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, 0x13, 0x30, 0x11, 0x30, + 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x81, 0x1b, 0xed, 0x5a, + 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, 0x85, 0x7a, 0x2f, 0x65, + 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, 0xcb, 0xeb, 0xf7, 0x1c, + 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, 0xf5, 0xbe, 0x85, 0x40, + 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x76, 0x30, 0x82, 0x01, 0x72, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, 0x30, 0x81, 0xa6, 0x31, + 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x63, + 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, + 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, 0x70, 0x6c, + 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00, 0xa0, 0x5d, 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, 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, 0x09, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x27, 0xfc, 0x20, 0xc2, 0x9e, 0xf7, + 0x26, 0xa7, 0x9d, 0x78, 0x7e, 0xc6, 0x1c, 0xd6, 0x29, 0x90, 0x81, 0x6b, 0x17, 0x85, 0xac, 0x44, 0xb8, 0x56, 0x95, 0xe8, + 0x35, 0x12, 0x31, 0xde, 0xb1, 0x91, 0x02, 0x20, 0x08, 0xe0, 0xd4, 0x58, 0x0d, 0x79, 0x60, 0xc1, 0x20, 0x3b, 0x1c, 0x0c, + 0xda, 0x46, 0x91, 0x73, 0x21, 0x38, 0x77, 0xe8, 0x97, 0xe1, 0xa8, 0xe8, 0x2d, 0x38, 0xd2, 0xa3, 0x72, 0xfb, 0xe3, 0xa4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_sha256_attr[] = { + 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, 0x02, 0x57, 0x30, 0x82, 0x02, 0x53, 0x30, 0x82, 0x01, 0xf9, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x34, 0x30, 0x30, 0x31, + 0x39, 0x35, 0x36, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x33, 0x30, 0x30, 0x31, 0x39, 0x35, 0x36, 0x5a, 0x30, + 0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, + 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0x39, 0x79, 0x59, 0x3f, + 0x88, 0x07, 0x03, 0x42, 0x1a, 0x09, 0x93, 0x0d, 0xcd, 0x1b, 0x5a, 0xa7, 0x2f, 0x7d, 0x5f, 0xc2, 0x7b, 0xd9, 0x81, 0xb8, + 0x81, 0xa1, 0x4e, 0xc5, 0x36, 0xae, 0xc7, 0xe1, 0xa4, 0xf0, 0x0f, 0x4e, 0x75, 0x34, 0xbc, 0xb0, 0xc8, 0xf3, 0xe6, 0x87, + 0x6c, 0xc4, 0xcd, 0x8c, 0x8f, 0x1c, 0xbc, 0xb1, 0x16, 0x46, 0x22, 0x6f, 0xfa, 0x00, 0xfc, 0xac, 0x57, 0x65, 0xe1, 0xa3, + 0x13, 0x30, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, + 0x81, 0x1b, 0xed, 0x5a, 0x08, 0x6d, 0xdb, 0x89, 0xef, 0x27, 0x9b, 0x8d, 0xe6, 0x6f, 0xd0, 0x56, 0xfd, 0xb9, 0x33, 0xe4, + 0x85, 0x7a, 0x2f, 0x65, 0x39, 0x6c, 0x0d, 0xef, 0xd5, 0x82, 0xc9, 0x7d, 0x02, 0x20, 0x34, 0x18, 0xb8, 0xaf, 0xf2, 0x05, + 0xcb, 0xeb, 0xf7, 0x1c, 0x73, 0x77, 0x8d, 0x03, 0xcc, 0xc7, 0x80, 0x34, 0x44, 0x8f, 0x51, 0x6a, 0x6d, 0x80, 0x46, 0xce, + 0xf5, 0xbe, 0x85, 0x40, 0x5a, 0xdd, 0x31, 0x82, 0x01, 0x86, 0x30, 0x82, 0x01, 0x82, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaf, + 0x30, 0x81, 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x41, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, + 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x30, 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, 0x36, 0x30, 0x33, 0x31, + 0x38, 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, 0x09, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x76, 0x40, 0x7c, 0xf7, 0x6a, 0x21, + 0x2b, 0x45, 0x88, 0xb7, 0x3f, 0x90, 0x22, 0x80, 0x52, 0x36, 0x8b, 0x95, 0xf7, 0x79, 0x4c, 0xf8, 0x2d, 0x20, 0x48, 0x10, + 0xad, 0x0d, 0x59, 0x48, 0x50, 0xb0, 0x02, 0x20, 0x31, 0xa2, 0x19, 0x75, 0x17, 0xf3, 0x0b, 0x5f, 0x35, 0xf9, 0xac, 0xa2, + 0x7f, 0x50, 0x94, 0x9b, 0x08, 0x86, 0x40, 0xf9, 0x56, 0xdf, 0xdd, 0x0a, 0x6c, 0xdd, 0x7d, 0x67, 0xf0, 0xa5, 0x2d, 0x5a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * MARK: RSA encrypted + */ +unsigned char rsa_3DES[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, + 0x31, 0x82, 0x01, 0xcd, 0x30, 0x82, 0x01, 0xc9, 0x02, 0x01, 0x00, 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, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xd8, 0xc9, 0x64, 0x49, 0x02, 0x4b, 0x6c, 0x18, 0x92, 0x5b, 0x0a, + 0xcc, 0x8e, 0x2b, 0x81, 0xb8, 0x35, 0xff, 0x0e, 0x19, 0x92, 0x24, 0x4b, 0x7e, 0x40, 0x0e, 0xcb, 0x25, 0xee, 0x74, 0x2a, + 0x8c, 0xe5, 0xa2, 0xcf, 0xd7, 0xd3, 0x1d, 0x6e, 0xa2, 0x45, 0x98, 0x22, 0xf7, 0x7d, 0xd4, 0x2d, 0x35, 0x7e, 0x68, 0xb6, + 0xc6, 0x21, 0x84, 0x70, 0x50, 0xfb, 0x35, 0xe7, 0x41, 0xc6, 0x99, 0xc0, 0x91, 0x3e, 0x05, 0x30, 0x71, 0x7a, 0xb4, 0x12, + 0x32, 0x9f, 0x6a, 0x22, 0x35, 0x5e, 0x85, 0x12, 0x81, 0x0a, 0x28, 0x46, 0x79, 0xab, 0x0e, 0x87, 0xd5, 0xb8, 0x33, 0x0a, + 0xe0, 0x68, 0xfd, 0xd4, 0x3b, 0xd9, 0x01, 0xaa, 0xfb, 0xf3, 0x89, 0x78, 0x35, 0x55, 0x37, 0x72, 0x65, 0x54, 0xa6, 0xb5, + 0x44, 0x48, 0x82, 0xcc, 0xbe, 0x77, 0x56, 0x7c, 0xae, 0xb2, 0x49, 0x34, 0xb7, 0x8e, 0x86, 0xd0, 0xcb, 0xdc, 0x55, 0x1f, + 0xd0, 0xdf, 0x0c, 0x40, 0x7b, 0xef, 0xd9, 0x11, 0x76, 0x26, 0x2a, 0xa0, 0xcc, 0xf7, 0x7e, 0x2d, 0x8e, 0x3f, 0xfe, 0x1e, + 0xfd, 0x4e, 0x6f, 0xed, 0x0d, 0xe3, 0x5c, 0xc7, 0x8f, 0x3f, 0x44, 0xd7, 0xaa, 0xc4, 0xaf, 0x5a, 0xb6, 0xa8, 0xcb, 0xf9, + 0x18, 0x1d, 0xac, 0x99, 0x33, 0x64, 0xdc, 0x9c, 0x79, 0x70, 0xd1, 0x8e, 0xe1, 0x91, 0xe8, 0x4a, 0x9a, 0xd4, 0xbb, 0xd6, + 0x49, 0xaa, 0xe2, 0xc0, 0x37, 0x7e, 0x01, 0xf8, 0x79, 0xea, 0xaa, 0x3f, 0xcf, 0x00, 0xdb, 0xb6, 0x29, 0xa3, 0x01, 0x9a, + 0x5c, 0x51, 0x5e, 0x0a, 0x15, 0x61, 0x34, 0xf9, 0x15, 0x43, 0x2f, 0x4f, 0x0f, 0xc8, 0x87, 0xaf, 0x20, 0x71, 0xbb, 0x08, + 0x31, 0x09, 0x23, 0x87, 0xb3, 0x18, 0xaf, 0x5a, 0xfa, 0x09, 0x69, 0xcb, 0x1f, 0xca, 0x6c, 0xcd, 0x04, 0xe6, 0x64, 0xb1, + 0xfb, 0x17, 0x54, 0xb7, 0x29, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x14, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x40, 0x70, 0xf8, 0x8a, 0xcd, 0x13, 0xbe, 0xcf, + 0xa0, 0x80, 0x04, 0x20, 0x14, 0xf3, 0xb8, 0x0f, 0x06, 0xbc, 0x80, 0xf6, 0x20, 0xa2, 0x83, 0xb0, 0x45, 0x23, 0x5f, 0xc8, + 0xe1, 0xee, 0xb4, 0x04, 0x2d, 0xcb, 0x1e, 0xe9, 0x97, 0x33, 0x79, 0x56, 0x2b, 0x8c, 0x47, 0x99, 0x04, 0x08, 0x72, 0xe3, + 0x41, 0xa0, 0xe7, 0x71, 0x0a, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char rsa_RC2[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, + 0x31, 0x82, 0x01, 0xcd, 0x30, 0x82, 0x01, 0xc9, 0x02, 0x01, 0x00, 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, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xc4, 0x99, 0x34, 0xf9, 0x35, 0xb8, 0xf3, 0xc4, 0xae, 0x00, 0x1a, + 0x61, 0x88, 0xd1, 0x6f, 0xb9, 0x6e, 0x2d, 0x4e, 0x77, 0x58, 0xbf, 0x7c, 0x21, 0xb4, 0x85, 0xc3, 0x39, 0x84, 0xbd, 0x19, + 0x24, 0x73, 0x9b, 0x80, 0xdf, 0xcc, 0xc2, 0x8a, 0xc1, 0xa1, 0x20, 0xa2, 0xf5, 0x47, 0x9f, 0x36, 0x80, 0x4a, 0x5a, 0x69, + 0x1f, 0x0d, 0x3e, 0xf1, 0x68, 0x57, 0x12, 0x31, 0x59, 0x6a, 0xf4, 0xbd, 0x5d, 0x98, 0x94, 0xca, 0x96, 0x9c, 0xd7, 0x51, + 0xcd, 0x55, 0x44, 0x24, 0x57, 0x4c, 0xe7, 0x11, 0xb5, 0x53, 0x19, 0x79, 0x72, 0xda, 0x19, 0xc9, 0xbd, 0xae, 0x74, 0xc0, + 0xbe, 0x71, 0xa7, 0x62, 0x1a, 0xf9, 0x7f, 0x40, 0x2b, 0xf3, 0xdf, 0x15, 0x68, 0x89, 0xf0, 0xb8, 0x84, 0x96, 0x42, 0x0b, + 0x37, 0x26, 0x9a, 0x73, 0xd5, 0x47, 0x23, 0xf7, 0x3e, 0xfa, 0x5f, 0x91, 0xea, 0x82, 0x8f, 0x0c, 0x71, 0xa3, 0xdf, 0x6a, + 0x9a, 0xe1, 0xe6, 0xd3, 0xf9, 0x5a, 0xfc, 0x5d, 0x55, 0x95, 0x6e, 0xa9, 0x2f, 0xdf, 0x79, 0x06, 0x62, 0x0b, 0x55, 0x68, + 0xfc, 0x0f, 0xad, 0x2a, 0x34, 0x6e, 0xc8, 0xc3, 0x09, 0x68, 0x03, 0xba, 0xc2, 0x92, 0x13, 0x91, 0x50, 0x3d, 0xc4, 0x79, + 0xe9, 0x69, 0x2a, 0x25, 0x2a, 0x8f, 0x56, 0xce, 0xe6, 0x0f, 0xc5, 0x9e, 0x3f, 0xcc, 0x42, 0xb3, 0x27, 0xd5, 0xe8, 0x4b, + 0xba, 0x10, 0x33, 0xfb, 0x75, 0x67, 0x85, 0xa3, 0xc6, 0x93, 0xb1, 0xea, 0xfb, 0x8c, 0x4b, 0x25, 0x18, 0x24, 0xcf, 0x30, + 0xe9, 0x29, 0xde, 0x4a, 0xeb, 0xd3, 0xab, 0x3c, 0xf1, 0xfb, 0x57, 0x55, 0x30, 0xf0, 0xc0, 0x1e, 0x25, 0xbc, 0xe9, 0x1e, + 0x92, 0x73, 0xb6, 0xd5, 0xe3, 0xa3, 0xf6, 0x52, 0x72, 0x04, 0x96, 0x1e, 0x26, 0xda, 0x70, 0xb4, 0xba, 0x1c, 0xc4, 0xc4, + 0x76, 0xdd, 0x6d, 0xbc, 0x71, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x19, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02, 0x30, 0x0d, 0x02, 0x01, 0x3a, 0x04, 0x08, 0x15, 0xea, 0x8f, + 0x86, 0x56, 0x06, 0x50, 0x78, 0xa0, 0x80, 0x04, 0x20, 0xc8, 0x6c, 0x6c, 0xfb, 0x40, 0xcd, 0x3d, 0x23, 0x79, 0xba, 0x7e, + 0x40, 0xad, 0xa8, 0x01, 0x3b, 0x63, 0xdf, 0x29, 0xe0, 0x5e, 0x82, 0xfb, 0x20, 0x3c, 0x2b, 0xc1, 0x12, 0x57, 0xd0, 0x04, + 0xd2, 0x04, 0x08, 0x21, 0x53, 0x34, 0x58, 0x2e, 0x5a, 0xd3, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +unsigned char rsa_AES_128[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, + 0x31, 0x82, 0x01, 0xcd, 0x30, 0x82, 0x01, 0xc9, 0x02, 0x01, 0x00, 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, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x61, 0x0b, 0xaa, 0xa7, 0xce, 0xe7, 0x74, 0xe6, 0x13, 0x91, 0xf4, + 0x9f, 0x83, 0x2d, 0x85, 0xef, 0x23, 0x1b, 0x6a, 0x90, 0x2d, 0x03, 0x61, 0x60, 0xf6, 0xa0, 0xa3, 0x84, 0x43, 0x04, 0xdf, + 0x08, 0x7a, 0x10, 0xaf, 0x6d, 0x9e, 0x4e, 0x57, 0xf9, 0x59, 0xe2, 0x12, 0xc6, 0xbf, 0x30, 0x46, 0x27, 0x03, 0x74, 0x12, + 0x5e, 0x4a, 0xe9, 0xf0, 0xdb, 0x4c, 0xf5, 0x91, 0xaa, 0x87, 0xf4, 0x1a, 0x93, 0xc7, 0xde, 0xf1, 0xde, 0x56, 0x28, 0x5e, + 0x3f, 0x95, 0x8b, 0xb2, 0x02, 0x17, 0x91, 0x26, 0x0f, 0x60, 0x95, 0x56, 0xe9, 0xdd, 0x19, 0xdb, 0xfc, 0xba, 0x35, 0x02, + 0x15, 0x3e, 0xb4, 0x76, 0x6d, 0x11, 0xf6, 0xab, 0xb7, 0x06, 0x9c, 0x7a, 0xb2, 0xcd, 0xef, 0x01, 0xef, 0x17, 0x36, 0x39, + 0x44, 0x51, 0x55, 0xb8, 0xee, 0xf3, 0xea, 0xdd, 0x31, 0xea, 0x25, 0xa4, 0x5c, 0xc1, 0x24, 0xf0, 0xd1, 0x46, 0xbf, 0xba, + 0x9f, 0xc3, 0x9c, 0x82, 0xa9, 0x2a, 0x00, 0xad, 0x7f, 0xb3, 0xec, 0x37, 0x27, 0x3e, 0x35, 0x4b, 0xe9, 0xef, 0xab, 0x96, + 0x40, 0xeb, 0xc3, 0xf1, 0x06, 0xad, 0x43, 0x27, 0x58, 0x53, 0xee, 0xe9, 0x6f, 0x32, 0x00, 0x8a, 0xc1, 0x6e, 0x41, 0xc9, + 0x93, 0xe2, 0xc3, 0xec, 0xf5, 0xd6, 0x8c, 0xe6, 0x23, 0x0c, 0xa6, 0x69, 0x3d, 0x26, 0xd0, 0xff, 0xf0, 0xdd, 0xcc, 0x2c, + 0xe2, 0xac, 0xf4, 0x6c, 0xe2, 0xd8, 0x50, 0x50, 0xac, 0x18, 0x25, 0x41, 0x5b, 0xf2, 0xd7, 0xf6, 0x7e, 0xe4, 0x96, 0x78, + 0x34, 0x3b, 0x68, 0x05, 0x87, 0x65, 0x3c, 0x86, 0xfa, 0x7b, 0x71, 0xc4, 0xfd, 0x84, 0x91, 0x21, 0x5b, 0x2f, 0x14, 0x59, + 0x2b, 0x5e, 0xf6, 0x67, 0x4c, 0x54, 0x47, 0x04, 0xf0, 0x03, 0x6b, 0x58, 0x56, 0x44, 0x5b, 0x9e, 0xbc, 0x62, 0x0d, 0xcf, + 0x60, 0x62, 0xba, 0x86, 0x36, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02, 0x04, 0x10, 0xa9, 0x7a, 0x30, 0x37, 0x44, 0x04, 0x37, + 0x12, 0x9c, 0xa6, 0xc9, 0xbe, 0x97, 0x3f, 0x5a, 0x57, 0xa0, 0x80, 0x04, 0x20, 0xa6, 0x84, 0xcc, 0x53, 0x40, 0xb5, 0x96, + 0x19, 0x67, 0x3a, 0x52, 0xa2, 0x42, 0x88, 0xe8, 0xea, 0x57, 0xea, 0x72, 0xc1, 0x8d, 0x09, 0xed, 0x36, 0x87, 0xf8, 0xf8, + 0x79, 0x19, 0x94, 0x87, 0x51, 0x04, 0x10, 0x40, 0x40, 0x80, 0x6a, 0x65, 0x21, 0x00, 0xde, 0x95, 0xa9, 0xcd, 0xe8, 0xea, + 0x2e, 0xbc, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char rsa_AES_192[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, + 0x31, 0x82, 0x01, 0xcd, 0x30, 0x82, 0x01, 0xc9, 0x02, 0x01, 0x00, 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, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xb5, 0x1e, 0x33, 0xe7, 0x51, 0xaf, 0x12, 0xda, 0xed, 0x3c, 0x81, + 0x81, 0x0a, 0xfd, 0x7e, 0xe0, 0x6b, 0x11, 0x9d, 0xed, 0xca, 0x31, 0xd8, 0x43, 0xe9, 0x28, 0xd6, 0x47, 0x69, 0x81, 0x3d, + 0x69, 0x64, 0x3f, 0xa1, 0x41, 0x00, 0xa9, 0x90, 0x90, 0x8f, 0x90, 0x50, 0xad, 0xd7, 0x46, 0xe4, 0x5b, 0xf2, 0x81, 0x39, + 0xe3, 0xa0, 0x91, 0x21, 0x54, 0x10, 0xb6, 0x61, 0x4a, 0xb4, 0xdc, 0xf8, 0x4d, 0xbb, 0x48, 0x8c, 0x95, 0xac, 0x95, 0xb0, + 0x81, 0x59, 0xfa, 0xeb, 0xc2, 0x46, 0xd1, 0xf7, 0x02, 0xff, 0x4c, 0x9d, 0xc8, 0x9a, 0x1c, 0x10, 0xe5, 0x8a, 0x4c, 0xaf, + 0x6d, 0xa8, 0xe0, 0xdb, 0xfd, 0x52, 0x71, 0x1a, 0xc7, 0x1b, 0x8a, 0xc8, 0xf8, 0x29, 0x51, 0x51, 0xee, 0xfd, 0x73, 0x1b, + 0x13, 0xb4, 0xa1, 0xdc, 0x2a, 0x44, 0x25, 0x92, 0xd9, 0x16, 0xae, 0x7a, 0x89, 0x30, 0x92, 0xff, 0x7d, 0x4a, 0x8e, 0xe2, + 0xb7, 0xad, 0x92, 0xc9, 0xc9, 0x97, 0x7b, 0x71, 0x5a, 0x28, 0xbe, 0x80, 0x55, 0xc6, 0x61, 0xd4, 0x74, 0xdc, 0xca, 0x45, + 0x09, 0x3c, 0x4c, 0x4f, 0xe5, 0x5a, 0x0a, 0x5d, 0xe5, 0x07, 0xc0, 0x7c, 0x92, 0x4d, 0xca, 0x67, 0x94, 0x88, 0x56, 0x71, + 0x8d, 0xc8, 0xb3, 0x17, 0x2e, 0x11, 0x3b, 0xab, 0x33, 0xa1, 0x1a, 0xdb, 0x26, 0x2c, 0x72, 0x6f, 0xd5, 0x5b, 0xa7, 0x01, + 0x78, 0xae, 0xf6, 0x39, 0xa6, 0xbf, 0x34, 0xfb, 0xc3, 0xcc, 0xd5, 0xb0, 0xda, 0x2f, 0x8b, 0x0a, 0x54, 0x14, 0x2b, 0xd7, + 0xbb, 0x66, 0x4e, 0x3d, 0xd1, 0x26, 0x45, 0xa4, 0x01, 0xf3, 0xb3, 0x0a, 0x9f, 0xf7, 0x2b, 0xd7, 0x9b, 0x69, 0xc3, 0x36, + 0x58, 0x38, 0xec, 0xdf, 0xce, 0xa6, 0x66, 0xdb, 0xe3, 0xce, 0x2d, 0xcb, 0xd0, 0x40, 0xc3, 0x7a, 0xb4, 0xdf, 0x99, 0xb5, + 0xfc, 0x9c, 0x85, 0xb7, 0x69, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16, 0x04, 0x10, 0x48, 0xce, 0x27, 0x89, 0x24, 0xcc, 0x5e, + 0x2a, 0x56, 0x94, 0x8a, 0x5a, 0xb8, 0x94, 0xc0, 0x2a, 0xa0, 0x80, 0x04, 0x20, 0xcb, 0x2e, 0x26, 0xf5, 0x81, 0x51, 0xdd, + 0x9d, 0x5d, 0x65, 0x1b, 0x8c, 0xc5, 0x71, 0x44, 0x14, 0x14, 0x2d, 0x39, 0xf2, 0x7d, 0xfb, 0x93, 0x48, 0xb5, 0xf7, 0x5b, + 0xed, 0x75, 0xa3, 0xfb, 0x28, 0x04, 0x10, 0x6c, 0xfa, 0xab, 0x37, 0x9f, 0xbe, 0xae, 0x97, 0x58, 0x86, 0x55, 0x1d, 0x09, + 0xf8, 0x22, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char rsa_AES_256[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, + 0x31, 0x82, 0x01, 0xcd, 0x30, 0x82, 0x01, 0xc9, 0x02, 0x01, 0x00, 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, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xb6, 0x78, 0xdd, 0x6f, 0x1d, 0x43, 0x80, 0xed, 0x26, 0x31, 0xed, + 0x03, 0x60, 0xd7, 0x73, 0x86, 0xf6, 0x0a, 0x73, 0xa1, 0x15, 0xe5, 0xa5, 0x6b, 0xd4, 0xcf, 0x66, 0x64, 0xfb, 0x5b, 0xdc, + 0xc5, 0x40, 0x6b, 0xc8, 0x95, 0xcb, 0xad, 0xa6, 0x2a, 0x0d, 0xed, 0xfb, 0xb1, 0xd9, 0xff, 0xd2, 0xd4, 0x26, 0x61, 0xcc, + 0xc5, 0xbf, 0x2c, 0x87, 0x96, 0x1b, 0x12, 0xb0, 0x71, 0x7a, 0xc5, 0x1d, 0x93, 0x89, 0x14, 0x67, 0x8a, 0xa3, 0x58, 0xbb, + 0x75, 0xca, 0x61, 0x67, 0x09, 0xbb, 0x91, 0x55, 0x45, 0x55, 0xff, 0xff, 0xb6, 0xa9, 0x76, 0x93, 0xc2, 0x15, 0xc2, 0x37, + 0x21, 0x01, 0x98, 0x90, 0x82, 0x8a, 0x49, 0x1b, 0x7e, 0x79, 0x87, 0x3c, 0xbe, 0x03, 0xba, 0x80, 0xac, 0xa9, 0x3a, 0x90, + 0xf2, 0x85, 0xf5, 0xb7, 0x87, 0xa4, 0x20, 0x9f, 0x0f, 0xc4, 0x76, 0xce, 0x8c, 0x6a, 0x6d, 0x6a, 0xc1, 0x9a, 0xc1, 0x39, + 0xba, 0x6a, 0xdb, 0xe8, 0x63, 0xdb, 0xfd, 0xde, 0x65, 0x1c, 0x73, 0x73, 0xdd, 0x6a, 0x44, 0x17, 0x30, 0xe6, 0x5d, 0x35, + 0x1b, 0x48, 0xe3, 0x66, 0x87, 0xa7, 0x0c, 0x0f, 0xcc, 0xe0, 0x02, 0x9d, 0xb1, 0x0d, 0xe5, 0x3a, 0x34, 0x9f, 0x24, 0x15, + 0x71, 0x38, 0x21, 0xc2, 0x64, 0x26, 0x5a, 0x6e, 0x56, 0x60, 0x1b, 0x4b, 0xa7, 0x09, 0x7f, 0xc8, 0xb6, 0xcc, 0x3e, 0x6b, + 0x9d, 0x1e, 0x93, 0x28, 0x58, 0x79, 0xeb, 0x66, 0xbb, 0xf3, 0xa5, 0x5a, 0x85, 0xcd, 0x94, 0x55, 0x49, 0x48, 0xe6, 0x0b, + 0xde, 0x27, 0x97, 0xd3, 0xa7, 0xac, 0x43, 0x39, 0x9d, 0x0f, 0x82, 0x98, 0x2d, 0xbb, 0xef, 0x0f, 0xf0, 0xb6, 0x6a, 0xeb, + 0x46, 0xe0, 0x1e, 0xfb, 0x98, 0xfa, 0x5b, 0x7b, 0x7c, 0xb2, 0x67, 0x5e, 0x32, 0x00, 0x11, 0x9d, 0xe6, 0xed, 0x79, 0xd0, + 0xc6, 0x7a, 0xa5, 0x78, 0xf4, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a, 0x04, 0x10, 0xbc, 0x87, 0x6d, 0xcb, 0x49, 0xeb, 0x09, + 0x09, 0x2a, 0xb1, 0xe4, 0xd8, 0x90, 0x7a, 0xee, 0xec, 0xa0, 0x80, 0x04, 0x20, 0xc1, 0x71, 0xaf, 0xa6, 0xd4, 0x0a, 0xea, + 0xa7, 0xd2, 0x5e, 0x00, 0x62, 0x1d, 0x9d, 0x8c, 0xc2, 0x72, 0xba, 0x24, 0xbb, 0x54, 0xb8, 0x0d, 0xe7, 0xed, 0x83, 0x67, + 0xbb, 0xb8, 0x43, 0x93, 0x03, 0x04, 0x10, 0xae, 0x0f, 0xc0, 0xaf, 0x22, 0xab, 0xb8, 0x54, 0xbf, 0x88, 0xff, 0xef, 0x3c, + 0x8c, 0xd5, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * MARK: EC encrypted + */ +unsigned char ec_3DES[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, + 0x31, 0x82, 0x01, 0x6b, 0xa1, 0x82, 0x01, 0x67, 0x30, 0x82, 0x01, 0x63, 0x02, 0x01, 0x03, 0xa0, 0x55, 0xa1, 0x53, 0x30, + 0x51, 0x30, 0x0b, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x05, 0x00, 0x03, 0x42, 0x00, 0x04, 0x6e, 0x8e, + 0x7a, 0x5f, 0x8b, 0x92, 0x84, 0xea, 0x7a, 0x9c, 0x00, 0x25, 0xef, 0xba, 0xe1, 0x3c, 0x1e, 0x54, 0xcc, 0xfb, 0x8f, 0x4a, + 0xc4, 0xfe, 0x9f, 0x13, 0xaf, 0x7d, 0x19, 0x21, 0x31, 0x0a, 0xb6, 0x9f, 0xcd, 0x86, 0x4f, 0xac, 0x4e, 0x58, 0xa2, 0x43, + 0x41, 0xf2, 0x87, 0xd9, 0x09, 0x31, 0xaf, 0x52, 0xb7, 0x7d, 0x5e, 0xef, 0x94, 0xa6, 0x60, 0xb0, 0x90, 0x19, 0xd8, 0xd6, + 0x6d, 0xe4, 0xa1, 0x0a, 0x04, 0x08, 0xb3, 0x0f, 0xa8, 0x09, 0xbb, 0x40, 0x00, 0x2f, 0x30, 0x21, 0x06, 0x09, 0x2b, 0x81, + 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x02, 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, + 0x08, 0xa5, 0x6f, 0xb2, 0xab, 0xdc, 0x28, 0x07, 0xa3, 0x30, 0x81, 0xd7, 0x30, 0x81, 0xd4, 0x30, 0x81, 0xaf, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x04, 0x20, 0x25, 0x53, 0x52, 0x49, 0xc7, + 0x54, 0xfc, 0xb7, 0xc9, 0x45, 0x0a, 0x65, 0xd1, 0x2e, 0x74, 0x68, 0x82, 0x40, 0x0f, 0xf2, 0x23, 0x71, 0x3d, 0xfe, 0x1f, + 0x29, 0xcb, 0x8d, 0x3a, 0x3b, 0x31, 0x99, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x8d, 0xff, 0xae, 0x19, 0xfa, 0x5f, + 0xac, 0x17, 0xa0, 0x80, 0x04, 0x20, 0x21, 0x72, 0x77, 0x5a, 0x8c, 0xba, 0x15, 0xb7, 0x05, 0x4e, 0x05, 0x26, 0x12, 0xef, + 0x0a, 0xd8, 0x8b, 0x82, 0x09, 0x05, 0x4b, 0xd5, 0xdc, 0x9e, 0xd6, 0x83, 0x5c, 0xd0, 0xeb, 0xac, 0x96, 0x51, 0x04, 0x08, + 0xbc, 0x4c, 0x7a, 0x8b, 0xfe, 0xea, 0x75, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_RC2[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, + 0x31, 0x82, 0x01, 0x63, 0xa1, 0x82, 0x01, 0x5f, 0x30, 0x82, 0x01, 0x5b, 0x02, 0x01, 0x03, 0xa0, 0x55, 0xa1, 0x53, 0x30, + 0x51, 0x30, 0x0b, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x05, 0x00, 0x03, 0x42, 0x00, 0x04, 0xe7, 0x2b, + 0xa7, 0x9d, 0x50, 0xb8, 0x53, 0x3a, 0x9a, 0xb4, 0x96, 0x26, 0xff, 0x34, 0x1f, 0xad, 0xa8, 0x9f, 0xc7, 0xeb, 0x85, 0x4d, + 0x87, 0x2a, 0x52, 0xcf, 0xb7, 0x9b, 0xb2, 0x7e, 0x45, 0xa1, 0x32, 0x8e, 0x73, 0x46, 0xf8, 0x70, 0xa1, 0xe8, 0x2c, 0x85, + 0x05, 0x87, 0xe3, 0x60, 0xce, 0xcb, 0x10, 0xa7, 0x70, 0x7f, 0xde, 0x1c, 0x14, 0xfd, 0x37, 0x1b, 0xd5, 0x1c, 0xe9, 0x7e, + 0x04, 0xf0, 0xa1, 0x0a, 0x04, 0x08, 0x4d, 0xeb, 0x81, 0xb0, 0x6b, 0xab, 0x37, 0x97, 0x30, 0x21, 0x06, 0x09, 0x2b, 0x81, + 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x02, 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, + 0x08, 0x8b, 0x55, 0xd5, 0xac, 0x91, 0x46, 0xd4, 0xc1, 0x30, 0x81, 0xcf, 0x30, 0x81, 0xcc, 0x30, 0x81, 0xaf, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x04, 0x18, 0xad, 0x29, 0xc4, 0x57, 0x7e, + 0xc6, 0x8b, 0x25, 0xb9, 0x68, 0x67, 0x34, 0x6a, 0xda, 0xb6, 0x69, 0x3f, 0xa5, 0x83, 0x6c, 0x7d, 0xb7, 0x2f, 0x14, 0x30, + 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x19, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x03, 0x02, 0x30, 0x0d, 0x02, 0x01, 0x3a, 0x04, 0x08, 0xf2, 0x82, 0xe9, 0x5e, 0xcd, 0x8f, 0xe5, 0x24, 0xa0, + 0x80, 0x04, 0x20, 0x5b, 0x89, 0x81, 0xa2, 0x22, 0x48, 0x8c, 0x89, 0x71, 0xf3, 0x30, 0x7e, 0x9a, 0x22, 0x77, 0x1d, 0xee, + 0x78, 0x0e, 0x9a, 0x43, 0xe2, 0xe9, 0xf7, 0x9e, 0xae, 0xe3, 0xd8, 0xf5, 0x37, 0xeb, 0x74, 0x04, 0x08, 0xdf, 0x23, 0x14, + 0xd2, 0x65, 0xb3, 0xe3, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_AES_128[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, + 0x31, 0x82, 0x01, 0x63, 0xa1, 0x82, 0x01, 0x5f, 0x30, 0x82, 0x01, 0x5b, 0x02, 0x01, 0x03, 0xa0, 0x55, 0xa1, 0x53, 0x30, + 0x51, 0x30, 0x0b, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x05, 0x00, 0x03, 0x42, 0x00, 0x04, 0xd7, 0x78, + 0x2a, 0xf6, 0xce, 0x5e, 0xc4, 0x86, 0x08, 0x29, 0xa6, 0x71, 0xe3, 0x95, 0x64, 0x50, 0x29, 0x7d, 0x6c, 0xed, 0xcd, 0x50, + 0xb9, 0x00, 0x31, 0xa3, 0x22, 0x44, 0x68, 0x2b, 0x1b, 0x20, 0x16, 0x8b, 0x98, 0x06, 0x2a, 0xb6, 0xfc, 0x09, 0xba, 0x98, + 0x65, 0xfd, 0xc7, 0x22, 0x16, 0x53, 0xa2, 0xf0, 0x6e, 0xea, 0xc5, 0x1b, 0x52, 0x4a, 0x3c, 0xd7, 0x34, 0x87, 0x37, 0x10, + 0x79, 0x86, 0xa1, 0x0a, 0x04, 0x08, 0x3c, 0x7d, 0x8c, 0x77, 0xe5, 0x3a, 0x51, 0xa1, 0x30, 0x21, 0x06, 0x09, 0x2b, 0x81, + 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x02, 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, + 0x08, 0x2d, 0xae, 0x3c, 0xc8, 0x8e, 0x8c, 0xe8, 0xb2, 0x30, 0x81, 0xcf, 0x30, 0x81, 0xcc, 0x30, 0x81, 0xaf, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x04, 0x18, 0xa9, 0x8d, 0xfd, 0xd2, 0x2f, + 0x1b, 0xbf, 0x89, 0x5d, 0xbe, 0x34, 0x93, 0x69, 0xdb, 0x71, 0x0c, 0xd1, 0x86, 0x87, 0x3e, 0xb3, 0x4f, 0x9e, 0x19, 0x30, + 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x01, 0x02, 0x04, 0x10, 0xa3, 0x3d, 0x9e, 0x01, 0x59, 0xcd, 0x0f, 0xcb, 0xf5, 0x6e, 0xda, 0xa6, 0xc7, + 0xb1, 0x42, 0xec, 0xa0, 0x80, 0x04, 0x20, 0x1d, 0xbf, 0xbd, 0xea, 0x30, 0xac, 0xeb, 0x24, 0xc4, 0x52, 0xfc, 0x2e, 0x3b, + 0x95, 0x6c, 0x2b, 0xf4, 0x4b, 0xee, 0xf6, 0x7a, 0x52, 0x06, 0x1d, 0x89, 0x78, 0x6d, 0x62, 0x11, 0x4b, 0xdc, 0x35, 0x04, + 0x10, 0x77, 0x65, 0xaf, 0x79, 0x76, 0xa8, 0x6c, 0xc1, 0x32, 0x62, 0xc8, 0xde, 0xfe, 0x8a, 0xf4, 0xd1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_AES_192[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, + 0x31, 0x82, 0x01, 0x6b, 0xa1, 0x82, 0x01, 0x67, 0x30, 0x82, 0x01, 0x63, 0x02, 0x01, 0x03, 0xa0, 0x55, 0xa1, 0x53, 0x30, + 0x51, 0x30, 0x0b, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x05, 0x00, 0x03, 0x42, 0x00, 0x04, 0x6a, 0x3b, + 0xb5, 0x42, 0x6a, 0x4f, 0x29, 0x5c, 0x21, 0xe7, 0xd2, 0x6f, 0x41, 0x65, 0x72, 0x26, 0x7c, 0x99, 0xe2, 0xd3, 0x54, 0x60, + 0xbd, 0x92, 0xff, 0x4a, 0xa0, 0x00, 0xf7, 0xf2, 0x75, 0xd8, 0x10, 0xfd, 0xea, 0x93, 0x7d, 0x20, 0xa1, 0x21, 0xa6, 0x57, + 0x44, 0x45, 0x47, 0x8f, 0x90, 0x2f, 0xc9, 0x11, 0xf7, 0xb3, 0x7e, 0xbe, 0x61, 0x6a, 0xe9, 0x5f, 0xbe, 0xb4, 0x08, 0xbf, + 0x0f, 0x13, 0xa1, 0x0a, 0x04, 0x08, 0xbf, 0xe2, 0xbe, 0xa4, 0x54, 0x91, 0xbe, 0x0b, 0x30, 0x21, 0x06, 0x09, 0x2b, 0x81, + 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x02, 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, + 0x08, 0x5c, 0x40, 0xe0, 0x4e, 0x20, 0xbc, 0xb9, 0xed, 0x30, 0x81, 0xd7, 0x30, 0x81, 0xd4, 0x30, 0x81, 0xaf, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x04, 0x20, 0xcd, 0x66, 0x20, 0x4b, 0x82, + 0x06, 0x6a, 0x0b, 0x24, 0x94, 0xf6, 0x62, 0xcd, 0x5e, 0x61, 0x3e, 0xb1, 0x81, 0x2b, 0x39, 0xcf, 0xd8, 0x95, 0x71, 0x24, + 0x9b, 0xbe, 0xc2, 0x2e, 0x72, 0x5b, 0x2f, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, + 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16, 0x04, 0x10, 0x7c, 0xbc, 0x78, 0xc9, 0x75, + 0x2f, 0xb8, 0xdb, 0x78, 0xee, 0xcc, 0x90, 0x2b, 0x77, 0x19, 0xc3, 0xa0, 0x80, 0x04, 0x20, 0xa7, 0x18, 0x7f, 0x3b, 0x5c, + 0x99, 0xc7, 0x18, 0x57, 0xca, 0x51, 0xa8, 0x14, 0x34, 0xd3, 0x1f, 0x60, 0xb2, 0xfd, 0xdf, 0xcd, 0x33, 0x18, 0xd0, 0x41, + 0xc6, 0x0f, 0x88, 0x37, 0x3d, 0xc4, 0xb4, 0x04, 0x10, 0x9e, 0xdd, 0x92, 0x67, 0x60, 0xb1, 0x73, 0x20, 0xa4, 0xad, 0x15, + 0x80, 0x08, 0x50, 0xc8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +unsigned char ec_AES_256[] = { + 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x02, + 0x31, 0x82, 0x01, 0x73, 0xa1, 0x82, 0x01, 0x6f, 0x30, 0x82, 0x01, 0x6b, 0x02, 0x01, 0x03, 0xa0, 0x55, 0xa1, 0x53, 0x30, + 0x51, 0x30, 0x0b, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x05, 0x00, 0x03, 0x42, 0x00, 0x04, 0x51, 0xf6, + 0x31, 0x78, 0xba, 0x47, 0x10, 0xd3, 0xe7, 0x3e, 0x03, 0x47, 0x51, 0x40, 0xcd, 0xf1, 0x77, 0xbb, 0x80, 0x28, 0xba, 0x9e, + 0x85, 0x96, 0x67, 0x28, 0xb5, 0x41, 0xa3, 0xf0, 0x4d, 0x64, 0xef, 0x5c, 0xcb, 0xd7, 0x87, 0x49, 0x6d, 0xf1, 0xeb, 0xd7, + 0x70, 0xd5, 0xe9, 0xef, 0xf2, 0xfa, 0x13, 0xe0, 0xf8, 0xed, 0x36, 0xea, 0xaa, 0x77, 0xed, 0xcb, 0xfd, 0x5a, 0x24, 0x4f, + 0x47, 0xf1, 0xa1, 0x0a, 0x04, 0x08, 0xf6, 0x65, 0x06, 0x57, 0x1a, 0x33, 0x5f, 0x4d, 0x30, 0x21, 0x06, 0x09, 0x2b, 0x81, + 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x02, 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, + 0x08, 0x29, 0xe6, 0x26, 0xd9, 0x55, 0x3f, 0x80, 0x5d, 0x30, 0x81, 0xdf, 0x30, 0x81, 0xdc, 0x30, 0x81, 0xaf, 0x30, 0x81, + 0xa6, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x10, 0x43, 0x4d, 0x53, 0x20, 0x45, 0x43, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x25, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, + 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x75, 0x72, 0x65, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x40, 0x61, 0x70, + 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x04, 0x50, 0x2b, 0xa2, 0xa7, 0x04, 0x28, 0xbc, 0xbe, 0x49, 0x1e, 0xd3, + 0x65, 0xf5, 0xb5, 0xb9, 0x25, 0x25, 0xac, 0xa6, 0xcf, 0x99, 0x08, 0xe6, 0x36, 0x02, 0xf0, 0x33, 0xc0, 0x42, 0x9a, 0x5d, + 0x06, 0xde, 0x37, 0xd4, 0xf1, 0x51, 0x52, 0xab, 0xbb, 0xd2, 0xda, 0x07, 0x33, 0x86, 0x55, 0x30, 0x80, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, + 0x2a, 0x04, 0x10, 0x58, 0xf6, 0xd7, 0x84, 0xe2, 0xe6, 0x8f, 0x12, 0xe1, 0x81, 0xfb, 0xe9, 0x9f, 0x02, 0xf4, 0x5b, 0xa0, + 0x80, 0x04, 0x20, 0xf3, 0x04, 0x59, 0x33, 0x99, 0x87, 0x13, 0x67, 0xce, 0xcd, 0x8a, 0x35, 0x0f, 0x86, 0x3a, 0xa5, 0x95, + 0xae, 0x6f, 0x75, 0x77, 0xb0, 0x87, 0x63, 0xf9, 0xfc, 0x86, 0x5d, 0x30, 0xf4, 0xa8, 0xb8, 0x04, 0x10, 0x71, 0x74, 0x33, + 0x6a, 0x63, 0x01, 0x59, 0x32, 0xeb, 0x66, 0x9e, 0x46, 0x2d, 0x33, 0xbf, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +#endif /* cms_01_test_h */ diff --git a/OSX/libsecurity_smime/regressions/smime-cms-test.c b/OSX/libsecurity_smime/regressions/smime-cms-test.c index 6083a213..b2ad45e8 100644 --- a/OSX/libsecurity_smime/regressions/smime-cms-test.c +++ b/OSX/libsecurity_smime/regressions/smime-cms-test.c @@ -384,7 +384,7 @@ const uint8_t gkIPACCG2DevCertClass87 [] = }; // gkIPACCG2DevCertClass87 [] // Concatenated blob of 2 DER certificat -const uint8_t TestDoubleCerts [] = +const uint8_t TestDoubleCerts1 [] = { 0x30, 0x82, 0x01, 0xbe, 0x30, 0x82, 0x01, 0x27, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, @@ -423,7 +423,12 @@ const uint8_t TestDoubleCerts [] = 0x30, 0x0a, 0xff, 0xdb, 0x7a, 0x72, 0xf6, 0x89, 0x51, 0x01, 0x81, 0x3b, 0x97, 0x46, 0x99, 0x8a, 0x52, 0x42, 0xaf, 0x63, 0xa2, 0x1d, 0xc0, 0xae, 0x09, 0xa6, 0x6c, 0x7c, 0x7f, 0x93, 0xc7, 0xd0, 0x18, 0x97, 0x6b, 0x59, - 0xa9, 0x23, 0x84, 0x65, 0xf9, 0xfd, 0x30, 0x82, 0x01, 0xbf, 0x30, 0x82, + 0xa9, 0x23, 0x84, 0x65, 0xf9, 0xfd, +}; + +const uint8_t TestDoubleCerts2 [] = +{ + 0x30, 0x82, 0x01, 0xbf, 0x30, 0x82, 0x01, 0x28, 0x02, 0x02, 0x03, 0xe9, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x25, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a, 0x53, 0x65, @@ -462,7 +467,7 @@ const uint8_t TestDoubleCerts [] = 0xea, 0x9c, 0x85, 0xc9, 0x32, 0xde, 0xa9, 0x62, 0xcb, 0x3c, 0xb7, 0xbd, 0x8d, 0x16, 0xec, 0xcf, 0x52, 0x17, 0xc8, 0x47, 0x99, 0x94, 0xe1, 0x4c, 0x39 -}; // Test with 2certs [] +}; /* Basic processing of input */ @@ -490,6 +495,7 @@ static void tests(void) SecCertificateRef another_cert = NULL; + CFMutableArrayRef input_certs = NULL; // Process a single raw certificate and make it a message isnt(another_cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), @@ -499,29 +505,34 @@ static void tests(void) "SecCMSCertificatesOnlyMessageCopyCertificates"); is(CFArrayGetCount(certs), 1, "certificate count is 1"); - // Process two raw certificates (concatenated DER blobs) and make it a message - isnt(another_cert = SecCertificateCreateWithBytes(NULL, TestDoubleCerts, sizeof(TestDoubleCerts)), + // Process two raw certificates and make it a message + input_certs = CFArrayCreateMutable(NULL, 3, &kCFTypeArrayCallBacks); + isnt(another_cert = SecCertificateCreateWithBytes(NULL, TestDoubleCerts1, sizeof(TestDoubleCerts1)), NULL, "create certificate"); - ok(message = SecCMSCreateCertificatesOnlyMessageIAP(another_cert), "create iAP specific cert only message (2certs)"); + CFArrayAppendValue(input_certs, another_cert); + CFReleaseNull(another_cert); + isnt(another_cert = SecCertificateCreateWithBytes(NULL, TestDoubleCerts2, sizeof(TestDoubleCerts2)), + NULL, "create certificate"); + CFArrayAppendValue(input_certs, another_cert); + CFReleaseNull(another_cert); + + ok(message = SecCMSCreateCertificatesOnlyMessage(input_certs), "create cert only message (2certs)"); ok(certs = SecCMSCertificatesOnlyMessageCopyCertificates(message), "SecCMSCertificatesOnlyMessageCopyCertificates"); - // FIXME: SecCMSCreateCertificatesOnlyMessageIAP should be changed to take a CFArrayRef argument. - // Note that a SecCertificateRef can only contain the data of a single certificate. - // If the fix for rdar://17159227 is present, the message will only contain one certificate. count = (certs) ? CFArrayGetCount(certs) : 0; - ok(count > 0 && count < 3, "certificate count is 1 or 2"); + ok(count == 2, "certificate count is 2"); // Clean up CFReleaseNull(another_cert); CFReleaseNull(message); - + CFReleaseNull(input_certs); CFReleaseNull(certs); } int smime_cms_test(int argc, char *const *argv) { - plan_tests(12); + plan_tests(13); tests(); diff --git a/OSX/libsecurity_smime/regressions/smime_regressions.h b/OSX/libsecurity_smime/regressions/smime_regressions.h index 2d4d93c6..13843842 100644 --- a/OSX/libsecurity_smime/regressions/smime_regressions.h +++ b/OSX/libsecurity_smime/regressions/smime_regressions.h @@ -26,4 +26,5 @@ #include ONE_TEST(smime_cms_test) +ONE_TEST(cms_01_basic) diff --git a/OSX/libsecurity_ssl/config/base.xcconfig b/OSX/libsecurity_ssl/config/base.xcconfig index 28ce35c7..ae70ec41 100644 --- a/OSX/libsecurity_ssl/config/base.xcconfig +++ b/OSX/libsecurity_ssl/config/base.xcconfig @@ -6,7 +6,7 @@ CURRENT_PROJECT_VERSION = $(RC_ProjectSourceVersion) VERSIONING_SYSTEM = apple-generic; DEAD_CODE_STRIPPING = YES; -ARCHS = $(ARCHS_STANDARD_32_64_BIT) +ARCHS[sdk=macosx*] = $(ARCHS_STANDARD_32_64_BIT) // Debug symbols should be on obviously GCC_GENERATE_DEBUGGING_SYMBOLS = YES @@ -15,3 +15,4 @@ STRIP_STYLE = debugging STRIP_INSTALLED_PRODUCT = NO WARNING_CFLAGS = -Wglobal-constructors -Wno-deprecated-declarations $(inherited) +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_ssl/config/kext.xcconfig b/OSX/libsecurity_ssl/config/kext.xcconfig index 1cafefd5..ef36c7e2 100644 --- a/OSX/libsecurity_ssl/config/kext.xcconfig +++ b/OSX/libsecurity_ssl/config/kext.xcconfig @@ -26,4 +26,4 @@ GCC_WARN_UNUSED_VARIABLE = YES LINK_WITH_STANDARD_LIBRARIES = NO -SUPPORTED_PLATFORMS = macosx iphoneos +SUPPORTED_PLATFORMS = macosx iphoneos appletvos watchos diff --git a/OSX/libsecurity_ssl/config/lib.xcconfig b/OSX/libsecurity_ssl/config/lib.xcconfig index 700aa696..1cb93673 100644 --- a/OSX/libsecurity_ssl/config/lib.xcconfig +++ b/OSX/libsecurity_ssl/config/lib.xcconfig @@ -7,7 +7,7 @@ CODE_SIGN_IDENTITY = HEADER_SEARCH_PATHS[sdk=macosx*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../include $(BUILT_PRODUCTS_DIR)/derived_src $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_keychain/ $(PROJECT_DIR)/../libsecurity_keychain/libDER $(BUILT_PRODUCTS_DIR) $(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers $(inherited) -HEADER_SEARCH_PATHS[sdk=iphone*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_asn1 $(PROJECT_DIR)/../libsecurity_keychain/libDER $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include $(inherited) +HEADER_SEARCH_PATHS[sdk=embedded*] = $(PROJECT_DIR) $(PROJECT_DIR)/../regressions $(PROJECT_DIR)/../utilities $(PROJECT_DIR)/../libsecurity_asn1 $(PROJECT_DIR)/../libsecurity_keychain/libDER $(PROJECT_DIR)/../sec $(BUILT_PRODUCTS_DIR)/usr/local/include $(inherited) SKIP_INSTALL = YES @@ -25,6 +25,4 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES GCC_WARN_ABOUT_RETURN_TYPE = YES GCC_WARN_UNUSED_VARIABLE = YES -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator - -GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator diff --git a/OSX/libsecurity_ssl/config/tests.xcconfig b/OSX/libsecurity_ssl/config/tests.xcconfig index 21233a21..c09f5ab7 100644 --- a/OSX/libsecurity_ssl/config/tests.xcconfig +++ b/OSX/libsecurity_ssl/config/tests.xcconfig @@ -17,15 +17,8 @@ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES GCC_WARN_ABOUT_RETURN_TYPE = YES GCC_WARN_UNUSED_VARIABLE = YES -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator -GCC_PREPROCESSOR_DEFINITIONS[sdk=iphonesimulator*] = INDIGO=1 $(inherited) - -#include "/AppleInternal/XcodeConfig/SimulatorSupport.xcconfig" - -// Set INSTALL_PATH_ACTUAL to whatever INSTALL_PATH would normally be -INSTALL_PATH_ACTUAL = /usr/local/bin - -// Set INSTALL_PATH[sdk=macosx*] when SimulatorSupport.xcconfig is unavailable -INSTALL_PATH[sdk=macosx*] = $(INSTALL_PATH_ACTUAL) +INSTALL_PATH = /usr/local/bin +HEADER_SEARCH_PATHS = $(PROJECT_DIR)/../utilities $(inherited) diff --git a/OSX/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c b/OSX/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c deleted file mode 100644 index 304df3b7..00000000 --- a/OSX/libsecurity_ssl/dtlsEcho/dtlsEchoClient.c +++ /dev/null @@ -1,310 +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 "../sslViewer/sslAppUtils.h" - -#include -#include -#include -#include -#include -#include -#include -#include /* close() */ -#include /* memset() */ -#include -#include - -#ifdef NO_SERVER -#include -#endif - -#include "ssl-utils.h" - -#define SERVER "127.0.0.1" -//#define SERVER "17.201.58.114" -#define PORT 23232 -#define BUFLEN 128 -#define COUNT 10 - -#if 0 -static void dumppacket(const unsigned char *data, unsigned long len) -{ - unsigned long i; - for(i=0;i0) { - readOff=0; - readLeft=(size_t) len; - printf("SocketRead: %ld bytes... epoch: %02x seq=%02x%02x\n", - len, d[4], d[9], d[10]); - - } else { - int theErr = errno; - switch(theErr) { - case EAGAIN: - //printf("SocketRead: EAGAIN\n"); - *dataLength=0; - /* nonblocking, no data */ - return errSSLWouldBlock; - default: - perror("SocketRead"); - return errSecIO; - } - } - } - - if(readLeft<*dataLength) { - *dataLength=readLeft; - } - - memcpy(data, readBuffer+readOff, *dataLength); - readLeft-=*dataLength; - readOff+=*dataLength; - - return errSecSuccess; - -} - -static -OSStatus SocketWrite( - SSLConnectionRef connection, - const void *data, - size_t *dataLength) /* IN/OUT */ -{ - int fd = (int)connection; - ssize_t len; - OSStatus err = errSecSuccess; - const uint8_t *d=data; - -#if 0 - if((rand()&3)==1) { - - /* drop 1/8th packets */ - printf("SocketWrite: Drop %ld bytes... epoch: %02x seq=%02x%02x\n", - *dataLength, d[4], d[9], d[10]); - return errSecSuccess; - - } -#endif - - len = send(fd, data, *dataLength, 0); - - if(len>0) { - *dataLength=(size_t)len; - printf("SocketWrite: Sent %ld bytes... epoch: %02x seq=%02x%02x\n", - len, d[4], d[9], d[10]); - return err; - } - - int theErr = errno; - switch(theErr) { - case EAGAIN: - /* nonblocking, no data */ - err = errSSLWouldBlock; - break; - default: - perror("SocketWrite"); - err = errSecIO; - break; - } - - return err; - -} - - -int main(int argc, char **argv) -{ - int fd; - struct sockaddr_in sa; - - if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) { - perror("socket"); - exit(-1); - } - -#ifdef NO_SERVER -# if DEBUG - securityd_init(); -# endif -#endif - - memset((char *) &sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(PORT); - if (inet_aton(SERVER, &sa.sin_addr)==0) { - fprintf(stderr, "inet_aton() failed\n"); - exit(1); - } - - time_t seed=time(NULL); -// time_t seed=1298952499; - srand((unsigned)seed); - printf("Random drop initialized with seed = %lu\n", seed); - - if(connect(fd, (struct sockaddr *)&sa, sizeof(sa))==-1) - { - perror("connect"); - return errno; - } - - /* Change to non blocking io */ - fcntl(fd, F_SETFL, O_NONBLOCK); - - SSLConnectionRef c=(SSLConnectionRef)(intptr_t)fd; - - - OSStatus ortn; - SSLContextRef ctx = NULL; - - SSLClientCertificateState certState; - SSLCipherSuite negCipher; - SSLProtocol negVersion; - - /* - * Set up a SecureTransport session. - */ - ortn = SSLNewDatagramContext(false, &ctx); - if(ortn) { - printSslErrStr("SSLNewDatagramContext", ortn); - return ortn; - } - ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); - if(ortn) { - printSslErrStr("SSLSetIOFuncs", ortn); - return ortn; - } - - ortn = SSLSetConnection(ctx, c); - if(ortn) { - printSslErrStr("SSLSetConnection", ortn); - return ortn; - } - - ortn = SSLSetMaxDatagramRecordSize(ctx, 400); - if(ortn) { - printSslErrStr("SSLSetMaxDatagramRecordSize", ortn); - return ortn; - } - - /* Lets not verify the cert, which is a random test cert */ - ortn = SSLSetEnableCertVerify(ctx, false); - if(ortn) { - printSslErrStr("SSLSetEnableCertVerify", ortn); - return ortn; - } - - ortn = SSLSetCertificate(ctx, server_chain()); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - return ortn; - } - - do { - ortn = SSLHandshake(ctx); - if(ortn == errSSLWouldBlock) { - /* keep UI responsive */ - sslOutputDot(); - } - } while (ortn == errSSLWouldBlock); - - - SSLGetClientCertificateState(ctx, &certState); - SSLGetNegotiatedCipher(ctx, &negCipher); - SSLGetNegotiatedProtocolVersion(ctx, &negVersion); - - int count; - size_t len, readLen, writeLen; - char buffer[BUFLEN]; - - count = 0; - while(count -#include - -#include "../sslViewer/sslAppUtils.h" - -#include -#include -#include -#include -#include -#include -#include -#include /* close() */ -#include /* memset() */ -#include -#include - -#ifdef NO_SERVER -#include -#endif - -#define PORT 23232 - -#include "ssl-utils.h" - -static void dumppacket(const unsigned char *data, unsigned long len) -{ - unsigned long i; - for(i=0;i0) { - readOff=0; - readLeft=(size_t) len; - printf("SocketRead: %ld bytes... epoch: %02x seq=%02x%02x\n", - len, d[4], d[9], d[10]); - } else { - int theErr = errno; - switch(theErr) { - case EAGAIN: - // printf("SocketRead: EAGAIN\n"); - *dataLength=0; - /* nonblocking, no data */ - return errSSLWouldBlock; - default: - perror("SocketRead"); - return errSecIO; - } - } - } - - if(readLeft<*dataLength) { - *dataLength=readLeft; - } - - memcpy(data, readBuffer+readOff, *dataLength); - readLeft-=*dataLength; - readOff+=*dataLength; - - - return errSecSuccess; - -} - - -static -OSStatus SocketWrite( - SSLConnectionRef connection, - const void *data, - size_t *dataLength) /* IN/OUT */ -{ - int fd = (int)connection; - ssize_t len; - OSStatus err = errSecSuccess; - const uint8_t *d=data; - -#if 1 - if((rand()&3)==1) { - /* drop 1/8 packets */ - printf("SocketWrite: Drop %ld bytes... epoch: %02x seq=%02x%02x\n", - *dataLength, d[4], d[9], d[10]); - return errSecSuccess; - } -#endif - - len = send(fd, data, *dataLength, 0); - - if(len>0) { - *dataLength=(size_t)len; - - printf("SocketWrite: Sent %ld bytes... epoch: %02x seq=%02x%02x\n", - len, d[4], d[9], d[10]); - - return err; - } - - int theErr = errno; - switch(theErr) { - case EAGAIN: - /* nonblocking, no data */ - err = errSSLWouldBlock; - break; - default: - perror("SocketWrite"); - err = errSecIO; - break; - } - - return err; - -} - - -int main(int argc, char **argv) -{ - struct sockaddr_in sa; /* server address for bind */ - struct sockaddr_in ca; /* client address for connect */ - int fd; - ssize_t l; - -#ifdef NO_SERVER -# if DEBUG - securityd_init(); -# endif -#endif - - if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1) { - perror("socket"); - return errno; - } - - time_t seed=time(NULL); -// time_t seed=1298952496; - srand((unsigned)seed); - printf("Random drop initialized with seed = %lu\n", seed); - - memset((char *) &sa, 0, sizeof(sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons(PORT); - sa.sin_addr.s_addr = htonl(INADDR_ANY); - - if(bind (fd, (struct sockaddr *)&sa, sizeof(sa))==-1) - { - perror("bind"); - return errno; - } - - printf("Waiting for first packet...\n"); - /* PEEK only... */ - socklen_t slen=sizeof(ca); - char b; - if((l=recvfrom(fd, &b, 1, MSG_PEEK, (struct sockaddr *)&ca, &slen))==-1) - { - perror("recvfrom"); - return errno; - } - - printf("Received packet from %s (%ld), connecting...\n", inet_ntoa(ca.sin_addr), l); - - if(connect(fd, (struct sockaddr *)&ca, sizeof(ca))==-1) - { - perror("connect"); - return errno; - } - - /* Change to non blocking */ - fcntl(fd, F_SETFL, O_NONBLOCK); - - - SSLConnectionRef c=(SSLConnectionRef)(intptr_t)fd; - - - OSStatus ortn; - SSLContextRef ctx = NULL; - - SSLClientCertificateState certState; - SSLCipherSuite negCipher; - - /* - * Set up a SecureTransport session. - */ - ortn = SSLNewDatagramContext(true, &ctx); - if(ortn) { - printSslErrStr("SSLNewDatagramContext", ortn); - return ortn; - } - - ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); - if(ortn) { - printSslErrStr("SSLSetIOFuncs", ortn); - return ortn; - } - - ortn = SSLSetConnection(ctx, c); - if(ortn) { - printSslErrStr("SSLSetConnection", ortn); - return ortn; - } - - ortn = SSLSetDatagramHelloCookie(ctx, &ca, 32); - if(ortn) { - printSslErrStr("SSLSetDatagramHelloCookie", ortn); - return ortn; - } - - ortn = SSLSetMaxDatagramRecordSize(ctx, 400); - if(ortn) { - printSslErrStr("SSLSetMaxDatagramRecordSize", ortn); - return ortn; - } - - /* Lets not verify the cert, which is a random test cert */ - ortn = SSLSetEnableCertVerify(ctx, false); - if(ortn) { - printSslErrStr("SSLSetEnableCertVerify", ortn); - return ortn; - } - - ortn = SSLSetCertificate(ctx, server_chain()); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - return ortn; - } - - ortn = SSLSetClientSideAuthenticate(ctx, kAlwaysAuthenticate); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - return ortn; - } - - printf("Server Handshake...\n"); - do { - ortn = SSLHandshake(ctx); - if(ortn == errSSLWouldBlock) { - /* keep UI responsive */ - sslOutputDot(); - } - } while (ortn == errSSLWouldBlock); - - if(ortn) { - printSslErrStr("SSLHandshake", ortn); - return ortn; - } - - SSLGetClientCertificateState(ctx, &certState); - SSLGetNegotiatedCipher(ctx, &negCipher); - - printf("Server Handshake done. Cipher is %s\n", sslGetCipherSuiteString(negCipher)); - - unsigned char buffer[MTU]; - size_t len, readLen; - - while(1) { - while((ortn=SSLRead(ctx, buffer, MTU, &readLen))==errSSLWouldBlock); - if(ortn) { - printSslErrStr("SSLRead", ortn); - break; - } - buffer[readLen]=0; - printf("Received %lu bytes:\n", readLen); - dumppacket(buffer, readLen); - - ortn=SSLWrite(ctx, buffer, readLen, &len); - if(ortn) { - printSslErrStr("SSLRead", ortn); - break; - } - printf("Echoing %lu bytes\n", len); - } - - SSLDisposeContext(ctx); - - return ortn; -} diff --git a/OSX/libsecurity_ssl/lib/SSLRecordInternal.c b/OSX/libsecurity_ssl/lib/SSLRecordInternal.c index 9b000871..8e494509 100644 --- a/OSX/libsecurity_ssl/lib/SSLRecordInternal.c +++ b/OSX/libsecurity_ssl/lib/SSLRecordInternal.c @@ -28,7 +28,6 @@ #include "SSLRecordInternal.h" #include "sslDebug.h" #include "cipherSpecs.h" -#include "sslUtils.h" #include "tls_record_internal.h" #include @@ -136,6 +135,7 @@ static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec) tls_record_parse_header(ctx->filter, header, &contentLen, &content_type); if(content_type&0x80) { + sslDebugLog("Detected SSL2 record in SSLReadRecordInternal"); // Looks like SSL2 record, reset expectations. head = 2; err=tls_record_parse_ssl2_header(ctx->filter, header, &contentLen, &content_type); @@ -144,17 +144,23 @@ static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec) check(ctx->partialReadBuffer.length>=head+contentLen); - if(head+contentLen>ctx->partialReadBuffer.length) + if(head+contentLen>ctx->partialReadBuffer.length) { + sslDebugLog("overflow in SSLReadRecordInternal"); return errSSLRecordRecordOverflow; + } if (ctx->amountRead < head + contentLen) - { readData.length = head + contentLen - ctx->amountRead; + { + readData.length = head + contentLen - ctx->amountRead; readData.data = ctx->partialReadBuffer.data + ctx->amountRead; len = readData.length; err = sslIoRead(readData, &len, ctx); if(err != 0) - { if (err == errSSLRecordWouldBlock) - ctx->amountRead += len; + { + if (err == errSSLRecordWouldBlock) + { + ctx->amountRead += len; + } return err; } ctx->amountRead += len; @@ -179,7 +185,7 @@ static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec) /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */ if(sz==0) { sslErrorLog("underflow in SSLReadRecordInternal"); - if(ctx->dtls) { + if(ctx->sslCtx->isDTLS) { // For DTLS, we should just drop it. return errSSLRecordUnexpectedRecord; } else { diff --git a/OSX/libsecurity_ssl/lib/SecureTransport.h b/OSX/libsecurity_ssl/lib/SecureTransport.h index 061ae594..89afee8c 100644 --- a/OSX/libsecurity_ssl/lib/SecureTransport.h +++ b/OSX/libsecurity_ssl/lib/SecureTransport.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2002,2005-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 1999-2002,2005-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -147,6 +147,10 @@ typedef CF_ENUM(int, SSLSessionOption) { * Set this option to break from a client hello in order to check for SNI */ kSSLSessionOptionBreakOnClientHello = 7, + /* + * Set this option to Allow renegotations. False by default. + */ + kSSLSessionOptionAllowRenegotiation = 8, }; @@ -171,13 +175,13 @@ typedef CF_ENUM(int, SSLClientCertificateState) { /* * Server side: We asked for a cert, client sent one, we validated * it OK. App can inspect the cert via - * SSLGetPeerCertificates(). + * SSLCopyPeerCertificates(). * Client side: server asked for one, we sent it. */ kSSLClientCertSent, /* * Client sent a cert but failed validation. Server side only. - * Server app can inspect the cert via SSLGetPeerCertificates(). + * Server app can inspect the cert via SSLCopyPeerCertificates(). */ kSSLClientCertRejected } ; @@ -303,6 +307,31 @@ typedef CF_ENUM(int, SSLConnectionType) kSSLDatagramType }; +/* + * Predefined TLS configurations constants + */ + +/* Default configuration - currently same as kSSLSessionConfig_standard */ +extern const CFStringRef kSSLSessionConfig_default; +/* ATS v1 Config: TLS v1.2, only PFS ciphersuites */ +extern const CFStringRef kSSLSessionConfig_ATSv1; +/* ATS v1 Config without PFS: TLS v1.2, include non PFS ciphersuites */ +extern const CFStringRef kSSLSessionConfig_ATSv1_noPFS; +/* TLS v1.2 to TLS v1.0, with default ciphersuites (no RC4) */ +extern const CFStringRef kSSLSessionConfig_standard; +/* TLS v1.2 to TLS v1.0, with defaults ciphersuites + RC4 */ +extern const CFStringRef kSSLSessionConfig_RC4_fallback; +/* TLS v1.0 only, with defaults ciphersuites + fallback SCSV */ +extern const CFStringRef kSSLSessionConfig_TLSv1_fallback; +/* TLS v1.0, with defaults ciphersuites + RC4 + fallback SCSV */ +extern const CFStringRef kSSLSessionConfig_TLSv1_RC4_fallback; +/* TLS v1.2 to TLS v1.0, defaults + RC4 + DHE ciphersuites */ +extern const CFStringRef kSSLSessionConfig_legacy; +/* TLS v1.2 to TLS v1.0, defaults + RC4 + DHE ciphersuites */ +extern const CFStringRef kSSLSessionConfig_legacy_DHE; +/* TLS v1.2, anonymous ciphersuites only */ +extern const CFStringRef kSSLSessionConfig_anonymous; + /****************** *** Public API *** @@ -410,6 +439,19 @@ SSLSetIOFuncs (SSLContextRef context, SSLWriteFunc writeFunc) __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_5_0); + +/* + * Set a predefined configuration for the SSL Session + * + * This currently affect enabled protocol versions, + * enabled ciphersuites, and the kSSLSessionOptionFallback + * session option. + */ +OSStatus +SSLSetSessionConfig(SSLContextRef context, + CFStringRef config) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); + /* * Set the minimum SSL protocol version allowed. Optional. * The default is the lower supported protocol. @@ -444,13 +486,13 @@ SSLGetProtocolVersionMin (SSLContextRef context, * * This can only be called when no session is active. * - * For TLS contexts, legal values for minVersion are : + * For TLS contexts, legal values for maxVersion are : * kSSLProtocol3 * kTLSProtocol1 * kTLSProtocol11 * kTLSProtocol12 * - * For DTLS contexts, legal values for minVersion are : + * For DTLS contexts, legal values for maxVersion are : * kDTLSProtocol1 */ OSStatus @@ -576,7 +618,7 @@ SSLGetProtocolVersion (SSLContextRef context, */ OSStatus SSLSetCertificate (SSLContextRef context, - CFArrayRef certRefs) + CFArrayRef _Nullable certRefs) __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_5_0); /* @@ -629,6 +671,25 @@ SSLGetPeerDomainName (SSLContextRef context, size_t *peerNameLen) // IN/OUT __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_5_0); + +/* + * Determine the buffer size needed for SSLCopyRequestedPeerNameLength(). + */ +OSStatus +SSLCopyRequestedPeerName (SSLContextRef context, + char *peerName, + size_t *peerNameLen) + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); + +/* + * Server Only: obtain the hostname specified by the client in the ServerName extension (SNI) + */ +OSStatus +SSLCopyRequestedPeerNameLength (SSLContextRef ctx, + size_t *peerNameLen) + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); + + /* * Specify the Datagram TLS Hello Cookie. * This is to be called for server side only and is optional. @@ -719,19 +780,6 @@ SSLGetEnabledCiphers (SSLContextRef context, __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_5_0); -/* Deprecated, does nothing */ -typedef CF_ENUM(int, SSLSessionStrengthPolicy) -{ - kSSLSessionStrengthPolicyDefault, - kSSLSessionStrengthPolicyATSv1, - kSSLSessionStrengthPolicyATSv1_noPFS, -}; - -OSStatus -SSLSetSessionStrengthPolicy(SSLContextRef context, - SSLSessionStrengthPolicy policyStrength); - - #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) /* * Enable/disable peer certificate chain validation. Default is enabled. @@ -1298,6 +1346,17 @@ OSStatus SSLHandshake (SSLContextRef context) __OSX_AVAILABLE_STARTING(__MAC_10_2, __IPHONE_5_0); +/* + * Server Only: Request renegotation. + * This will return an error if the server is already renegotiating, or if the session is closed. + * After this return without error, the application should call SSLHandshake() and/or SSLRead() as + * for the original handshake. + */ +OSStatus +SSLReHandshake (SSLContextRef context) + __OSX_AVAILABLE_STARTING(__MAC_10_12, __IPHONE_10_0); + + /* * Normal application-level read/write. On both of these, a errSSLWouldBlock * return and a partially completed transfer - or even zero bytes transferred - diff --git a/OSX/libsecurity_ssl/lib/SecureTransportPriv.h b/OSX/libsecurity_ssl/lib/SecureTransportPriv.h index 703a8e74..66f8b845 100644 --- a/OSX/libsecurity_ssl/lib/SecureTransportPriv.h +++ b/OSX/libsecurity_ssl/lib/SecureTransportPriv.h @@ -146,6 +146,7 @@ SSLGetClientSideAuthenticate ( SSLContextRef context, SSLAuthenticate *auth); // RETURNED +#if !TARGET_OS_IPHONE /* * Get/set array of trusted leaf certificates. * @@ -161,7 +162,7 @@ OSStatus SSLCopyTrustedLeafCertificates ( SSLContextRef context, CFArrayRef *certRefs); // RETURNED, caller must release - +#endif /* * Get/set enable of anonymous ciphers. This is deprecated and now a no-op. */ @@ -375,10 +376,10 @@ extern OSStatus SSLGetClientAuthTypes( unsigned *numTypes); /* IN/OUT */ /* - * Obtain the SSLClientAuthenticationType actually performed. - * Only valid if client certificate state is kSSLClientCertSent - * or kSSLClientCertRejected; SSLClientAuthNone is returned as - * the negotiated auth type otherwise. + * -- DEPRECATED -- + * This is not actually useful. Currently return errSecUnimplemented. + * The client auth type is fully determined by the type of private key used by + * the client. */ extern OSStatus SSLGetNegotiatedClientAuthType( SSLContextRef ctx, @@ -440,25 +441,6 @@ OSStatus SSLSetDHEEnabled(SSLContextRef ctx, bool enabled); OSStatus SSLGetDHEEnabled(SSLContextRef ctx, bool *enabled); -extern const CFStringRef kSSLSessionConfig_default; -extern const CFStringRef kSSLSessionConfig_ATSv1; -extern const CFStringRef kSSLSessionConfig_ATSv1_noPFS; -extern const CFStringRef kSSLSessionConfig_legacy; -extern const CFStringRef kSSLSessionConfig_standard; -extern const CFStringRef kSSLSessionConfig_RC4_fallback; -extern const CFStringRef kSSLSessionConfig_TLSv1_fallback; -extern const CFStringRef kSSLSessionConfig_TLSv1_RC4_fallback; -extern const CFStringRef kSSLSessionConfig_legacy_DHE; - -OSStatus -SSLSetSessionConfig(SSLContextRef context, - CFStringRef config); - -OSStatus -SSLGetSessionConfig(SSLContextRef context, - CFStringRef *config); - - #if TARGET_OS_IPHONE /* Following are SPIs on iOS */ @@ -843,16 +825,6 @@ SSLGetALPNData (SSLContextRef context, // end of ALPN -OSStatus -SSLCopyRequestedPeerName (SSLContextRef context, - char *peerName, - size_t *peerNameLen); - -OSStatus -SSLCopyRequestedPeerNameLength (SSLContextRef ctx, - size_t *peerNameLen); - - #ifdef __cplusplus } #endif diff --git a/OSX/libsecurity_ssl/lib/appleSession.c b/OSX/libsecurity_ssl/lib/appleSession.c deleted file mode 100644 index 941a473b..00000000 --- a/OSX/libsecurity_ssl/lib/appleSession.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2008,2010-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@ - */ - -/* - * appleSession.c - Session storage module, Apple CDSA version. - */ - -/* - * The current implementation stores sessions in a linked list, a member of a - * SessionCache object for which we keep a single global instance. It is - * expected that at a given time, only a small number of sessions will be - * cached, so the random insertion access provided by a map<> is unnecessary. - * New entries are placed in the head of the list, assuming a LIFO usage - * tendency. - * - * Entries in this cache have a time to live of SESSION_CACHE_TTL, currently - * ten minutes. Entries are tested for being stale upon lookup; also, the global - * sslCleanupSession() tests all entries in the cache, deleting entries which - * are stale. This function is currently called whenever an SSLContext is deleted. - * The current design does not provide any asynchronous timed callouts to perform - * further cache cleanup; it was decided that the thread overhead of this would - * outweight the benefits (again assuming a small number of entries in the - * cache). - * - * When a session is added via sslAddSession, and a cache entry already - * exists for the specifed key (sessionID), the sessionData for the existing - * cache entry is updated with the new sessionData. The entry's expiration - * time is unchanged (thus a given session entry can only be used for a finite - * time no mattter how often it is re-used), - */ - -#include "ssl.h" -#include "sslMemory.h" -#include "sslDebug.h" -#include "appleSession.h" - -#include -#include -#include - -#include - -/* default time-to-live in cache, in seconds */ -#define QUICK_CACHE_TEST 0 -#if QUICK_CACHE_TEST -#define SESSION_CACHE_TTL ((CFTimeInterval)5) -#else -#define SESSION_CACHE_TTL ((CFTimeInterval)(10 * 60)) -#endif /* QUICK_CACHE_TEST */ - -#define CACHE_PRINT 0 -#if CACHE_PRINT -#define DUMP_ALL_CACHE 0 - -static void cachePrint( - const void *entry, - const SSLBuffer *key, - const SSLBuffer *data) -{ - printf("entry: %p ", entry); - unsigned char *kd = key->data; - if(data != NULL) { - unsigned char *dd = data->data; - printf(" key: %02X%02X%02X%02X%02X%02X%02X%02X" - " data: %02X%02X%02X%02X... (len %d)\n", - kd[0],kd[1],kd[2],kd[3], kd[4],kd[5],kd[6],kd[7], - dd[0],dd[1],dd[2],dd[3], (unsigned)data->length); - } - else { - /* just print key */ - printf(" key: %02X%02X%02X%02X%02X%02X%02X%02X\n", - kd[0],kd[1],kd[2],kd[3], kd[4],kd[5],kd[6],kd[7]); - } -} -#else /* !CACHE_PRINT */ -#define cachePrint(e, k, d) -#define DUMP_ALL_CACHE 0 -#endif /* CACHE_PRINT */ - -#if DUMP_ALL_CACHE -static void dumpAllCache(void); -#else -#define dumpAllCache() -#endif - -/* - * One entry (value) in SessionCache. - */ -typedef struct SessionCacheEntry SessionCacheEntry; -struct SessionCacheEntry { - /* Linked list of SessionCacheEntries. */ - SessionCacheEntry *next; - - SSLBuffer mKey; - SSLBuffer mSessionData; - - /* this entry to be removed from session map at this time */ - CFAbsoluteTime mExpiration; -}; - -/* - * Note: the caller passes in the expiration time solely to accomodate the - * instantiation of a single const Time::Interval for use in calculating - * TTL. This const, SessionCache.mTimeToLive, is in the singleton gSession Cache. - */ -/* - * This constructor, the only one, allocs copies of the key and value - * SSLBuffers. - */ -static SessionCacheEntry *SessionCacheEntryCreate( - const SSLBuffer *key, - const SSLBuffer *sessionData, - CFAbsoluteTime expirationTime) -{ - OSStatus serr; - - SessionCacheEntry *entry = sslMalloc(sizeof(SessionCacheEntry)); - if (entry == NULL) - return NULL; - - serr = SSLCopyBuffer(key, &entry->mKey); - if(serr) { - sslFree (entry); - return NULL; - } - serr = SSLCopyBuffer(sessionData, &entry->mSessionData); - if(serr) { - SSLFreeBuffer(&entry->mKey); - sslFree (entry); - return NULL; - } - - sslLogSessCacheDebug("SessionCacheEntryCreate(buf,buf) %p", entry); - entry->mExpiration = expirationTime; - - return entry; -} - -static void SessionCacheEntryDelete(SessionCacheEntry *entry) -{ - sslLogSessCacheDebug("~SessionCacheEntryDelete() %p", entry); - SSLFreeBuffer(&entry->mKey); // no SSLContext - SSLFreeBuffer(&entry->mSessionData); - sslFree(entry); -} - -/* basic lookup/match function */ -static bool SessionCacheEntryMatchKey(SessionCacheEntry *entry, - const SSLBuffer *key) -{ - if(key->length != entry->mKey.length) { - return false; - } - if((key->data == NULL) || (entry->mKey.data == NULL)) { - return false; - } - return (memcmp(key->data, entry->mKey.data, entry->mKey.length) == 0); -} - -static bool SessionCacheEntryIsStale(SessionCacheEntry *entry, - CFAbsoluteTime now) -{ - return now > entry->mExpiration; -} - -/* has this expired? */ -static bool SessionCacheEntryIsStaleNow(SessionCacheEntry *entry) -{ - return SessionCacheEntryIsStale(entry, CFAbsoluteTimeGetCurrent()); -} - -/* replace existing mSessionData */ -static OSStatus SessionCacheEntrySetSessionData(SessionCacheEntry *entry, - const SSLBuffer *data) -{ - SSLFreeBuffer(&entry->mSessionData); - return SSLCopyBuffer(data, &entry->mSessionData); -} - -/* - * Global list of sessions and associated state. We maintain a singleton of - * this. - */ -typedef struct SessionCache { - SessionCacheEntry *head; - CFTimeInterval mTimeToLive; /* default time-to-live in seconds */ -} SessionCache; - -static pthread_mutex_t gSessionCacheLock = PTHREAD_MUTEX_INITIALIZER; -static SessionCache *gSessionCache = NULL; - -static void SessionCacheInit(void) { - gSessionCache = sslMalloc(sizeof(SessionCache)); - gSessionCache->head = NULL; - gSessionCache->mTimeToLive = SESSION_CACHE_TTL; -} - -static SessionCache *SessionCacheGetLockedInstance(void) { - pthread_mutex_lock(&gSessionCacheLock); - if (!gSessionCache) { - /* We could use pthread_once, but we already have a mutex for other - reasons. */ - SessionCacheInit(); - } - - return gSessionCache; -} - -/* these three correspond to the C functions exported by this file */ -static OSStatus SessionCacheAddEntry( - SessionCache *cache, - const SSLBuffer *sessionKey, - const SSLBuffer *sessionData, - uint32_t timeToLive) /* optional time-to-live in seconds; 0 ==> default */ -{ - SessionCacheEntry *entry = NULL; - SessionCacheEntry **current; - CFTimeInterval expireTime; - - for (current = &(cache->head); *current; current = &((*current)->next)) { - entry = *current; - if (SessionCacheEntryMatchKey(entry, sessionKey)) { - /* cache hit - just update this entry's sessionData if necessary */ - /* Note we leave expiration time and position in queue unchanged - - OK? */ - /* What if the entry has already expired? */ - if((entry->mSessionData.length == sessionData->length) && - (memcmp(entry->mSessionData.data, sessionData->data, - sessionData->length) == 0)) { - /* - * These usually match, and a memcmp is a lot cheaper than - * a malloc and a free, hence this quick optimization..... - */ - sslLogSessCacheDebug("SessionCache::addEntry CACHE HIT " - "entry = %p", entry); - return errSecSuccess; - } - else { - sslLogSessCacheDebug("SessionCache::addEntry CACHE REPLACE " - "entry = %p", entry); - return SessionCacheEntrySetSessionData(entry, sessionData); - } - } - } - - expireTime = CFAbsoluteTimeGetCurrent(); - if(timeToLive) { - /* caller-specified */ - expireTime += (CFTimeInterval)timeToLive; - } - else { - /* default */ - expireTime += cache->mTimeToLive; - } - /* this allocs new copy of incoming sessionKey and sessionData */ - entry = SessionCacheEntryCreate(sessionKey, sessionData, expireTime); - - sslLogSessCacheDebug("SessionCache::addEntry %p", entry); - cachePrint(entry, sessionKey, sessionData); - dumpAllCache(); - - /* add to head of queue for LIFO caching */ - entry->next = cache->head; - cache->head = entry; - - return errSecSuccess; -} - -static OSStatus SessionCacheLookupEntry( - SessionCache *cache, - const SSLBuffer *sessionKey, - SSLBuffer *sessionData) -{ - SessionCacheEntry *entry = NULL; - SessionCacheEntry **current; - for (current = &(cache->head); *current; current = &((*current)->next)) { - entry = *current; - if (SessionCacheEntryMatchKey(entry, sessionKey)) - break; - } - - if (*current == NULL) - return errSSLSessionNotFound; - - if (SessionCacheEntryIsStaleNow(entry)) { - sslLogSessCacheDebug("SessionCache::lookupEntry %p: STALE " - "entry, deleting; current %p, entry->next %p", - entry, current, entry->next); - cachePrint(entry, sessionKey, &entry->mSessionData); - *current = entry->next; - SessionCacheEntryDelete(entry); - return errSSLSessionNotFound; - } - - /* alloc/copy sessionData from existing entry (caller must free) */ - return SSLCopyBuffer(&entry->mSessionData, sessionData); -} - -static OSStatus SessionCacheDeleteEntry( - SessionCache *cache, - const SSLBuffer *sessionKey) -{ - SessionCacheEntry **current; - - for (current = &(cache->head); *current; current = &((*current)->next)) { - SessionCacheEntry *entry = *current; - if (SessionCacheEntryMatchKey(entry, sessionKey)) { - #ifndef DEBUG - sslLogSessCacheDebug("...SessionCacheDeleteEntry: deleting " - "cached session (%p)", entry); - cachePrint(entry, &entry->mKey, &entry->mSessionData); - #endif - *current = entry->next; - SessionCacheEntryDelete(entry); - return errSecSuccess; - } - } - - return errSecSuccess; -} - -/* cleanup, delete stale entries */ -static bool SessionCacheCleanup(SessionCache *cache) -{ - bool brtn = false; - CFAbsoluteTime rightNow = CFAbsoluteTimeGetCurrent(); - SessionCacheEntry **current; - - for (current = &(cache->head); *current;) { - SessionCacheEntry *entry = *current; - if(SessionCacheEntryIsStale(entry, rightNow)) { - #ifndef DEBUG - sslLogSessCacheDebug("...SessionCacheCleanup: deleting " - "cached session (%p)", entry); - cachePrint(entry, &entry->mKey, &entry->mSessionData); - #endif - *current = entry->next; - SessionCacheEntryDelete(entry); - } - else { - current = &((*current)->next); - /* we're leaving one in the map */ - brtn = true; - } - } - return brtn; -} - -#if DUMP_ALL_CACHE -static void dumpAllCache(void) -{ - SessionCache *cache = gSessionCache; - SessionCacheEntry *entry; - - printf("Contents of sessionCache:\n"); - for(entry = cache->head; entry; entry = entry->next) { - cachePrint(entry, &entry->mKey, &entry->mSessionData); - } -} -#endif /* DUMP_ALL_CACHE */ - -/* - * Store opaque sessionData, associated with opaque sessionKey. - */ -OSStatus sslAddSession ( - const SSLBuffer sessionKey, - const SSLBuffer sessionData, - uint32_t timeToLive) /* optional time-to-live in seconds; 0 ==> default */ -{ - SessionCache *cache = SessionCacheGetLockedInstance(); - OSStatus serr; - if (!cache) - serr = errSSLSessionNotFound; - else - { - serr = SessionCacheAddEntry(cache, &sessionKey, &sessionData, timeToLive); - - dumpAllCache(); - } - - pthread_mutex_unlock(&gSessionCacheLock); - return serr; -} - -/* - * Given an opaque sessionKey, alloc & retrieve associated sessionData. - */ -OSStatus sslCopySession ( - const SSLBuffer sessionKey, - SSLBuffer *sessionData) -{ - SessionCache *cache = SessionCacheGetLockedInstance(); - OSStatus serr; - if (!cache) - serr = errSSLSessionNotFound; - else - { - serr = SessionCacheLookupEntry(cache, &sessionKey, sessionData); - - sslLogSessCacheDebug("sslGetSession(%d, %p): %d", - (int)sessionKey.length, sessionKey.data, - (int)serr); - if(!serr) { - cachePrint(NULL, &sessionKey, sessionData); - } - else { - cachePrint(NULL, &sessionKey, NULL); - } - dumpAllCache(); - } - - pthread_mutex_unlock(&gSessionCacheLock); - - return serr; -} - -OSStatus sslDeleteSession ( - const SSLBuffer sessionKey) -{ - SessionCache *cache = SessionCacheGetLockedInstance(); - OSStatus serr; - if (!cache) - serr = errSSLSessionNotFound; - else - { - serr = SessionCacheDeleteEntry(cache, &sessionKey); - } - - pthread_mutex_unlock(&gSessionCacheLock); - return serr; -} - -/* cleanup up session cache, deleting stale entries. */ -OSStatus sslCleanupSession(void) -{ - SessionCache *cache = SessionCacheGetLockedInstance(); - OSStatus serr = errSecSuccess; - bool moreToGo = false; - - if (!cache) - serr = errSSLSessionNotFound; - else - { - moreToGo = SessionCacheCleanup(cache); - } - /* Possible TBD: if moreToGo, schedule a timed callback to this function */ - - pthread_mutex_unlock(&gSessionCacheLock); - return serr; -} diff --git a/OSX/libsecurity_ssl/lib/security_ssl.exp b/OSX/libsecurity_ssl/lib/security_ssl.exp index e49ea120..624a672f 100644 --- a/OSX/libsecurity_ssl/lib/security_ssl.exp +++ b/OSX/libsecurity_ssl/lib/security_ssl.exp @@ -48,6 +48,7 @@ _SSLInternal_PRF _SSLNewContext _SSLNewDatagramContext _SSLRead +_SSLReHandshake _SSLSetAllowsAnyRoot _SSLSetAllowsExpiredCerts _SSLSetAllowsExpiredRoots @@ -90,7 +91,5 @@ _SSLGetClientAuthTypes _SSLGetNegotiatedClientAuthType _SSLSetMinimumDHGroupSize _SSLGetMinimumDHGroupSize -_SSLSetSessionStrengthPolicy _SSLSetSessionConfig -_SSLGetSessionConfig diff --git a/OSX/libsecurity_ssl/lib/sslCipherSpecs.c b/OSX/libsecurity_ssl/lib/sslCipherSpecs.c index d9bf5c4c..144d585e 100644 --- a/OSX/libsecurity_ssl/lib/sslCipherSpecs.c +++ b/OSX/libsecurity_ssl/lib/sslCipherSpecs.c @@ -31,7 +31,6 @@ #include "sslDebug.h" #include "sslMemory.h" #include "sslDebug.h" -#include "sslUtils.h" #include "sslPriv.h" #include @@ -302,9 +301,12 @@ SSLGetEnabledCiphers (SSLContextRef ctx, err = tls_handshake_get_ciphersuites(ctx->hdsk, &ciphersuites, &n); - return cipherSuitesToCipherSuites(n, - ciphersuites, - ciphers, - numCiphers); - + if(err) { + return err; + } else { + return cipherSuitesToCipherSuites(n, + ciphersuites, + ciphers, + numCiphers); + } } diff --git a/OSX/libsecurity_ssl/lib/sslContext.c b/OSX/libsecurity_ssl/lib/sslContext.c index 653cbe32..89f89687 100644 --- a/OSX/libsecurity_ssl/lib/sslContext.c +++ b/OSX/libsecurity_ssl/lib/sslContext.c @@ -29,7 +29,6 @@ #include "SSLRecordInternal.h" #include "SecureTransportPriv.h" -#include "appleSession.h" #include "ssl.h" #include "sslCipherSpecs.h" #include "sslContext.h" @@ -37,7 +36,6 @@ #include "sslDebug.h" #include "sslKeychain.h" #include "sslMemory.h" -#include "sslUtils.h" #include "tlsCallbacks.h" @@ -78,26 +76,6 @@ static void sslFreeDnList(SSLContext *ctx) ctx->acceptableDNList = NULL; } -/* - This frees ctx->localCert, which is allocated in parseIncomingCert. - This is structured as a list, but all the SSLCertificates structs are - allocated as a single array, so there is only on sslFree(localCert). - */ -static void sslFreeLocalCert(SSLContext *ctx) -{ - SSLCertificate *cert; - - cert = ctx->localCert; - while (cert) - { - SSLFreeBuffer(&cert->derCert); - cert = cert->next; - } - sslFree(ctx->localCert); - ctx->localCert = NULL; -} - - Boolean sslIsSessionActive(const SSLContext *ctx) { assert(ctx != NULL); @@ -134,15 +112,20 @@ Boolean sslIsSessionActive(const SSLContext *ctx) #define MIN_ALLOWED_DTLS_MTU 64 /* this ensure than there will be no integer underflow when calculating max write size */ -int kSplitDefaultValue; +/* Preferences values */ CFIndex kMinDhGroupSizeDefaultValue; +CFIndex kMinProtocolVersionDefaultValue; +CFStringRef kSSLSessionConfigDefaultValue; +Boolean kSSLDisableRecordSplittingDefaultValue; + +static tls_cache_t g_session_cache = NULL; #if TARGET_OS_IPHONE /* * Instead of using CFPropertyListReadFromFile we use a * CFPropertyListCreateWithStream directly * here. CFPropertyListReadFromFile() uses - * CFURLCopyResourcePropertyForKey() andCF pulls in CoreServices for + * CFURLCopyResourcePropertyForKey() and CF pulls in CoreServices for * CFURLCopyResourcePropertyForKey() and that doesn't work in install * enviroment. */ @@ -161,55 +144,91 @@ CopyPlistFromFile(CFURLRef url) #endif -static void _SSLContextReadDefault() +static +CFTypeRef SSLPreferencesCopyValue(CFStringRef key, CFPropertyListRef managed_prefs) { - /* 0 = disabled, 1 = split every write, 2 = split second and subsequent writes */ - /* Enabled by default, this may cause some interop issues, see and */ - const int defaultSplitDefaultValue = 2; - - CFTypeRef value = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SSLWriteSplit"), - CFSTR("com.apple.security"), - kCFPreferencesAnyUser, - kCFPreferencesCurrentHost); - if (value) { - if (CFGetTypeID(value) == CFBooleanGetTypeID()) - kSplitDefaultValue = CFBooleanGetValue((CFBooleanRef)value) ? 1 : 0; - else if (CFGetTypeID(value) == CFNumberGetTypeID()) { - if (!CFNumberGetValue((CFNumberRef)value, kCFNumberIntType, &kSplitDefaultValue)) - kSplitDefaultValue = defaultSplitDefaultValue; - } - if (kSplitDefaultValue < 0 || kSplitDefaultValue > 2) { - kSplitDefaultValue = defaultSplitDefaultValue; - } - CFRelease(value); - } - else { - kSplitDefaultValue = defaultSplitDefaultValue; - } + CFTypeRef value = (CFTypeRef) CFPreferencesCopyAppValue(CFSTR("SSLSessionConfig"), kCFPreferencesCurrentApplication); - /* Min DH Group Size */ - kMinDhGroupSizeDefaultValue = CFPreferencesGetAppIntegerValue(CFSTR("SSLMinDhGroupSize"), kCFPreferencesCurrentApplication, NULL); + if(!value && managed_prefs) { + value = CFDictionaryGetValue(managed_prefs, key); + } + + return value; +} + +static +CFIndex SSLPreferencesGetInteger(CFStringRef key, CFPropertyListRef managed_prefs) +{ + CFTypeRef value = SSLPreferencesCopyValue(key, managed_prefs); + CFIndex int_value = 0; + if (isNumber(value)) { + CFNumberGetValue(value, kCFNumberCFIndexType, &int_value); + } + CFReleaseSafe(value); + return int_value; +} + +static +Boolean SSLPreferencesGetBoolean(CFStringRef key, CFPropertyListRef managed_prefs) +{ + CFTypeRef value = SSLPreferencesCopyValue(key, managed_prefs); + Boolean bool_value = FALSE; + if (isBoolean(value)) { + bool_value = CFBooleanGetValue(value); + } + + CFReleaseSafe(value); + return bool_value; +} + +static +CFStringRef SSLPreferencesCopyString(CFStringRef key, CFPropertyListRef managed_prefs) +{ + CFTypeRef value = SSLPreferencesCopyValue(key, managed_prefs); + if (isString(value)) { + return value; + } else { + CFReleaseSafe(value); + return NULL; + } +} + +static void _SSLContextReadDefault() +{ + CFPropertyListRef managed_prefs = NULL; #if TARGET_OS_IPHONE - /* on iOS, if the above returned nothing, we manually look into mobile's Managed Preferences */ + /* on iOS, we also look for preferences from mobile's Managed Preferences */ /* Note that if the process is running as mobile, the above call will already have read the Managed Preference plist. - As a result, if you have some preferences set manually with defaults, which preference applies may be different for mobile vs not-mobile. */ - if(kMinDhGroupSizeDefaultValue == 0) { - CFURLRef prefURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Library/Managed Preferences/mobile/.GlobalPreferences.plist"), kCFURLPOSIXPathStyle, false); - if(prefURL) { - CFPropertyListRef plist = CopyPlistFromFile(prefURL); - if (plist) { - value = CFDictionaryGetValue(plist, CFSTR("SSLMinDhGroupSize")); - if (isNumber(value)) { - CFNumberGetValue(value, kCFNumberCFIndexType, &kMinDhGroupSizeDefaultValue); - } - } - CFReleaseSafe(plist); - } - CFReleaseSafe(prefURL); + As a result, if you have some preferences set manually with defaults, which preference applies may be different for mobile vs not-mobile. */ + CFURLRef prefURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Library/Managed Preferences/mobile/.GlobalPreferences.plist"), kCFURLPOSIXPathStyle, false); + if(prefURL) { + managed_prefs = CopyPlistFromFile(prefURL); } + CFReleaseSafe(prefURL); #endif + /* Disable record splitting */ + /* Enabled by default, this may cause some interop issues, see and */ + kSSLDisableRecordSplittingDefaultValue = SSLPreferencesGetBoolean(CFSTR("SSLDisableRecordSplitting"), managed_prefs); + + /* Min DH Group Size */ + kMinDhGroupSizeDefaultValue = SSLPreferencesGetInteger(CFSTR("SSLMinDhGroupSize"), managed_prefs); + + /* Default Min Prototcol Version */ + kMinProtocolVersionDefaultValue = SSLPreferencesGetInteger(CFSTR("SSLMinProtocolVersion"), managed_prefs); + + /* Default Config */ + kSSLSessionConfigDefaultValue = SSLPreferencesCopyString(CFSTR("SSLSessionConfig"), managed_prefs); + + CFReleaseSafe(managed_prefs); +} + +/* This functions initialize global variables, run once per process */ +static void SSLContextOnce(void) +{ + _SSLContextReadDefault(); + g_session_cache = tls_cache_create(); } CFGiblisWithHashFor(SSLContext) @@ -269,6 +288,13 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS return NULL; } + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + SSLContextOnce(); + }); + + ctx->cache = g_session_cache; + tls_handshake_set_callbacks(ctx->hdsk, &tls_handshake_callbacks, ctx); @@ -297,33 +323,24 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS /* Default for RSA blinding is ENABLED */ ctx->rsaBlindingEnable = true; - /* Default for sending one-byte app data record is DISABLED */ - ctx->oneByteRecordEnable = false; + /* Default for sending one-byte app data record is ENABLED */ + ctx->oneByteRecordEnable = !kSSLDisableRecordSplittingDefaultValue; /* Dont enable fallback behavior by default */ ctx->fallbackEnabled = false; - /* Consult global system preference for default behavior: - * 0 = disabled, 1 = split every write, 2 = split second and subsequent writes - * (caller can override by setting kSSLSessionOptionSendOneByteRecord) - */ - static pthread_once_t sReadDefault = PTHREAD_ONCE_INIT; - pthread_once(&sReadDefault, _SSLContextReadDefault); - if (kSplitDefaultValue > 0) { - ctx->oneByteRecordEnable = true; - } - - /* Default for server is DHE enabled, default for client is disabled */ - if(ctx->protocolSide == kSSLServerSide) { - SSLSetDHEEnabled(ctx, true); - } else { - SSLSetDHEEnabled(ctx, false); + if(kSSLSessionConfigDefaultValue) { + SSLSetSessionConfig(ctx, kSSLSessionConfigDefaultValue); } if(kMinDhGroupSizeDefaultValue) { tls_handshake_set_min_dh_group_size(ctx->hdsk, (unsigned)kMinDhGroupSizeDefaultValue); } + if(kMinProtocolVersionDefaultValue) { + SSLSetProtocolVersionMin(ctx, (unsigned)kMinProtocolVersionDefaultValue); + } + /* default for anonymous ciphers is DISABLED */ ctx->anonCipherEnable = false; @@ -334,8 +351,6 @@ SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolS ctx->signalCertRequest = false; ctx->signalClientAuth = false; - ctx->negAuthType = SSLClientAuthNone; /* ditto */ - return ctx; } @@ -406,16 +421,14 @@ void SSLContextDestroy(CFTypeRef arg) SSLFreeBuffer(&ctx->receivedDataBuffer); CFReleaseSafe(ctx->acceptableCAs); +#if !TARGET_OS_IPHONE CFReleaseSafe(ctx->trustedLeafCerts); +#endif CFReleaseSafe(ctx->localCertArray); CFReleaseSafe(ctx->encryptCertArray); - CFReleaseSafe(ctx->peerCert); CFReleaseSafe(ctx->trustedCerts); CFReleaseSafe(ctx->peerSecTrust); - sslFreePrivKey(&ctx->signingPrivKeyRef); - - sslFreeLocalCert(ctx); sslFreeDnList(ctx); SSLFreeBuffer(&ctx->ownVerifyData); @@ -426,9 +439,10 @@ void SSLContextDestroy(CFTypeRef arg) SSLFreeBuffer(&ctx->dhParamsEncoded); - memset(((uint8_t*) ctx) + sizeof(CFRuntimeBase), 0, sizeof(SSLContext) - sizeof(CFRuntimeBase)); + if(ctx->cache) + tls_cache_cleanup(ctx->cache); - sslCleanupSession(); + memset(((uint8_t*) ctx) + sizeof(CFRuntimeBase), 0, sizeof(SSLContext) - sizeof(CFRuntimeBase)); } /* @@ -512,6 +526,9 @@ SSLSetSessionOption (SSLContextRef context, case kSSLSessionOptionAllowServerIdentityChange: tls_handshake_set_server_identity_change(context->hdsk, value); break; + case kSSLSessionOptionAllowRenegotiation: + tls_handshake_set_renegotiation(context->hdsk, value); + break; default: return errSecParam; } @@ -1331,56 +1348,32 @@ OSStatus SSLSetAllowsExpiredCerts(SSLContextRef ctx, Boolean allowExpired) { - if(ctx == NULL) { - return errSecParam; - } - sslCertDebug("SSLSetAllowsExpiredCerts %s", - allowExpired ? "true" : "false"); - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->allowExpiredCerts = allowExpired; - return errSecSuccess; + /* This has been deprecated since 10.9, and non-functional since at least 10.10 */ + return 0; } OSStatus SSLGetAllowsExpiredCerts (SSLContextRef ctx, Boolean *allowExpired) { - if(ctx == NULL) { - return errSecParam; - } - *allowExpired = ctx->allowExpiredCerts; - return errSecSuccess; + /* This has been deprecated since 10.9, and non-functional since at least 10.10 */ + return errSecUnimplemented; } OSStatus SSLSetAllowsExpiredRoots(SSLContextRef ctx, Boolean allowExpired) { - if(ctx == NULL) { - return errSecParam; - } - sslCertDebug("SSLSetAllowsExpiredRoots %s", - allowExpired ? "true" : "false"); - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->allowExpiredRoots = allowExpired; - return errSecSuccess; + /* This has been deprecated since 10.9, and non-functional since at least 10.10 */ + return 0; } OSStatus SSLGetAllowsExpiredRoots (SSLContextRef ctx, Boolean *allowExpired) { - if(ctx == NULL) { - return errSecParam; - } - *allowExpired = ctx->allowExpiredRoots; - return errSecSuccess; + /* This has been deprecated since 10.9, and non-functional since at least 10.10 */ + return errSecUnimplemented; } OSStatus SSLSetAllowsAnyRoot( @@ -1483,6 +1476,7 @@ SSLCopyTrustedRoots (SSLContextRef ctx, #endif } +#if !TARGET_OS_IPHONE OSStatus SSLSetTrustedLeafCertificates (SSLContextRef ctx, CFArrayRef trustedCerts) @@ -1498,8 +1492,7 @@ SSLSetTrustedLeafCertificates (SSLContextRef ctx, if(ctx->trustedLeafCerts) { CFRelease(ctx->trustedLeafCerts); } - ctx->trustedLeafCerts = trustedCerts; - CFRetain(trustedCerts); + ctx->trustedLeafCerts = CFRetainSafe(trustedCerts); return errSecSuccess; } @@ -1518,6 +1511,7 @@ SSLCopyTrustedLeafCertificates (SSLContextRef ctx, *trustedCerts = NULL; return errSecSuccess; } +#endif OSStatus SSLSetClientSideAuthenticate (SSLContext *ctx, @@ -1568,7 +1562,7 @@ SSLGetClientCertificateState (SSLContextRef ctx, *clientState = kSSLClientCertNone; break; case kSSLClientCertRequested: - if(ctx->localCert) { + if(ctx->localCertArray) { *clientState = kSSLClientCertSent; } else { *clientState = kSSLClientCertRequested; @@ -1587,7 +1581,7 @@ SSLGetClientCertificateState (SSLContextRef ctx, *clientState = ctx->clientCertState; break; case kSSLClientCertRequested: - if(ctx->peerCert) { + if(ctx->peerSecTrust) { *clientState = kSSLClientCertSent; } else { *clientState = kSSLClientCertRequested; @@ -1602,10 +1596,13 @@ SSLGetClientCertificateState (SSLContextRef ctx, return errSecSuccess; } +#include + OSStatus SSLSetCertificate (SSLContextRef ctx, - CFArrayRef certRefs) + CFArrayRef _Nullable certRefs) { + OSStatus ortn; /* * -- free localCerts if we have any * -- Get raw cert data, convert to ctx->localCert @@ -1617,23 +1614,17 @@ SSLSetCertificate (SSLContextRef ctx, } CFReleaseNull(ctx->localCertArray); - /* changing the client cert invalidates negotiated auth type */ - ctx->negAuthType = SSLClientAuthNone; if(certRefs == NULL) { return errSecSuccess; // we have cleared the cert, as requested } - sslFreeLocalCert(ctx); - OSStatus ortn = parseIncomingCerts(ctx, - certRefs, - &ctx->localCert, - &ctx->signingPrivKeyRef); - if(ortn == errSecSuccess) { - ctx->localCertArray = certRefs; - CFRetain(certRefs); - if(ctx->protocolSide==kSSLClientSide) - SSLUpdateNegotiatedClientAuthType(ctx); - tls_handshake_set_identity(ctx->hdsk, ctx->localCert, ctx->signingPrivKeyRef); + + ortn = tls_helper_set_identity_from_array(ctx->hdsk, certRefs); + + if(ortn == noErr) { + ctx->localCertArray = certRefs; + CFRetain(certRefs); } + return ortn; } @@ -1931,46 +1922,34 @@ SSLCopyDistinguishedNames (SSLContextRef ctx, /* * Request peer certificates. Valid anytime, subsequent to * a handshake attempt. - * Common code for SSLGetPeerCertificates() and SSLCopyPeerCertificates(). - * TODO: the 'legacy' argument is not used anymore. */ -static OSStatus -sslCopyPeerCertificates (SSLContextRef ctx, - CFArrayRef *certs, - Boolean legacy) +OSStatus +SSLCopyPeerCertificates (SSLContextRef ctx, CFArrayRef *certs) { if(ctx == NULL) { return errSecParam; } - if (!ctx->peerCert) { + if (!ctx->peerSecTrust) { *certs = NULL; return errSecBadReq; } - CFArrayRef ca = CFArrayCreateCopy(kCFAllocatorDefault, ctx->peerCert); - *certs = ca; + CFIndex count = SecTrustGetCertificateCount(ctx->peerSecTrust); + CFMutableArrayRef ca = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks); if (ca == NULL) { return errSecAllocate; } - if (legacy) { - CFIndex ix, count = CFArrayGetCount(ca); - for (ix = 0; ix < count; ++ix) { - CFRetain(CFArrayGetValueAtIndex(ca, ix)); - } - } + for (CFIndex ix = 0; ix < count; ++ix) { + CFArrayAppendValue(ca, SecTrustGetCertificateAtIndex(ctx->peerSecTrust, ix)); + } + *certs = ca; + return errSecSuccess; } -OSStatus -SSLCopyPeerCertificates (SSLContextRef ctx, - CFArrayRef *certs) -{ - return sslCopyPeerCertificates(ctx, certs, false); -} - #if !TARGET_OS_IPHONE // Permanently removing from iOS, keep for OSX (deprecated), removed from headers. // Mailsmith Crashes While Getting New Mail Under Mavericks Developer Preview @@ -1981,7 +1960,7 @@ OSStatus SSLGetPeerCertificates (SSLContextRef ctx, CFArrayRef *certs) { - return sslCopyPeerCertificates(ctx, certs, true); + return errSecUnimplemented; } #endif @@ -2105,12 +2084,8 @@ SSLCopyPeerTrust( /* Create a SecTrustRef if this was a resumed session and we didn't have one yet. */ - if (!ctx->peerCert) { - ctx->peerCert = tls_get_peer_certs(tls_handshake_get_peer_certificates(ctx->hdsk)); - } - if (!ctx->peerSecTrust && ctx->peerCert) { - status = sslCreateSecTrust(ctx, ctx->peerCert, - &ctx->peerSecTrust); + if (!ctx->peerSecTrust) { + status = sslCreateSecTrust(ctx, &ctx->peerSecTrust); } *trust = ctx->peerSecTrust; @@ -2130,9 +2105,8 @@ OSStatus SSLGetPeerSecTrust( /* Create a SecTrustRef if this was a resumed session and we didn't have one yet. */ - if (!ctx->peerSecTrust && ctx->peerCert) { - status = sslCreateSecTrust(ctx, ctx->peerCert, - &ctx->peerSecTrust); + if (!ctx->peerSecTrust) { + status = sslCreateSecTrust(ctx, &ctx->peerSecTrust); } *trust = ctx->peerSecTrust; @@ -2454,92 +2428,13 @@ OSStatus SSLGetClientAuthTypes( } /* - * Obtain the SSLClientAuthenticationType actually performed. - * Only valid if client certificate state is kSSLClientCertSent - * or kSSLClientCertRejected; returns errSecParam otherwise. + * -- DEPRECATED -- Return errSecUnimplemented. */ OSStatus SSLGetNegotiatedClientAuthType( SSLContextRef ctx, SSLClientAuthenticationType *authType) /* RETURNED */ { - if(ctx == NULL) { - return errSecParam; - } - - *authType = ctx->negAuthType; - - return errSecSuccess; -} - -/* - * Update the negotiated client authentication type. - * This function may be called at any time; however, note that - * the negotiated authentication type will be SSLClientAuthNone - * until both of the following have taken place (in either order): - * - a CertificateRequest message from the server has been processed - * - a client certificate has been specified - * As such, this function (only) needs to be called from (both) - * SSLProcessCertificateRequest and SSLSetCertificate. - */ -OSStatus SSLUpdateNegotiatedClientAuthType( - SSLContextRef ctx) -{ - if(ctx == NULL) { - return errSecParam; - } - assert(ctx->protocolSide==kSSLClientSide); - /* - * See if we have a signing cert that matches one of the - * allowed auth types. The x509Requested flag indicates "we - * have a cert that we think the server will accept". - */ - ctx->x509Requested = 0; - ctx->negAuthType = SSLClientAuthNone; - if(ctx->signingPrivKeyRef != NULL) { - CFIndex ourKeyAlg = sslPrivKeyGetAlgorithmID((SecKeyRef)tls_private_key_get_context(ctx->signingPrivKeyRef)); - - unsigned i; - for(i=0; inumAuthTypes; i++) { - switch(ctx->clientAuthTypes[i]) { - case SSLClientAuth_RSASign: - if(ourKeyAlg == kSecRSAAlgorithmID) { - ctx->x509Requested = 1; - ctx->negAuthType = SSLClientAuth_RSASign; - } - break; - case SSLClientAuth_ECDSASign: - #if SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH - case SSLClientAuth_ECDSAFixedECDH: - #endif - if(ourKeyAlg == kSecECDSAAlgorithmID) { - ctx->x509Requested = 1; - ctx->negAuthType = ctx->clientAuthTypes[i]; - } - break; - #if SSL_ENABLE_RSA_FIXED_ECDH_AUTH - case SSLClientAuth_RSAFixedECDH: - /* Odd case, we differ from our signer */ - if((ourKeyAlg == kSecECDSAAlgorithmID) && - (ctx->ourSignerAlg == kSecRSAAlgorithmID)) { - ctx->x509Requested = 1; - ctx->negAuthType = SSLClientAuth_RSAFixedECDH; - } - break; - #endif - default: - /* None others supported */ - break; - } - if(ctx->x509Requested) { - sslLogNegotiateDebug("===CHOOSING authType %d", (int)ctx->negAuthType); - break; - } - } /* parsing authTypes */ - } /* we have a signing key */ - - tls_handshake_set_client_auth_type(ctx->hdsk, ctx->negAuthType); - - return errSecSuccess; + return errSecUnimplemented; } OSStatus SSLGetNumberOfSignatureAlgorithms( @@ -2642,14 +2537,6 @@ OSStatus SSLInternal_PRF( vout, outLen); } -/* To be implemented */ -OSStatus -SSLSetSessionStrengthPolicy(SSLContextRef context, - SSLSessionStrengthPolicy policyStrength) -{ - return errSecSuccess; -} - const CFStringRef kSSLSessionConfig_default = CFSTR("default"); const CFStringRef kSSLSessionConfig_ATSv1 = CFSTR("ATSv1"); const CFStringRef kSSLSessionConfig_ATSv1_noPFS = CFSTR("ATSv1_noPFS"); @@ -2659,61 +2546,36 @@ const CFStringRef kSSLSessionConfig_RC4_fallback = CFSTR("RC4_fallback"); const CFStringRef kSSLSessionConfig_TLSv1_fallback = CFSTR("TLSv1_fallback"); const CFStringRef kSSLSessionConfig_TLSv1_RC4_fallback = CFSTR("TLSv1_RC4_fallback"); const CFStringRef kSSLSessionConfig_legacy_DHE = CFSTR("legacy_DHE"); +const CFStringRef kSSLSessionConfig_anonymous = CFSTR("anonymous"); static tls_handshake_config_t SSLSessionConfig_to_tls_handshake_config(CFStringRef config) { if(CFEqual(config, kSSLSessionConfig_ATSv1)){ return tls_handshake_config_ATSv1; - } else if(CFEqual(config, kSSLSessionConfig_ATSv1_noPFS)){ + } else if(CFEqual(config, kSSLSessionConfig_ATSv1_noPFS)){ return tls_handshake_config_ATSv1_noPFS; - } else if(CFEqual(config, kSSLSessionConfig_standard)){ + } else if(CFEqual(config, kSSLSessionConfig_standard)){ return tls_handshake_config_standard; - } else if(CFEqual(config, kSSLSessionConfig_TLSv1_fallback)){ + } else if(CFEqual(config, kSSLSessionConfig_TLSv1_fallback)){ return tls_handshake_config_TLSv1_fallback; - } else if(CFEqual(config, kSSLSessionConfig_TLSv1_RC4_fallback)){ + } else if(CFEqual(config, kSSLSessionConfig_TLSv1_RC4_fallback)){ return tls_handshake_config_TLSv1_RC4_fallback; - } else if(CFEqual(config, kSSLSessionConfig_RC4_fallback)){ + } else if(CFEqual(config, kSSLSessionConfig_RC4_fallback)){ return tls_handshake_config_RC4_fallback; - } else if(CFEqual(config, kSSLSessionConfig_legacy)){ + } else if(CFEqual(config, kSSLSessionConfig_legacy)){ return tls_handshake_config_legacy; - } else if(CFEqual(config, kSSLSessionConfig_legacy_DHE)){ + } else if(CFEqual(config, kSSLSessionConfig_legacy_DHE)){ return tls_handshake_config_legacy_DHE; - } else if(CFEqual(config, kSSLSessionConfig_default)){ + } else if(CFEqual(config, kSSLSessionConfig_anonymous)){ + return tls_handshake_config_anonymous; + } else if(CFEqual(config, kSSLSessionConfig_default)){ return tls_handshake_config_default; } else { return tls_handshake_config_none; } } -static -const CFStringRef tls_handshake_config_to_SSLSessionConfig(tls_handshake_config_t config) -{ - switch(config) { - case tls_handshake_config_ATSv1: - return kSSLSessionConfig_ATSv1; - case tls_handshake_config_ATSv1_noPFS: - return kSSLSessionConfig_ATSv1_noPFS; - case tls_handshake_config_standard: - return kSSLSessionConfig_standard; - case tls_handshake_config_RC4_fallback: - return kSSLSessionConfig_RC4_fallback; - case tls_handshake_config_TLSv1_fallback: - return kSSLSessionConfig_TLSv1_fallback; - case tls_handshake_config_TLSv1_RC4_fallback: - return kSSLSessionConfig_TLSv1_RC4_fallback; - case tls_handshake_config_legacy: - return kSSLSessionConfig_legacy; - case tls_handshake_config_legacy_DHE: - return kSSLSessionConfig_legacy_DHE; - case tls_handshake_config_default: - return kSSLSessionConfig_default; - case tls_handshake_config_none: - return NULL; - } -} - - /* Set Predefined TLS Configuration */ OSStatus SSLSetSessionConfig(SSLContextRef context, @@ -2726,19 +2588,3 @@ SSLSetSessionConfig(SSLContextRef context, return errSecParam; } } - -OSStatus -SSLGetSessionConfig(SSLContextRef context, - CFStringRef *config) -{ - tls_handshake_config_t cfg; - OSStatus err = tls_handshake_get_config(context->hdsk, &cfg); - if(err) { - return err; - } - - *config = tls_handshake_config_to_SSLSessionConfig(cfg); - - return noErr; -} - diff --git a/OSX/libsecurity_ssl/lib/sslContext.h b/OSX/libsecurity_ssl/lib/sslContext.h index 10579dc6..590efcb3 100644 --- a/OSX/libsecurity_ssl/lib/sslContext.h +++ b/OSX/libsecurity_ssl/lib/sslContext.h @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef USE_CDSA_CRYPTO #include @@ -86,12 +87,11 @@ struct SSLContext CFRuntimeBase _base; IOContext ioCtx; - const struct SSLRecordFuncs *recFuncs; SSLRecordContextRef recCtx; tls_handshake_t hdsk; - + tls_cache_t cache; int readCipher_ready; int writeCipher_ready; @@ -123,20 +123,9 @@ struct SSLContext uint16_t selectedCipher; /* currently selected */ - - tls_private_key_t signingPrivKeyRef; /* our private key */ - - /* Server DH Parameters */ SSLBuffer dhParamsEncoded; /* PKCS3 encoded blob - prime + generator */ - /* - * Local and Peer cert chains. - * For both, the root is the last in the chain. - */ - SSLCertificate *localCert; - CFArrayRef peerCert; - /* * The arrays we are given via SSLSetCertificate() and SSLSetEncryptionCertificate(). * We keep them here, refcounted, solely for the associated getter. @@ -150,10 +139,12 @@ struct SSLContext CFMutableArrayRef trustedCerts; Boolean trustedCertsOnly; +#if !TARGET_OS_IPHONE /* * trusted leaf certs as specified in SSLSetTrustedLeafCertificates() */ CFArrayRef trustedLeafCerts; +#endif Boolean allowExpiredCerts; Boolean allowExpiredRoots; @@ -163,14 +154,11 @@ struct SSLContext SSLBuffer peerID; SSLBuffer resumableSession; /* We keep a copy for now - but eventually this should go away if we get refcounted SSLBuffers */ - - uint16_t *ecdhCurves; unsigned ecdhNumCurves; /* server-side only */ SSLAuthenticate clientAuth; /* kNeverAuthenticate, etc. */ - //Boolean tryClientAuth; /* client and server */ SSLClientCertificateState clientCertState; @@ -229,9 +217,6 @@ struct SSLContext unsigned numAuthTypes; const tls_client_auth_type *clientAuthTypes; - /* client auth type actually negotiated */ - tls_client_auth_type negAuthType; - /* Timeout for DTLS retransmit */ CFAbsoluteTime timeout_deadline; CFAbsoluteTime timeout_duration; diff --git a/OSX/libsecurity_ssl/lib/sslCrypto.c b/OSX/libsecurity_ssl/lib/sslCrypto.c index df6d9707..1142c7f9 100644 --- a/OSX/libsecurity_ssl/lib/sslCrypto.c +++ b/OSX/libsecurity_ssl/lib/sslCrypto.c @@ -28,7 +28,6 @@ #include "sslCrypto.h" #include "sslContext.h" #include "sslMemory.h" -#include "sslUtils.h" #include "sslDebug.h" #include @@ -47,6 +46,8 @@ #include #endif +#include + /* * Get algorithm id for a SSLPubKey object. */ @@ -71,120 +72,37 @@ CFIndex sslPrivKeyGetAlgorithmID(SecKeyRef privKey) #endif } -static -OSStatus sslCreateCFArrayFromList(const tls_buffer_list_t *list, CFArrayRef *cfArray) -{ - int err; - CFMutableArrayRef array = NULL; - CFDataRef data = NULL; - - err = errSSLInternal; - - array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - require(array, out); - - while(list) { - require((data = CFDataCreate(kCFAllocatorDefault, list->buffer.data, list->buffer.length)), out); - CFArrayAppendValue(array, data); - CFReleaseNull(data); - list=list->next; - } - - *cfArray = array; - return errSecSuccess; - -out: - CFReleaseSafe(data); - CFReleaseSafe(array); - return err; -} OSStatus sslCreateSecTrust( SSLContext *ctx, - CFArrayRef certChain, SecTrustRef *pTrust) /* RETURNED */ { OSStatus status = errSecAllocate; - CFStringRef peerDomainName = NULL; - CFTypeRef policies = NULL; SecTrustRef trust = NULL; - const char *peerDomainNameData = NULL; - size_t peerDomainNameLen = 0; - if(ctx->protocolSide==kSSLClientSide) { - tls_handshake_get_peer_hostname(ctx->hdsk, &peerDomainNameData, &peerDomainNameLen); - } - - if (CFArrayGetCount(certChain) == 0) { - status = errSSLBadCert; - goto errOut; - } - - if (peerDomainNameLen && peerDomainNameData) { - CFIndex len = peerDomainNameLen; - if (peerDomainNameData[len - 1] == 0) { - len--; - //secwarning("peerDomainName is zero terminated!"); - } - /* @@@ Double check that this is the correct encoding. */ - require(peerDomainName = CFStringCreateWithBytes(kCFAllocatorDefault, - (const UInt8 *)peerDomainNameData, len, - kCFStringEncodingUTF8, false), errOut); - } - - /* If we are the client, our peer certificates must satisfy the - ssl server policy. */ - bool use_server_policy = (ctx->protocolSide == kSSLClientSide); - require(policies = SecPolicyCreateSSL(use_server_policy, peerDomainName), errOut); - - require_noerr(status = SecTrustCreateWithCertificates(certChain, policies, - &trust), errOut); - - /* If we are the client, let's see if we have OCSP responses and SCTs in the TLS handshake */ - if(ctx->protocolSide == kSSLClientSide) { - const tls_buffer_list_t *sct_list = tls_handshake_get_peer_sct_list(ctx->hdsk); - const tls_buffer *ocsp_response = tls_handshake_get_peer_ocsp_response(ctx->hdsk); - - if(ocsp_response) { - CFDataRef responseData = CFDataCreate(kCFAllocatorDefault, ocsp_response->data, ocsp_response->length); - status = SecTrustSetOCSPResponse(trust, responseData); - CFReleaseSafe(responseData); - require_noerr(status, errOut); - } - - if(sct_list) { - CFArrayRef sctArray = NULL; - require_noerr(status = sslCreateCFArrayFromList(sct_list, &sctArray), errOut); -#if TARGET_OS_IPHONE - status = SecTrustSetSignedCertificateTimestamps(trust, sctArray); -#else - status = noErr; -#endif - CFReleaseSafe(sctArray); - require_noerr(status, errOut); - } - } + require_noerr(status = tls_helper_create_peer_trust(ctx->hdsk, ctx->protocolSide==kSSLServerSide, &trust), errOut); /* If we have trustedAnchors we set them here. */ - if (ctx->trustedCerts) { - require_noerr(status = SecTrustSetAnchorCertificates(trust, - ctx->trustedCerts), errOut); - require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, - ctx->trustedCertsOnly), errOut); + if (trust && ctx->trustedCerts) { + require_noerr(status = SecTrustSetAnchorCertificates(trust, ctx->trustedCerts), errOut); + require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, ctx->trustedCertsOnly), errOut); } status = errSecSuccess; errOut: - CFReleaseSafe(peerDomainName); - CFReleaseSafe(policies); - - *pTrust = trust; + if(status != noErr) { + CFReleaseSafe(trust); + *pTrust = NULL; + } else { + *pTrust = trust; + } return status; } +#if !TARGET_OS_IPHONE /* Return the first certificate reference from the supplied array * whose data matches the given certificate, or NULL if none match. */ @@ -218,13 +136,13 @@ sslGetMatchingCertInArray( return matchedCert; } +#endif /* * Verify a chain of DER-encoded certs. */ static OSStatus sslVerifyCertChain( - SSLContext *ctx, - CFArrayRef certChain) + SSLContext *ctx) { OSStatus status; SecTrustRef trust = NULL; @@ -232,7 +150,10 @@ static OSStatus sslVerifyCertChain( /* renegotiate - start with a new SecTrustRef */ CFReleaseNull(ctx->peerSecTrust); - if(certChain==NULL) { + /* on failure, we always return trust==NULL, so we don't check the returned status here */ + sslCreateSecTrust(ctx, &trust); + + if(trust==NULL) { if(ctx->protocolSide == kSSLClientSide) { /* No cert chain is always a trust failure on the server side */ status = errSSLXCertChainInvalid; @@ -249,7 +170,6 @@ static OSStatus sslVerifyCertChain( goto errOut; } - status = sslCreateSecTrust(ctx, certChain, &trust); if (!ctx->enableCertVerify) { /* trivial case, this is caller's responsibility */ @@ -275,16 +195,18 @@ static OSStatus sslVerifyCertChain( status = errSecSuccess; } else { +#if !TARGET_OS_IPHONE /* * If the caller provided a list of trusted leaf certs, check them here */ - if(ctx->trustedLeafCerts) { - if (sslGetMatchingCertInArray((SecCertificateRef)CFArrayGetValueAtIndex(certChain, 0), - ctx->trustedLeafCerts)) { - status = errSecSuccess; - goto errOut; - } - } + if(ctx->trustedLeafCerts) { + if (sslGetMatchingCertInArray(SecTrustGetCertificateAtIndex(trust, 0), + ctx->trustedLeafCerts)) { + status = errSecSuccess; + goto errOut; + } + } +#endif status = errSSLXCertChainInvalid; } /* Do we really need to return things like: @@ -306,144 +228,6 @@ errOut: return status; } -/* Extract public SecKeyRef from Certificate Chain */ -static -int sslCopyPeerPubKey(const SSLCertificate *certchain, - SecKeyRef *pubKey) -{ - int err; - check(pubKey); - SecTrustRef trust = NULL; - const SSLCertificate *cert; - CFMutableArrayRef certArray = NULL; - CFDataRef certData = NULL; - SecCertificateRef cfCert = NULL; - - err = errSSLInternal; - - certArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - cert = certchain; - while(cert) { - require((certData = CFDataCreate(kCFAllocatorDefault, cert->derCert.data, cert->derCert.length)), out); - require_action((cfCert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)), out, err=errSSLBadCert); - CFArrayAppendValue(certArray, cfCert); - CFReleaseNull(cfCert); - CFReleaseNull(certData); - cert=cert->next; - } - - require_noerr((err=SecTrustCreateWithCertificates(certArray, NULL, &trust)), out); - SecKeyRef key = SecTrustCopyPublicKey(trust); - require_action(key, out, err=errSSLBadCert); - - *pubKey = key; - - err = errSecSuccess; - -out: - CFReleaseSafe(certData); - CFReleaseSafe(cfCert); - CFReleaseSafe(trust); - CFReleaseSafe(certArray); - - return err; -} - -/* Extract the pubkey from a cert chain, and send it to the tls_handshake context */ -int tls_set_peer_pubkey(SSLContext *ctx) -{ - int err; - CFIndex algId; - SecKeyRef pubkey = NULL; - CFDataRef modulus = NULL; - CFDataRef exponent = NULL; - CFDataRef ecpubdata = NULL; - const SSLCertificate *certchain = NULL; - - certchain = tls_handshake_get_peer_certificates(ctx->hdsk); - CFReleaseNull(ctx->peerCert); - - /* If there is no certchain, then we don't need to set the pubkey in coreTLS */ - /* We should really set it to "NULL" or none, but we need to fix the coreTLS API */ - /* See: coreTLS: replace tls_handshake_set_peer_rsa_public_key and tls_handshake_set_peer_ec_public_key with a common function */ - if(!certchain) - return 0; - - ctx->peerCert = tls_get_peer_certs(certchain); - -#if 0 - { /* dump certs */ - int i=0; - int j; - const SSLCertificate *tmp = certchain; - while(tmp) { - printf("cert%d[] = {", i); - for(j=0; jderCert.length; j++) { - if((j&0xf)==0) - printf("\n"); - printf("0x%02x, ", tmp->derCert.data[j]); - } - printf("}\n"); - tmp=tmp->next; - i++; - } - } -#endif - - require_noerr((err=sslCopyPeerPubKey(certchain, &pubkey)), errOut); - -#if TARGET_OS_IPHONE - algId = SecKeyGetAlgorithmID(pubkey); -#else - algId = SecKeyGetAlgorithmId(pubkey); -#endif - - err = errSSLCrypto; - - switch(algId) { - case kSecRSAAlgorithmID: - { - require((modulus = SecKeyCopyModulus(pubkey)), errOut); - require((exponent = SecKeyCopyExponent(pubkey)), errOut); - - tls_buffer mod; - tls_buffer exp; - - mod.data = (uint8_t *)CFDataGetBytePtr(modulus); - mod.length = CFDataGetLength(modulus); - - exp.data = (uint8_t *)CFDataGetBytePtr(exponent); - exp.length = CFDataGetLength(exponent); - - err = tls_handshake_set_peer_rsa_public_key(ctx->hdsk, &mod, &exp); - break; - } - case kSecECDSAAlgorithmID: - { - tls_named_curve curve = SecECKeyGetNamedCurve(pubkey); - require((ecpubdata = SecECKeyCopyPublicBits(pubkey)), errOut); - - tls_buffer pubdata; - pubdata.data = (uint8_t *)CFDataGetBytePtr(ecpubdata); - pubdata.length = CFDataGetLength(ecpubdata); - - err = tls_handshake_set_peer_ec_public_key(ctx->hdsk, curve, &pubdata); - - break; - } - default: - break; - } - -errOut: - CFReleaseSafe(pubkey); - CFReleaseSafe(modulus); - CFReleaseSafe(exponent); - CFReleaseSafe(ecpubdata); - - return err; -} - /* Convert cert in DER format into an CFArray of SecCertificateRef */ CFArrayRef tls_get_peer_certs(const SSLCertificate *certs) @@ -487,7 +271,7 @@ tls_verify_peer_cert(SSLContext *ctx) call to tls_handshake_set_peer_trust(). In some case a verification failure here is normal, for example if there is no cert (eg: PSK and Anon DH ciphersuites) */ - st = sslVerifyCertChain(ctx, ctx->peerCert); + st = sslVerifyCertChain(ctx); tls_handshake_trust_t trust; switch (st) { case errSecSuccess: @@ -519,7 +303,7 @@ tls_verify_peer_cert(SSLContext *ctx) if (ctx->breakOnClientAuth) { err = errSSLClientAuthCompleted; } - } else if(ctx->peerCert) { + } else if(ctx->peerSecTrust) { /* * Schedule return to the caller to verify the server's identity. * This will only return if a server cert was sent. In other cases diff --git a/OSX/libsecurity_ssl/lib/sslCrypto.h b/OSX/libsecurity_ssl/lib/sslCrypto.h index 52fb833d..007fa969 100644 --- a/OSX/libsecurity_ssl/lib/sslCrypto.h +++ b/OSX/libsecurity_ssl/lib/sslCrypto.h @@ -58,7 +58,6 @@ CFIndex sslPrivKeyGetAlgorithmID(SecKeyRef privKey); OSStatus sslCreateSecTrust( SSLContext *ctx, - CFArrayRef certChain, SecTrustRef *trust); /* RETURNED */ OSStatus sslVerifySelectedCipher( diff --git a/OSX/libsecurity_ssl/lib/sslDebug.h b/OSX/libsecurity_ssl/lib/sslDebug.h index b42e4c01..00dc5cda 100644 --- a/OSX/libsecurity_ssl/lib/sslDebug.h +++ b/OSX/libsecurity_ssl/lib/sslDebug.h @@ -29,8 +29,8 @@ #define _SSL_DEBUG_H_ #ifdef KERNEL -/* TODO: support secdebug in the kernel */ -#define secdebug(x...) +/* TODO: support secinfo in the kernel */ +#define secinfo(x...) #else /* KERNEL */ #include #endif @@ -40,43 +40,43 @@ #endif -#define ssl_secdebug secdebug +#define ssl_secinfo secinfo #ifndef NDEBUG /* log changes in handshake state */ -#define sslHdskStateDebug(args...) ssl_secdebug("sslHdskState", ## args) +#define sslHdskStateDebug(args...) ssl_secinfo("sslHdskState", ## args) /* log handshake and alert messages */ -#define sslHdskMsgDebug(args...) ssl_secdebug("sslHdskMsg", ## args) +#define sslHdskMsgDebug(args...) ssl_secinfo("sslHdskMsg", ## args) /* log negotiated handshake parameters */ -#define sslLogNegotiateDebug(args...) ssl_secdebug("sslLogNegotiate", ## args) +#define sslLogNegotiateDebug(args...) ssl_secinfo("sslLogNegotiate", ## args) /* log received protocol messsages */ -#define sslLogRxProtocolDebug(msgType) ssl_secdebug("sslLogRxProtocol", \ +#define sslLogRxProtocolDebug(msgType) ssl_secinfo("sslLogRxProtocol", \ "---received protoMsg %s", msgType) /* log resumable session info */ -#define sslLogResumSessDebug(args...) ssl_secdebug("sslResumSession", ## args) +#define sslLogResumSessDebug(args...) ssl_secinfo("sslResumSession", ## args) /* log low-level session info in appleSession.c */ -#define sslLogSessCacheDebug(args...) ssl_secdebug("sslSessionCache", ## args) +#define sslLogSessCacheDebug(args...) ssl_secinfo("sslSessionCache", ## args) /* log record-level I/O (SSLRead, SSLWrite) */ -#define sslLogRecordIo(args...) ssl_secdebug("sslRecordIo", ## args) +#define sslLogRecordIo(args...) ssl_secinfo("sslRecordIo", ## args) /* cert-related info */ -#define sslCertDebug(args...) ssl_secdebug("sslCert", ## args) +#define sslCertDebug(args...) ssl_secinfo("sslCert", ## args) /* Diffie-Hellman */ -#define sslDhDebug(args...) ssl_secdebug("sslDh", ## args) +#define sslDhDebug(args...) ssl_secinfo("sslDh", ## args) /* EAP-FAST PAC-based session resumption */ -#define sslEapDebug(args...) ssl_secdebug("sslEap", ## args) +#define sslEapDebug(args...) ssl_secinfo("sslEap", ## args) /* ECDSA */ -#define sslEcdsaDebug(args...) ssl_secdebug("sslEcdsa", ## args) +#define sslEcdsaDebug(args...) ssl_secinfo("sslEcdsa", ## args) #else /* NDEBUG */ @@ -110,13 +110,13 @@ extern void SSLDump(const unsigned char *data, unsigned long len); /* extra debug logging of non-error conditions, if SSL_DEBUG is defined */ #if SSL_DEBUG //#define sslDebugLog(args...) printf(args) -#define sslDebugLog(args...) ssl_secdebug("sslDebug", ## args) +#define sslDebugLog(args...) ssl_secinfo("sslDebug", ## args) #else #define sslDebugLog(args...) #endif /* all errors logged to stdout for DEBUG config only */ //#define sslErrorLog(args...) printf(args) -#define sslErrorLog(args...) ssl_secdebug("sslError", ## args) +#define sslErrorLog(args...) ssl_secinfo("sslError", ## args) #define sslDump(d, l) SSLDump((d), (l)) #endif /* NDEBUG */ diff --git a/OSX/libsecurity_ssl/lib/sslKeychain.c b/OSX/libsecurity_ssl/lib/sslKeychain.c index c561c0a2..feadf29a 100644 --- a/OSX/libsecurity_ssl/lib/sslKeychain.c +++ b/OSX/libsecurity_ssl/lib/sslKeychain.c @@ -40,7 +40,6 @@ #include "sslDebug.h" #include "sslKeychain.h" -#include "sslUtils.h" #include #include diff --git a/OSX/libsecurity_ssl/lib/sslRecord.c b/OSX/libsecurity_ssl/lib/sslRecord.c index 601761f4..d5ec8974 100644 --- a/OSX/libsecurity_ssl/lib/sslRecord.c +++ b/OSX/libsecurity_ssl/lib/sslRecord.c @@ -31,7 +31,6 @@ #include "sslMemory.h" #include "sslContext.h" #include "sslDebug.h" -#include "sslUtils.h" #include "SSLRecordInternal.h" #include diff --git a/OSX/libsecurity_ssl/lib/sslTransport.c b/OSX/libsecurity_ssl/lib/sslTransport.c index 8bd50bca..0be0d389 100644 --- a/OSX/libsecurity_ssl/lib/sslTransport.c +++ b/OSX/libsecurity_ssl/lib/sslTransport.c @@ -31,12 +31,15 @@ #include "sslRecord.h" #include "sslDebug.h" #include "sslCipherSpecs.h" -#include "sslUtils.h" #include #include #include +#include + +#include +#include #ifndef NDEBUG static inline void sslIoTrace( @@ -57,7 +60,6 @@ extern int kSplitDefaultValue; static OSStatus SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx); static OSStatus SSLHandshakeProceed(SSLContext *ctx); -//static OSStatus SSLInitConnection(SSLContext *ctx); OSStatus SSLWrite( @@ -75,7 +77,6 @@ SSLWrite( return errSecParam; } dataLen = dataLength; - processed = 0; /* Initialize in case we return with errSSLWouldBlock */ *bytesWritten = 0; switch(ctx->state) { @@ -98,7 +99,6 @@ SSLWrite( /* First, we have to wait until the session is ready to send data, so the encryption keys and such have been established. */ - err = errSecSuccess; while (!(ctx->writeCipher_ready)) { if ((err = SSLHandshakeProceed(ctx)) != 0) goto exit; @@ -113,7 +113,6 @@ SSLWrite( /* Skip empty writes, fragmentation is done at the coreTLS layer */ if(dataLen) { rec.contentType = SSL_RecordTypeAppData; - rec.protocolVersion = ctx->negProtocolVersion; rec.contents.data = ((uint8_t *)data) + processed; rec.contents.length = dataLen; if ((err = SSLWriteRecord(rec, ctx)) != 0) @@ -133,13 +132,14 @@ exit: case errSSLUnexpectedRecord: case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ case errSSLClientCertRequested: - case errSSLClosedGraceful: - break; - default: - sslErrorLog("SSLWrite: going to state errorClose due to err %d\n", - (int)err); - SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); - break; + case errSSLClientHelloReceived: + case errSSLClosedGraceful: + break; + default: + sslErrorLog("SSLWrite: going to state errorClose due to err %d\n", + (int)err); + SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); + break; } abort: sslIoTrace(ctx, "SSLWrite(2)", dataLength, *bytesWritten, err); @@ -183,25 +183,31 @@ readRetry: /* First, we have to wait until the session is ready to receive data, so the encryption keys and such have been established. */ - err = errSecSuccess; while (ctx->readCipher_ready == 0) { if ((err = SSLHandshakeProceed(ctx)) != 0) { goto exit; } } + /* Need this to handle the case were SSLRead returned + errSSLClientHelloReceived as readCipher_ready is not set yet in that case */ + if ((err = tls_handshake_continue(ctx->hdsk)) != 0) + return err; + /* Attempt to service the write queue */ if ((err = SSLServiceWriteQueue(ctx)) != 0) { if (err != errSSLWouldBlock) { goto exit; } - err = errSecSuccess; /* Write blocking shouldn't stop attempts to read */ } remaining = bufSize; charPtr = (uint8_t *)data; + + /* If we have data in the buffer, use that first */ if (ctx->receivedDataBuffer.data) - { count = ctx->receivedDataBuffer.length - ctx->receivedDataPos; + { + count = ctx->receivedDataBuffer.length - ctx->receivedDataPos; if (count > bufSize) count = bufSize; memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count); @@ -217,29 +223,27 @@ readRetry: if (ctx->receivedDataBuffer.data != 0 && ctx->receivedDataPos >= ctx->receivedDataBuffer.length) - { SSLFreeBuffer(&ctx->receivedDataBuffer); + { + SSLFreeBuffer(&ctx->receivedDataBuffer); ctx->receivedDataBuffer.data = 0; ctx->receivedDataPos = 0; } /* - * This while statement causes a hang when using nonblocking low-level I/O! - while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose) - ..what we really have to do is just return as soon as we read one - record. A performance hit in the nonblocking case, but that is - the only way this code can work in both modes... + * If we didnt fill up the users buffer, get some more data */ if (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose) - { assert(ctx->receivedDataBuffer.data == 0); + { + assert(ctx->receivedDataBuffer.data == 0); if ((err = SSLReadRecord(&rec, ctx)) != 0) { goto exit; } if (rec.contentType == SSL_RecordTypeAppData || rec.contentType == SSL_RecordTypeV2_0) - { if (rec.contents.length <= remaining) - { memcpy(charPtr, rec.contents.data, rec.contents.length); - remaining -= rec.contents.length; - charPtr += rec.contents.length; + { + if (rec.contents.length <= remaining) + { /* Copy all we got in the user's buffer */ + memcpy(charPtr, rec.contents.data, rec.contents.length); *processed += rec.contents.length; { if ((err = SSLFreeRecord(rec, ctx))) { @@ -248,12 +252,11 @@ readRetry: } } else - { memcpy(charPtr, rec.contents.data, remaining); - charPtr += remaining; + { /* Copy what we can in the user's buffer, keep the rest for next SSLRead. */ + memcpy(charPtr, rec.contents.data, remaining); *processed += remaining; ctx->receivedDataBuffer = rec.contents; ctx->receivedDataPos = remaining; - remaining = 0; } } else { @@ -262,7 +265,7 @@ readRetry: process the write queue. This replicate exactly the behavior before the coreTLS adoption */ if(err == errSSLClosedGraceful) { - err = SSLClose(ctx); + SSLClose(ctx); } else { goto exit; } @@ -282,20 +285,21 @@ exit: goto readRetry; } /* shut down on serious errors */ - switch(err) { - case errSecSuccess: - case errSSLWouldBlock: + switch(err) { + case errSecSuccess: + case errSSLWouldBlock: case errSSLUnexpectedRecord: - case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ - case errSSLClientCertRequested: - case errSSLClosedGraceful: - case errSSLClosedNoNotify: - break; - default: - sslErrorLog("SSLRead: going to state errorClose due to err %d\n", - (int)err); - SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); - break; + case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */ + case errSSLClientCertRequested: + case errSSLClientHelloReceived: + case errSSLClosedGraceful: + case errSSLClosedNoNotify: + break; + default: + sslErrorLog("SSLRead: going to state errorClose due to err %d\n", + (int)err); + SSLChangeHdskState(ctx, SSL_HdskStateErrorClose); + break; } abort: sslIoTrace(ctx, "SSLRead returns", dataLength, *processed, err); @@ -306,6 +310,85 @@ abort: #include "sslCrypto.h" #endif + + +static void get_extended_peer_id(SSLContext *ctx, tls_buffer *extended_peer_id) +{ + uint8_t md[CC_SHA256_DIGEST_LENGTH]; + __block CC_SHA256_CTX hash_ctx; + + CC_SHA256_Init(&hash_ctx); + + CC_SHA256_Update(&hash_ctx, &ctx->allowAnyRoot, sizeof(ctx->allowAnyRoot)); + +#if !TARGET_OS_IPHONE + if(ctx->trustedLeafCerts) { + CFArrayForEach(ctx->trustedLeafCerts, ^(const void *value) { + SecCertificateRef cert = (SecCertificateRef) value; + CC_SHA256_Update(&hash_ctx, SecCertificateGetBytePtr(cert), (CC_LONG)SecCertificateGetLength(cert)); + }); + } +#endif + + CC_SHA256_Update(&hash_ctx, &ctx->trustedCertsOnly, sizeof(ctx->trustedCertsOnly)); + + + if(ctx->trustedCerts) { + CFArrayForEach(ctx->trustedCerts, ^(const void *value) { + SecCertificateRef cert = (SecCertificateRef) value; + CC_SHA256_Update(&hash_ctx, SecCertificateGetBytePtr(cert), (CC_LONG)SecCertificateGetLength(cert)); + }); + } + + CC_SHA256_Final(md, &hash_ctx); + + extended_peer_id->length = ctx->peerID.length + sizeof(md); + extended_peer_id->data = sslMalloc(extended_peer_id->length); + memcpy(extended_peer_id->data, ctx->peerID.data, ctx->peerID.length); + memcpy(extended_peer_id->data+ctx->peerID.length, md, sizeof(md)); +} + +/* Send the initial client hello */ +static OSStatus +SSLHandshakeStart(SSLContext *ctx) +{ + int err; + tls_buffer extended_peer_id; + get_extended_peer_id(ctx, &extended_peer_id); + err = tls_handshake_negotiate(ctx->hdsk, &extended_peer_id); + free(extended_peer_id.data); + if(err) + return err; + + ctx->readCipher_ready = 0; + ctx->writeCipher_ready = 0; + SSLChangeHdskState(ctx, SSL_HdskStatePending); + + return noErr; +} + +OSStatus +SSLReHandshake(SSLContext *ctx) +{ + if(ctx == NULL) { + return errSecParam; + } + + if (ctx->state == SSL_HdskStateGracefulClose) + return errSSLClosedGraceful; + if (ctx->state == SSL_HdskStateErrorClose) + return errSSLClosedAbort; + if (ctx->state == SSL_HdskStatePending) + return errSecBadReq; + + /* If we are the client, we start the negotiation */ + if(ctx->protocolSide == kSSLClientSide) { + return SSLHandshakeStart(ctx); + } else { + return tls_handshake_request_renegotiation(ctx->hdsk); + } +} + OSStatus SSLHandshake(SSLContext *ctx) { @@ -319,8 +402,6 @@ SSLHandshake(SSLContext *ctx) if (ctx->state == SSL_HdskStateErrorClose) return errSSLClosedAbort; - err = errSecSuccess; - if(ctx->isDTLS && ctx->timeout_deadline) { CFAbsoluteTime current = CFAbsoluteTimeGetCurrent(); @@ -333,12 +414,23 @@ SSLHandshake(SSLContext *ctx) } } - while (ctx->readCipher_ready == 0 || ctx->writeCipher_ready == 0) - { + /* Initial Client Hello */ + if(ctx->state==SSL_HdskStateUninit) { + /* If we are the client, we start the negotiation */ + if(ctx->protocolSide == kSSLClientSide) { + err = SSLHandshakeStart(ctx); + if(err) { + return err; + } + } + SSLChangeHdskState(ctx, SSL_HdskStatePending); + } + + do { err = SSLHandshakeProceed(ctx); if((err != 0) && (err != errSSLUnexpectedRecord)) return err; - } + } while (ctx->readCipher_ready == 0 || ctx->writeCipher_ready == 0); /* one more flush at completion of successful handshake */ if ((err = SSLServiceWriteQueue(ctx)) != 0) { @@ -391,10 +483,10 @@ static void ad_log_SecureTransport_early_fail(long signature) CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature); - if(key) + if(key) { gADClientAddValueForScalarKey(key, 1); - - CFRelease(key); + CFRelease(key); + } } } @@ -431,22 +523,12 @@ static void log_SecureTransport_early_fail(long signature) #endif } + static OSStatus SSLHandshakeProceed(SSLContext *ctx) { OSStatus err; - - if(ctx->state==SSL_HdskStateUninit) { - /* If we are the client, we start the negotiation */ - if(ctx->protocolSide == kSSLClientSide) { - err = tls_handshake_negotiate(ctx->hdsk, &ctx->peerID); - if(err) - return err; - } - SSLChangeHdskState(ctx, SSL_HdskStatePending); - } - if ((err = tls_handshake_continue(ctx->hdsk)) != 0) return err; diff --git a/OSX/libsecurity_ssl/lib/sslTypes.h b/OSX/libsecurity_ssl/lib/sslTypes.h index d3a56ba8..2c9d3f08 100644 --- a/OSX/libsecurity_ssl/lib/sslTypes.h +++ b/OSX/libsecurity_ssl/lib/sslTypes.h @@ -96,7 +96,6 @@ struct typedef struct { uint8_t contentType; - SSLProtocolVersion protocolVersion; SSLBuffer contents; } SSLRecord; diff --git a/OSX/libsecurity_ssl/lib/sslUtils.c b/OSX/libsecurity_ssl/lib/sslUtils.c deleted file mode 100644 index 0390dc78..00000000 --- a/OSX/libsecurity_ssl/lib/sslUtils.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2008,2010-2012,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@ - */ - -/* - * sslUtils.c - Misc. OS independant SSL utility functions - */ - -/* THIS FILE CONTAINS KERNEL CODE */ - -#include "sslUtils.h" -#include "sslTypes.h" -#include "sslDebug.h" - -#include - -#ifndef NDEBUG -void SSLDump(const unsigned char *data, unsigned long len) -{ - unsigned long i; - for(i=0;i 0 && length <= 4); //anything else would be an internal error. - while (length--) - val = (val << 8) | *p++; - return val; -} - -uint8_t * -SSLEncodeInt(uint8_t *p, size_t value, size_t length) -{ - unsigned char *retVal = p + length; /* Return pointer to char after int */ - check(length > 0 && length <= 4); //anything else would be an internal error. - while (length--) /* Assemble backwards */ - { p[length] = (uint8_t)value; /* Implicit masking to low byte */ - value >>= 8; - } - return retVal; -} - -size_t -SSLDecodeSize(const uint8_t *p, size_t length) -{ - unsigned int val = 0; - check(length > 0 && length <= 4); //anything else would be an internal error. - while (length--) - val = (val << 8) | *p++; - return val; -} - -uint8_t * -SSLEncodeSize(uint8_t *p, size_t value, size_t length) -{ - unsigned char *retVal = p + length; /* Return pointer to char after int */ - check(length > 0 && length <= 4); //anything else would be an internal error. - while (length--) /* Assemble backwards */ - { p[length] = (uint8_t)value; /* Implicit masking to low byte */ - value >>= 8; - } - return retVal; -} - - -uint8_t * -SSLEncodeUInt64(uint8_t *p, uint64_t value) -{ - p = SSLEncodeInt(p, (value>>32)&0xffffffff, 4); - return SSLEncodeInt(p, value&0xffffffff, 4); -} - - -void -IncrementUInt64(sslUint64 *v) -{ - (*v)++; -} - -void -SSLDecodeUInt64(const uint8_t *p, size_t length, uint64_t *v) -{ - check(length > 0 && length <= 8); - if(length<=4) { - *v=SSLDecodeInt(p, length); - } else { - *v=((uint64_t)SSLDecodeInt(p, length-4))<<32 | SSLDecodeInt(p+length-4, 4); - } -} - - -#if SSL_DEBUG - -const char *protocolVersStr(SSLProtocolVersion prot) -{ - switch(prot) { - case SSL_Version_Undetermined: return "SSL_Version_Undetermined"; - case SSL_Version_2_0: return "SSL_Version_2_0"; - case SSL_Version_3_0: return "SSL_Version_3_0"; - case TLS_Version_1_0: return "TLS_Version_1_0"; - case TLS_Version_1_1: return "TLS_Version_1_1"; - case TLS_Version_1_2: return "TLS_Version_1_2"; - default: sslErrorLog("protocolVersStr: bad prot\n"); return "BAD PROTOCOL"; - } - return NULL; /* NOT REACHED */ -} - -#endif /* SSL_DEBUG */ - - - diff --git a/OSX/libsecurity_ssl/lib/sslUtils.h b/OSX/libsecurity_ssl/lib/sslUtils.h deleted file mode 100644 index 992b6ffd..00000000 --- a/OSX/libsecurity_ssl/lib/sslUtils.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2000-2001,2005-2007,2010-2012,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@ - */ - -/* - * sslUtils.h - - Misc. OS independant SSL utility functions - */ - -#ifndef _SSLUTILS_H_ -#define _SSLUTILS_H_ 1 - -#include "sslTypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -uint32_t SSLDecodeInt( - const uint8_t * p, - size_t length); -uint8_t *SSLEncodeInt( - uint8_t *p, - size_t value, - size_t length); - -/* Same, but the value to encode is a size_t */ -size_t SSLDecodeSize( - const uint8_t * p, - size_t length); -uint8_t *SSLEncodeSize( - uint8_t *p, - size_t value, - size_t length); - -/* Same but for 64bits int */ -uint8_t* SSLEncodeUInt64( - uint8_t *p, - sslUint64 value); -void IncrementUInt64( - sslUint64 *v); -void SSLDecodeUInt64( - const uint8_t *p, - size_t length, - sslUint64 *v); - -static inline -int SSLHandshakeHeaderSize(SSLRecord *rec) -{ - if(rec->protocolVersion==DTLS_Version_1_0) - return 12; - else - return 4; -} - -#ifndef NDEBUG -extern const char *protocolVersStr(SSLProtocolVersion prot); -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/OSX/libsecurity_ssl/lib/tlsCallbacks.c b/OSX/libsecurity_ssl/lib/tlsCallbacks.c index 95827179..5bad6e77 100644 --- a/OSX/libsecurity_ssl/lib/tlsCallbacks.c +++ b/OSX/libsecurity_ssl/lib/tlsCallbacks.c @@ -28,11 +28,12 @@ #include "sslCrypto.h" #include "sslDebug.h" #include "sslMemory.h" -#include "appleSession.h" #include #include #include "utilities/SecCFRelease.h" +#include +#include static int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type) @@ -65,8 +66,7 @@ tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t // Need to call this here, in case SetCertificate was already called. myCtx->clientCertState = kSSLClientCertRequested; myCtx->clientAuthTypes = tls_handshake_get_peer_acceptable_client_auth_type(myCtx->hdsk, &myCtx->numAuthTypes); - SSLUpdateNegotiatedClientAuthType(myCtx); - if (myCtx->breakOnCertRequest && (myCtx->localCert==NULL)) { + if (myCtx->breakOnCertRequest && (myCtx->localCertArray==NULL)) { myCtx->signalCertRequest = true; err = errSSLClientCertRequested; } @@ -93,7 +93,7 @@ tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t case tls_handshake_message_certificate: /* For clients, we only check the cert when we receive the ServerHelloDone message. For servers, we check the client's cert right here. For both we set the public key */ - err = tls_set_peer_pubkey(myCtx); + err = tls_helper_set_peer_pubkey(myCtx->hdsk); if(!err && (myCtx->protocolSide == kSSLServerSide)) { err = tls_verify_peer_cert(myCtx); } @@ -199,22 +199,28 @@ int tls_handshake_set_protocol_version_callback(tls_handshake_ctx_t ctx, static int tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer sessionData) { + int err = errSSLSessionNotFound; SSLContext *myCtx = (SSLContext *)ctx; + sslDebugLog("%s: %p, key len=%zd, k[0]=%02x, data len=%zd\n", __FUNCTION__, myCtx, sessionKey.length, sessionKey.data[0], sessionData.length); - return sslAddSession(sessionKey, sessionData, myCtx->sessionCacheTimeout); + + if(myCtx->cache) { + err = tls_cache_save_session_data(myCtx->cache, &sessionKey, &sessionData, myCtx->sessionCacheTimeout); + } + return err; } static int tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer *sessionData) { SSLContext *myCtx = (SSLContext *)ctx; - int err; + int err = errSSLSessionNotFound; SSLFreeBuffer(&myCtx->resumableSession); - err = sslCopySession(sessionKey, &myCtx->resumableSession); - + if(myCtx->cache) { + err = tls_cache_load_session_data(myCtx->cache, &sessionKey, &myCtx->resumableSession); + } sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx, sessionKey.length, sessionData->length, err); - *sessionData = myCtx->resumableSession; return err; @@ -223,16 +229,26 @@ tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sess static int tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey) { + int err = errSSLSessionNotFound; + SSLContext *myCtx = (SSLContext *)ctx; + sslDebugLog("%p, key len=%zd k[0]=%02x\n", ctx, sessionKey.length, sessionKey.data[0]); - return sslDeleteSession(sessionKey); + if(myCtx->cache) { + err = tls_cache_delete_session_data(myCtx->cache, &sessionKey); + } + return err; } static int tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx) { + SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p\n", ctx); - return sslCleanupSession(); + if(myCtx->cache) { + tls_cache_empty(myCtx->cache); + } + return 0; } tls_handshake_callbacks_t tls_handshake_callbacks = { @@ -250,5 +266,3 @@ tls_handshake_callbacks_t tls_handshake_callbacks = { .advance_read_cipher = tls_handshake_advance_read_cipher_callback, .set_protocol_version = tls_handshake_set_protocol_version_callback, }; - - diff --git a/OSX/libsecurity_ssl/lib/tls_record_internal.h b/OSX/libsecurity_ssl/lib/tls_record_internal.h index 76fa58b3..00c8facc 100644 --- a/OSX/libsecurity_ssl/lib/tls_record_internal.h +++ b/OSX/libsecurity_ssl/lib/tls_record_internal.h @@ -60,7 +60,6 @@ typedef struct WaitingRecord struct SSLRecordInternalContext { tls_record_t filter; - bool dtls; /* Reference back to the SSLContext */ SSLContextRef sslCtx; diff --git a/OSX/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj b/OSX/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj index ae2f87c0..fd242111 100644 --- a/OSX/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_ssl/libsecurity_ssl.xcodeproj/project.pbxproj @@ -63,8 +63,8 @@ 0C80AB1317E9025B008F7F5B /* sslCrypto.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C80AB1217E9025B008F7F5B /* sslCrypto.c */; }; 0C86A5FD19705A08009B006A /* ssl-52-noconn.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C86A5FC19705A08009B006A /* ssl-52-noconn.c */; }; 0C8DD1561B1CF75400D43050 /* ssl-54-dhe.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C8DD1531B1CEE9A00D43050 /* ssl-54-dhe.c */; }; + 0C9A76A81CB478D7002111EE /* ssl-56-renegotiate.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CD3A1951CB466DB00667E3F /* ssl-56-renegotiate.c */; }; 0CA9800617E3925A00205D87 /* sslKeychain.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF4230534D89900303760 /* sslKeychain.c */; }; - 0CA9800917E7734000205D87 /* appleSession.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF3FF0534D89900303760 /* appleSession.c */; }; 0CA9803417E7899B00205D87 /* SSLRecordInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA413A15C75863002AEC4C /* SSLRecordInternal.c */; }; 0CB3EC4818AEDB6B00647921 /* ssl-48-split.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CB3EC4718AEDB6B00647921 /* ssl-48-split.c */; }; 0CCA417915C89EA3002AEC4C /* ssl-39-echo.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CCA416815C89EA3002AEC4C /* ssl-39-echo.c */; }; @@ -84,7 +84,6 @@ 4CAFF4540534D89900303760 /* sslContext.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF41A0534D89900303760 /* sslContext.c */; }; 4CAFF4640534D89900303760 /* sslRecord.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42A0534D89900303760 /* sslRecord.c */; }; 4CAFF4680534D89900303760 /* sslTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42E0534D89900303760 /* sslTransport.c */; }; - 4CAFF4690534D89900303760 /* sslUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFF42F0534D89900303760 /* sslUtils.c */; }; AAB589F216CACE540071FE64 /* ssl-44-crashes.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CC954F0161A62AE005D3D4A /* ssl-44-crashes.c */; }; /* End PBXBuildFile section */ @@ -190,11 +189,10 @@ 0CCA42EB15C8A71A002AEC4C /* sslAppUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sslAppUtils.h; path = sslViewer/sslAppUtils.h; sourceTree = SOURCE_ROOT; }; 0CCAB6191B3C93E100C97526 /* ssl-55-sessioncache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-55-sessioncache.c"; sourceTree = ""; }; 0CCF28B7166D5F5000AFA37C /* ssl-47-falsestart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-47-falsestart.c"; sourceTree = ""; }; + 0CD3A1951CB466DB00667E3F /* ssl-56-renegotiate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-56-renegotiate.c"; sourceTree = ""; }; 0CDDC9A6195CD44400E93A27 /* ssl-51-state.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-51-state.c"; sourceTree = ""; }; 0CEA459218CF71AE00BD32A9 /* ssl-49-sni.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "ssl-49-sni.c"; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_ssl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_ssl.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 4CAFF3FF0534D89900303760 /* appleSession.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = appleSession.c; sourceTree = ""; }; - 4CAFF4000534D89900303760 /* appleSession.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = appleSession.h; sourceTree = ""; }; 4CAFF4020534D89900303760 /* cipherSpecs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cipherSpecs.h; sourceTree = ""; }; 4CAFF4030534D89900303760 /* CipherSuite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CipherSuite.h; sourceTree = ""; }; 4CAFF4090534D89900303760 /* SecureTransport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SecureTransport.h; sourceTree = ""; }; @@ -202,7 +200,7 @@ 4CAFF4170534D89900303760 /* sslBuildFlags.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslBuildFlags.h; sourceTree = ""; }; 4CAFF41A0534D89900303760 /* sslContext.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslContext.c; sourceTree = ""; }; 4CAFF41B0534D89900303760 /* sslContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslContext.h; sourceTree = ""; }; - 4CAFF41C0534D89900303760 /* sslDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslDebug.h; sourceTree = ""; }; + 4CAFF41C0534D89900303760 /* sslDebug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = sslDebug.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 4CAFF4230534D89900303760 /* sslKeychain.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslKeychain.c; sourceTree = ""; }; 4CAFF4240534D89900303760 /* sslKeychain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sslKeychain.h; sourceTree = ""; }; 4CAFF4260534D89900303760 /* sslMemory.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = sslMemory.c; sourceTree = ""; }; @@ -260,7 +258,6 @@ 050651C7056A83F3008AD683 /* Apple Custom */ = { isa = PBXGroup; children = ( - 4CAFF3FF0534D89900303760 /* appleSession.c */, 4CAFF4230534D89900303760 /* sslKeychain.c */, ); name = "Apple Custom"; @@ -368,6 +365,7 @@ 0C4B8F391A895D6E00AE503B /* ssl-53-clientauth.c */, 0C8DD1531B1CEE9A00D43050 /* ssl-54-dhe.c */, 0CCAB6191B3C93E100C97526 /* ssl-55-sessioncache.c */, + 0CD3A1951CB466DB00667E3F /* ssl-56-renegotiate.c */, 0C6C634215D1BDCF00BC68CD /* ssl-utils.c */, 0C6C634415D1BE3900BC68CD /* ssl-utils.h */, 0C0E0469162CA288009F7C71 /* ssl_regressions.h */, @@ -445,7 +443,6 @@ 0CCA413715C75863002AEC4C /* sslCipherSpecs.h */, 0CCA413B15C75863002AEC4C /* SSLRecordInternal.h */, 0CCA414215C75863002AEC4C /* tls_record_internal.h */, - 4CAFF4000534D89900303760 /* appleSession.h */, 4CAFF4020534D89900303760 /* cipherSpecs.h */, 4CAFF40B0534D89900303760 /* ssl.h */, 4CAFF4170534D89900303760 /* sslBuildFlags.h */, @@ -572,7 +569,7 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_ssl" */; compatibilityVersion = "Xcode 3.2"; @@ -618,6 +615,7 @@ 0C8DD1561B1CF75400D43050 /* ssl-54-dhe.c in Sources */, 0CCAB61A1B3C93E100C97526 /* ssl-55-sessioncache.c in Sources */, 0C0F140B191AC0A200481BA2 /* ssl-50-server.c in Sources */, + 0C9A76A81CB478D7002111EE /* ssl-56-renegotiate.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -648,14 +646,12 @@ 0C1F06F7189B1F0600E65030 /* sslMemory.c in Sources */, 0C80AB1317E9025B008F7F5B /* sslCrypto.c in Sources */, 0CA9803417E7899B00205D87 /* SSLRecordInternal.c in Sources */, - 0CA9800917E7734000205D87 /* appleSession.c in Sources */, 0CA9800617E3925A00205D87 /* sslKeychain.c in Sources */, 0C03D65917DFD8C00087643B /* sslCipherSpecs.c in Sources */, 4CAFF4540534D89900303760 /* sslContext.c in Sources */, 0C03D65B17DFE67E0087643B /* tlsCallbacks.c in Sources */, 4CAFF4640534D89900303760 /* sslRecord.c in Sources */, 4CAFF4680534D89900303760 /* sslTransport.c in Sources */, - 4CAFF4690534D89900303760 /* sslUtils.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -755,6 +751,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = BE6A959D14E3700A00C158E0 /* debug.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + ENABLE_TESTABILITY = YES; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; }; name = Debug; @@ -763,6 +762,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = BE6A959F14E3700A00C158E0 /* release.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; SDKROOT = macosx.internal; }; name = Release; diff --git a/OSX/libsecurity_ssl/regressions/ssl-39-echo.c b/OSX/libsecurity_ssl/regressions/ssl-39-echo.c index 10fa94f6..80020471 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-39-echo.c +++ b/OSX/libsecurity_ssl/regressions/ssl-39-echo.c @@ -625,7 +625,7 @@ static void *securetransport_ssl_thread(void *arg) unsigned char ibuf[4096], obuf[4096]; size_t len; if (ssl->is_server) { - SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf); + require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf),out, ortn = -1); require_noerr_quiet(ortn = SSLWrite(ctx, obuf, sizeof(obuf), &len), out); require_action_quiet(len == sizeof(obuf), out, ortn = -1); } diff --git a/OSX/libsecurity_ssl/regressions/ssl-41-clientauth.c b/OSX/libsecurity_ssl/regressions/ssl-41-clientauth.c index b9f63642..35ddfc4b 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-41-clientauth.c +++ b/OSX/libsecurity_ssl/regressions/ssl-41-clientauth.c @@ -13,6 +13,7 @@ #include #include #include +#include #if TARGET_OS_IPHONE #include @@ -333,6 +334,7 @@ static void tests(void) is(CFGetRetainCount(privKey), 1, "privKey rc = 1"); ok(ctx=SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType), "SSLNewContext"); + require(ctx, errOut); ok_status(SSLSetCertificate(ctx, trust_chain), "SSLSetCertificate"); CFReleaseSafe(ctx); @@ -343,6 +345,7 @@ static void tests(void) is(CFGetRetainCount(privKey), 1, "privKey rc = 1"); ok(ctx=SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType), "SSLCreateContext"); + require(ctx, errOut); ok_status(SSLSetCertificate(ctx, trust_chain), "SSLSetCertificate"); CFReleaseSafe(ctx); @@ -353,6 +356,7 @@ static void tests(void) is(CFGetRetainCount(privKey), 1, "privKey rc = 1"); ok(ctx=SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType), "SSLCreateContext"); + require(ctx, errOut); ok_status(SSLSetCertificate(ctx, trust_chain), "SSLSetCertificate"); ok_status(SSLSetCertificate(ctx, trust_chain), "SSLSetCertificate"); CFReleaseSafe(ctx); @@ -363,6 +367,7 @@ static void tests(void) is(CFGetRetainCount(cert2), 1, "cert2 rc = 1"); is(CFGetRetainCount(privKey), 1, "privKey rc = 1"); +errOut: CFReleaseNull(trust_chain); } diff --git a/OSX/libsecurity_ssl/regressions/ssl-42-ciphers.c b/OSX/libsecurity_ssl/regressions/ssl-42-ciphers.c index c07b4126..c5c27d6f 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-42-ciphers.c +++ b/OSX/libsecurity_ssl/regressions/ssl-42-ciphers.c @@ -74,7 +74,8 @@ static const SSLCipherSuite SupportedCipherSuites[] = { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, - // TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + /* RC4 */ + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, @@ -90,6 +91,12 @@ static const SSLCipherSuite SupportedCipherSuites[] = { SSL_DH_anon_WITH_RC4_128_MD5, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_anon_WITH_NULL_SHA, + TLS_ECDH_anon_WITH_RC4_128_SHA, + TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_anon_WITH_AES_128_CBC_SHA, + TLS_ECDH_anon_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, diff --git a/OSX/libsecurity_ssl/regressions/ssl-43-ciphers.c b/OSX/libsecurity_ssl/regressions/ssl-43-ciphers.c index 47250db0..e7d89c94 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-43-ciphers.c +++ b/OSX/libsecurity_ssl/regressions/ssl-43-ciphers.c @@ -89,10 +89,13 @@ */ -#define OPENSSL_SERVER "ariadne.apple.com" + +//#define OPENSSL_SERVER "ariadne.apple.com" +//#define GNUTLS_SERVER "ariadne.apple.com" //#define OPENSSL_SERVER "kuip.apple.com" -#define GNUTLS_SERVER "ariadne.apple.com" //#define GNUTLS_SERVER "kuip.apple.com" +#define OPENSSL_SERVER "192.168.2.1" +#define GNUTLS_SERVER "192.168.2.1" static struct { const char *host; @@ -185,26 +188,6 @@ const CipherSuiteName ciphers[] = { CIPHER(3, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, {0, 0, 0, 0}, false) // Not supported by either gnutls or openssl #endif -#if 1 - /* ECDH_ECDSA cipher suites */ - CIPHER(1, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, {4, 0, 0, 1}, false) - CIPHER(1, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, {4, 0, 0, 1}, false) - CIPHER(1, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, {4, 0, 0, 1}, false) - CIPHER(3, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, {0, 0, 0, 1}, false) - CIPHER(1, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, {4, 0, 0, 1}, false) - CIPHER(3, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, {0, 0, 0, 1}, false) -#endif - -#if 1 - /* ECDH_RSA cipher suites */ - CIPHER(1, TLS_ECDH_RSA_WITH_RC4_128_SHA, {3, 0, 0, 1}, false) - CIPHER(1, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, {3, 0, 0, 1}, false) - CIPHER(1, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, {3, 0, 0, 1}, false) - CIPHER(3, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, {0, 0, 0, 1}, false) - CIPHER(1, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, {3, 0, 0, 1}, false) - CIPHER(3, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, {0, 0, 0, 1}, false) -#endif - #if 0 CIPHER(1, TLS_PSK_WITH_RC4_128_SHA, {1, 1, 0, 0}, true) CIPHER(1, TLS_PSK_WITH_3DES_EDE_CBC_SHA, {1, 1, 0, 0}, true) @@ -227,12 +210,6 @@ const CipherSuiteName ciphers[] = { CIPHER(3, TLS_DH_anon_WITH_AES_128_GCM_SHA256, {1, 1, 0, 0}, true) CIPHER(3, TLS_DH_anon_WITH_AES_256_GCM_SHA384, {1, 0, 0, 0}, true) - CIPHER(3, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, {3, 0, 0, 0}, false) - CIPHER(3, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, {3, 0, 0, 0}, false) - - CIPHER(3, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, {4, 0, 0, 0}, false) - CIPHER(3, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, {4, 0, 0, 0}, false) - CIPHER(3, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, {1, 1, 0, 0}, false) CIPHER(3, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, {1, 1, 0, 0}, false) @@ -505,6 +482,8 @@ static OSStatus securetransport(ssl_test_handle * ssl) SSLContextRef ctx = ssl->st; SecTrustRef trust = NULL; bool got_server_auth = false, got_client_cert_req = false; + CFMutableArrayRef peer_cert_array = NULL; + CFMutableArrayRef orig_peer_cert_array = NULL; //uint64_t start = mach_absolute_time(); do { @@ -524,8 +503,8 @@ static OSStatus securetransport(ssl_test_handle * ssl) CFIndex n_certs = SecTrustGetCertificateCount(trust); /*fprintf(stderr, "%ld certs; trust_eval: %d\n", n_certs, trust_result); */ - CFMutableArrayRef peer_cert_array = CFArrayCreateMutable(NULL, n_certs, &kCFTypeArrayCallBacks); - CFMutableArrayRef orig_peer_cert_array = CFArrayCreateMutableCopy(NULL, n_certs, ssl->certs); + peer_cert_array = CFArrayCreateMutable(NULL, n_certs, &kCFTypeArrayCallBacks); + orig_peer_cert_array = CFArrayCreateMutableCopy(NULL, n_certs, ssl->certs); while (n_certs--) CFArrayInsertValueAtIndex(peer_cert_array, 0, SecTrustGetCertificateAtIndex(trust, n_certs)); @@ -539,8 +518,6 @@ static OSStatus securetransport(ssl_test_handle * ssl) #if 0 require(CFEqual(orig_peer_cert_array, peer_cert_array), out); #endif - CFRelease(orig_peer_cert_array); - CFRelease(peer_cert_array); /* CFStringRef cert_name = SecCertificateCopySubjectSummary(cert); @@ -610,6 +587,8 @@ static OSStatus securetransport(ssl_test_handle * ssl) #endif out: + CFReleaseSafe(orig_peer_cert_array); + CFReleaseSafe(peer_cert_array); SSLClose(ctx); SSLDisposeContext(ctx); if (trust) CFRelease(trust); @@ -688,6 +667,7 @@ tests(void) ok(!ok, "Handshake failed: %40s to %s:%d proto=%d", ciphers[i].name, servers[p].host, port, pr); close(s); + free(client); } /* SKIP block */ } diff --git a/OSX/libsecurity_ssl/regressions/ssl-44-crashes.c b/OSX/libsecurity_ssl/regressions/ssl-44-crashes.c index dda31178..0967e6dc 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-44-crashes.c +++ b/OSX/libsecurity_ssl/regressions/ssl-44-crashes.c @@ -206,7 +206,7 @@ static void *securetransport_ssl_thread(void *arg) unsigned char ibuf[8], obuf[8]; size_t len; if (ssl->is_server) { - SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf); + require_action_quiet(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, sizeof(obuf), obuf), out, ortn = -1); require_noerr_quiet(ortn = SSLWrite(ctx, obuf, sizeof(obuf), &len), out); require_action_quiet(len == sizeof(obuf), out, ortn = -1); } else { @@ -296,17 +296,9 @@ tests(void) pthread_join(client_thread, (void*)&client_err); pthread_join(server_thread, (void*)&server_err); - // errors expected for TARGET_OS_IPHONE implementation - int expected_client_error3 = errSSLBadCert; - int expected_server_error3 = errSSLClosedGraceful; - - // allow OS X errors if we are not yet using unified SecTrust - if (server_err == errSSLProtocol) { expected_server_error3 = errSSLProtocol; } - if (client_err == errSSLIllegalParam) { expected_client_error3 = errSSLIllegalParam; } - - ok(server_err==((i==3)?expected_server_error3:0), "Server error = %d (i=%d)", server_err, i); - /* tests 0/1 should cause errSSLClosedAbort, 2 should cause errSSLBadRecordMac, 3 should cause errSSLBadCert */ - ok(client_err==((i==3)?expected_client_error3:(i==2)?errSSLBadRecordMac:errSSLClosedAbort), "Client error = %d (i=%d)", client_err, i); + ok(server_err==((i==3)?errSSLPeerCertUnknown:0), "Server error = %d (i=%d)", server_err, i); + /* tests 0/1 should cause errSSLClosedAbort, 2 should cause errSSLBadRecordMac, 3 should cause errSSLXCertChainInvalid */ + ok(client_err==((i==3)?errSSLXCertChainInvalid:(i==2)?errSSLBadRecordMac:errSSLClosedAbort), "Client error = %d (i=%d)", client_err, i); out: free(client); diff --git a/OSX/libsecurity_ssl/regressions/ssl-45-tls12.c b/OSX/libsecurity_ssl/regressions/ssl-45-tls12.c index 67e2ea4a..9708d7c7 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-45-tls12.c +++ b/OSX/libsecurity_ssl/regressions/ssl-45-tls12.c @@ -97,31 +97,17 @@ static int SocketConnect(const char *hostName, int port) int err; struct hostent *ent; - if (hostName[0] >= '0' && hostName[0] <= '9') - { + if (hostName[0] >= '0' && hostName[0] <= '9') { host.s_addr = inet_addr(hostName); - } - else { - unsigned dex; -#define GETHOST_RETRIES 5 - /* seeing a lot of soft failures here that I really don't want to track down */ - for(dex=0; dexh_addr, sizeof(struct in_addr)); } - sock = socket(AF_INET, SOCK_STREAM, 0); addr.sin_addr = host; addr.sin_port = htons((u_short)port); @@ -132,7 +118,7 @@ static int SocketConnect(const char *hostName, int port) if(err!=0) { perror("connect failed"); - return err; + return -1; } return sock; @@ -268,12 +254,17 @@ out: +#define CONNECT_TRIES 3 + static ssl_test_handle * ssl_test_handle_create(struct s_server *server) { - int comm; + int comm = -1; + + for(int try = 0; comm<0 && tryhost, server->port); + } - comm=SocketConnect(server->host, server->port); if(comm<0) { fail("connect failed with err=%d - %s:%d", comm, server->host, server->port); return NULL; @@ -307,7 +298,7 @@ struct s_server servers[] = { {"www.amazon.com",443, kTLSProtocol12 }, //{"www.mikestoolbox.org",443, kTLSProtocol12 }, /* servers with issues */ - {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version + // This server went offline as of May 2016 -- {"vpp.visa.co.uk", 443, kTLSProtocol12 }, // Doesnt like SSL 3.0 in initial record layer version {"imap.softbank.jp",993, kTLSProtocol12 }, // softbank imap server, there are multiple servers behind this, one of them is not able to handle downgrading to TLS 1.2 properly (126.240.66.17). {"mobile.charter.net",993, kTLSProtocol12 }, // Support 1.2 but fail to negotiate properly {"mybill.vodafone.com.au", 443, kTLSProtocol1 }, /* 2056 bit server key */ diff --git a/OSX/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c b/OSX/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c index cf3b3b3f..2ed75a8b 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c +++ b/OSX/libsecurity_ssl/regressions/ssl-46-SSLGetSupportedCiphers.c @@ -241,6 +241,14 @@ const SSLCipherSuite TLSv1_fallback_ciphersuites[] = { SSL_RSA_WITH_3DES_EDE_CBC_SHA, }; +const SSLCipherSuite anonymous_ciphersuites[] = { + TLS_ECDH_anon_WITH_AES_256_CBC_SHA, + TLS_ECDH_anon_WITH_AES_128_CBC_SHA, + TLS_DH_anon_WITH_AES_256_CBC_SHA256, + TLS_DH_anon_WITH_AES_256_CBC_SHA, + TLS_DH_anon_WITH_AES_128_CBC_SHA256, + TLS_DH_anon_WITH_AES_128_CBC_SHA +}; static int test_GetEnabledCiphers(SSLContextRef ssl, unsigned expected_num_ciphers, const SSLCipherSuite *expected_ciphers) @@ -251,8 +259,8 @@ static int test_GetEnabledCiphers(SSLContextRef ssl, unsigned expected_num_ciphe SSLCipherSuite *ciphers = NULL; OSStatus err; - err=SSLSetIOFuncs(ssl, &SocketRead, &SocketWrite); - err=SSLSetConnection(ssl, NULL); + require_noerr(SSLSetIOFuncs(ssl, &SocketRead, &SocketWrite), out); + require_noerr(SSLSetConnection(ssl, NULL), out); require_noerr(SSLGetNumberEnabledCiphers(ssl, &num_ciphers), out); require_string(num_ciphers==expected_num_ciphers, out, "wrong ciphersuites number"); @@ -268,8 +276,8 @@ static int test_GetEnabledCiphers(SSLContextRef ssl, unsigned expected_num_ciphe free(ciphers); ciphers = NULL; - err=SSLHandshake(ssl); - + err = SSLHandshake(ssl); + require(err == errSSLWouldBlock, out); require_noerr(SSLGetNumberEnabledCiphers(ssl, &num_ciphers), out); require_string(num_ciphers==expected_num_ciphers, out, "wrong ciphersuites number"); @@ -373,17 +381,47 @@ out: if(ssl) CFRelease(ssl); } +static void +test_default(SSLProtocolSide side) +{ + SSLContextRef ssl = NULL; + bool server = (side == kSSLServerSide); + + ssl=SSLCreateContext(kCFAllocatorDefault, side, kSSLStreamType); + ok(ssl, "test_config: SSLCreateContext(1) failed (%s)", server?"server":"client"); + require(ssl, out); + + /* The order of this tests does matter, be careful when adding tests */ + ok(!test_GetSupportedCiphers(ssl, server), "test_default: GetSupportedCiphers test failed (%s)", server?"server":"client"); + ok(!test_GetEnabledCiphers(ssl, sizeof(standard_ciphersuites)/sizeof(SSLCipherSuite), standard_ciphersuites), "test_default: GetEnabledCiphers test failed (%s)", server?"server":"client"); + + CFRelease(ssl); ssl=NULL; + + ssl=SSLCreateContext(kCFAllocatorDefault, side, kSSLStreamType); + ok(ssl, "test_default: SSLCreateContext(2) failed (%s)", server?"server":"client"); + require(ssl, out); + + ok(!test_SetEnabledCiphers(ssl), "test_config: SetEnabledCiphers test failed (%s)", server?"server":"client"); + +out: + if(ssl) CFRelease(ssl); +} + + int ssl_46_SSLGetSupportedCiphers(int argc, char *const *argv) { - plan_tests(132); + plan_tests(154); test_dhe(kSSLClientSide, true); test_dhe(kSSLServerSide, true); test_dhe(kSSLClientSide, false); test_dhe(kSSLServerSide, false); + test_default(kSSLClientSide); + test_default(kSSLServerSide); + #define TEST_CONFIG(x, y) do { \ test_config(kSSLClientSide, x, sizeof(y)/sizeof(SSLCipherSuite), y); \ test_config(kSSLServerSide, x, sizeof(y)/sizeof(SSLCipherSuite), y); \ @@ -397,7 +435,8 @@ int ssl_46_SSLGetSupportedCiphers(int argc, char *const *argv) TEST_CONFIG(kSSLSessionConfig_RC4_fallback, legacy_ciphersuites); TEST_CONFIG(kSSLSessionConfig_TLSv1_fallback, standard_ciphersuites); TEST_CONFIG(kSSLSessionConfig_TLSv1_RC4_fallback, legacy_ciphersuites); - TEST_CONFIG(kSSLSessionConfig_default, legacy_ciphersuites); + TEST_CONFIG(kSSLSessionConfig_default, standard_ciphersuites); + TEST_CONFIG(kSSLSessionConfig_anonymous, anonymous_ciphersuites); return 0; } diff --git a/OSX/libsecurity_ssl/regressions/ssl-47-falsestart.c b/OSX/libsecurity_ssl/regressions/ssl-47-falsestart.c index 90e7d6c2..d7c43e00 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-47-falsestart.c +++ b/OSX/libsecurity_ssl/regressions/ssl-47-falsestart.c @@ -81,35 +81,21 @@ static int SocketConnect(const char *hostName, int port) { struct sockaddr_in addr; struct in_addr host; - int sock; + int sock; int err; struct hostent *ent; - if (hostName[0] >= '0' && hostName[0] <= '9') - { + if (hostName[0] >= '0' && hostName[0] <= '9') { host.s_addr = inet_addr(hostName); - } - else { - unsigned dex; -#define GETHOST_RETRIES 5 - /* seeing a lot of soft failures here that I really don't want to track down */ - for(dex=0; dexh_addr, sizeof(struct in_addr)); } - sock = socket(AF_INET, SOCK_STREAM, 0); addr.sin_addr = host; addr.sin_port = htons((u_short)port); @@ -120,17 +106,15 @@ static int SocketConnect(const char *hostName, int port) if(err!=0) { perror("connect failed"); - return err; + return -1; } /* make non blocking */ fcntl(sock, F_SETFL, O_NONBLOCK); - return sock; } - static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length) { size_t len = *length; @@ -224,8 +208,9 @@ static OSStatus securetransport(ssl_test_handle * ssl) bool got_server_auth = false, got_client_cert_req = false; ortn = SSLHandshake(ctx); - //fprintf(stderr, "Fell out of SSLHandshake with error: %ld\n", (long)ortn); - + + require_action_quiet(ortn==errSSLWouldBlock, out, printf("SSLHandshake failed with err %ld\n", (long)ortn)); + size_t sent, received; const char *r=request; size_t l=sizeof(request); @@ -306,6 +291,7 @@ struct s_server { #define NSERVERS (int)(sizeof(servers)/sizeof(servers[0])) #define NLOOPS 1 +#define CONNECT_TRIES 3 static void tests(void) @@ -318,11 +304,13 @@ tests(void) for(fs=0;fs<2; fs++) { ssl_test_handle *client; - - int s; OSStatus r; + int s = -1; + + for(int try = 0; s<0 && tryis_server) { size_t len; - SecRandomCopyBytes(kSecRandomDefault, ssl->write_size, obuf); + require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, ssl->write_size, obuf), out, ortn = -1); require_noerr(ortn = SSLWrite(ctx, obuf, ssl->write_size, &len), out); require_action(len == ssl->write_size, out, ortn = -1); require_noerr(ortn = SSLWrite(ctx, obuf, ssl->write_size, &len), out); diff --git a/OSX/libsecurity_ssl/regressions/ssl-49-sni.c b/OSX/libsecurity_ssl/regressions/ssl-49-sni.c index 0afdde59..2a661339 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-49-sni.c +++ b/OSX/libsecurity_ssl/regressions/ssl-49-sni.c @@ -147,12 +147,14 @@ static void *securetransport_server_thread(void *arg) "SNI does not match"); } require_noerr(SSLSetCertificate(ctx, server_certs), out); + free(sni); } out: SSLClose(ctx); SSLDisposeContext(ctx); close(ssl->comm); + CFReleaseSafe(server_certs); pthread_exit((void *)(intptr_t)ortn); return NULL; @@ -214,7 +216,8 @@ ssl_test_handle_create(uint32_t session_id, bool server, int comm) return handle; out: - if (ctx) CFRelease(ctx); + if (handle) free(handle); + if (ctx) CFRelease(ctx); return NULL; } diff --git a/OSX/libsecurity_ssl/regressions/ssl-51-state.c b/OSX/libsecurity_ssl/regressions/ssl-51-state.c index 66790429..91a48385 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-51-state.c +++ b/OSX/libsecurity_ssl/regressions/ssl-51-state.c @@ -172,6 +172,7 @@ static int process(tls_stream_parser_ctx_t ctx, tls_buffer record) test_printf("%s: %p processed, err=%d\n", __FUNCTION__, ctx, err); errOut: + free(decrypted.data); return err; } diff --git a/OSX/libsecurity_ssl/regressions/ssl-52-noconn.c b/OSX/libsecurity_ssl/regressions/ssl-52-noconn.c index d0e329ea..b3e3028f 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-52-noconn.c +++ b/OSX/libsecurity_ssl/regressions/ssl-52-noconn.c @@ -28,6 +28,8 @@ void tests() ortn = SSLHandshake(ctx); is(ortn, errSSLWouldBlock, "SSLHandshake unexpected return\n"); + + CFRelease(ctx); } diff --git a/OSX/libsecurity_ssl/regressions/ssl-53-clientauth.c b/OSX/libsecurity_ssl/regressions/ssl-53-clientauth.c index 47d19094..bd0aaea6 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-53-clientauth.c +++ b/OSX/libsecurity_ssl/regressions/ssl-53-clientauth.c @@ -393,8 +393,6 @@ tests(void) ssl_server_handle_destroy(server); ssl_client_handle_destroy(client); - close(sp[0]); - close(sp[1]); CFReleaseSafe(client_certs); } diff --git a/OSX/libsecurity_ssl/regressions/ssl-54-dhe.c b/OSX/libsecurity_ssl/regressions/ssl-54-dhe.c index 55fb18d3..d1ef7824 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-54-dhe.c +++ b/OSX/libsecurity_ssl/regressions/ssl-54-dhe.c @@ -389,9 +389,6 @@ tests(void) ssl_server_handle_destroy(server); ssl_client_handle_destroy(client); - close(sp[0]); - close(sp[1]); - } } diff --git a/OSX/libsecurity_ssl/regressions/ssl-55-sessioncache.c b/OSX/libsecurity_ssl/regressions/ssl-55-sessioncache.c index 9563d7ec..8f9add5b 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-55-sessioncache.c +++ b/OSX/libsecurity_ssl/regressions/ssl-55-sessioncache.c @@ -100,7 +100,7 @@ typedef struct { } ssl_client_handle; static ssl_client_handle * -ssl_client_handle_create(int comm, CFArrayRef trustedCA, uint32_t cache_ttl, uintptr_t peerID) +ssl_client_handle_create(int comm, bool anyRoot, CFArrayRef trustedCA, bool trustedCAOnly, CFArrayRef trustedLeafs, uint32_t cache_ttl, uintptr_t peerID) { ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle)); SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); @@ -115,7 +115,11 @@ ssl_client_handle_create(int comm, CFArrayRef trustedCA, uint32_t cache_ttl, uin require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name, strlen(peer_domain_name)), out); - require_noerr(SSLSetTrustedRoots(ctx, trustedCA, true), out); + require_noerr(SSLSetAllowsAnyRoot(ctx, anyRoot), out); + require_noerr(SSLSetTrustedRoots(ctx, trustedCA, trustedCAOnly), out); +#if !TARGET_OS_IPHONE + require_noerr(SSLSetTrustedLeafCertificates(ctx, trustedLeafs), out); +#endif require_noerr(SSLSetSessionCacheTimeout(ctx, cache_ttl), out); @@ -263,35 +267,35 @@ out: static void -tests(void) +tests_cache_ttl(void) { pthread_t client_thread, server_thread; CFArrayRef server_certs = server_chain(); CFArrayRef trusted_ca = trusted_roots(); - ok(server_certs, "got server certs"); - ok(trusted_ca, "got trusted roots"); + ok(server_certs, "ttl: got server certs"); + ok(trusted_ca, "ttl: got trusted roots"); int i, j, k; - for (i=0; i<2; i++) { - for (j=0; j<2; j++) { + for (i=0; i<2; i++) { // client cache TTL + for (j=0; j<2; j++) { // Server cache TTL for (k=0; k<2; k++) { + ssl_client_handle *client = NULL; + ssl_server_handle *server = NULL; int sp[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno); fcntl(sp[0], F_SETNOSIGPIPE, 1); fcntl(sp[1], F_SETNOSIGPIPE, 1); - ssl_client_handle *client; - client = ssl_client_handle_create(sp[0], trusted_ca, i, (i<<8)|(j+1)); - ok(client!=NULL, "could not create client handle (%d:%d:%d)", i, j, k); - + client = ssl_client_handle_create(sp[0], false, trusted_ca, true, NULL, i, (i<<8)|(j+1)); + ok(client!=NULL, "ttl: could not create client handle (%d:%d:%d)", i, j, k); + require(client, errOut); - ssl_server_handle *server; server = ssl_server_handle_create(sp[1], server_certs, j); - ok(server!=NULL, "could not create server handle (%d:%d:%d)", i, j, k); - + ok(server!=NULL, "ttl: could not create server handle (%d:%d:%d)", i, j, k); + require(server, errOut); pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client); pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server); @@ -304,19 +308,18 @@ tests(void) unsigned char sessionID[32]; size_t sessionIDLength = sizeof(sessionID); - ok(client_err==0, "unexpected error %ld (client %d:%d:%d)", client_err, i, j, k); - ok(server_err==0, "unexpected error %ld (server %d:%d:%d)", server_err, i, j, k); + ok(client_err==0, "ttl: unexpected error %ld (client %d:%d:%d)", client_err, i, j, k); + ok(server_err==0, "ttl: unexpected error %ld (server %d:%d:%d)", server_err, i, j, k); ok_status(SSLGetResumableSessionInfo(client->st, &resumed, sessionID, &sessionIDLength), "SSLGetResumableSessionInfo"); - ok(i || j || (!k) || resumed, "Unexpected resumption state=%d (%d:%d:%d)", resumed, i, j, k); + ok((bool)resumed == (bool)(k && (!i) && (!j)), "ttl: Unexpected resumption state=%d (%d:%d:%d)", resumed, i, j, k); + errOut: ssl_server_handle_destroy(server); ssl_client_handle_destroy(client); - close(sp[0]); - close(sp[1]); - /* Sleep one second so that Session cache TTL can expire */ - sleep(1); + /* Sleep two seconds so that Session cache TTL can expire */ + sleep(2); } } } @@ -325,13 +328,96 @@ tests(void) CFReleaseSafe(trusted_ca); } +static void +tests_cache_trust(void) +{ + pthread_t client_thread, server_thread; + CFArrayRef server_certs = server_chain(); + CFArrayRef trusted_ca = trusted_roots(); + CFMutableArrayRef trusted_ca2 = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, trusted_ca); + CFArrayAppendArray(trusted_ca2, trusted_ca, CFRangeMake(0, CFArrayGetCount(trusted_ca))); + + ok(server_certs, "trust: got server certs"); + ok(trusted_ca, "trust: got trusted roots"); + ok(trusted_ca2, "trust: got trusted roots extra"); + + int any, ca, caonly, leaf, k; + + // Test cache and trust options: + + + for (any=0; any<2; any++) // any root ? + for (ca=0; ca<2; ca++) // trustedCA ? + for (caonly=0; caonly<2; caonly++) // leaf> +#if TARGET_OS_IPHONE + { + leaf = 0; +#else + for (leaf=0; leaf<2; leaf++) + { +#endif + // attempt initial connection, then resumed connection, but all with same peer id (0xdeadbeef) + for (k=0; k<2; k++) { + ssl_client_handle *client = NULL; + ssl_server_handle *server = NULL; + + int sp[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno); + fcntl(sp[0], F_SETNOSIGPIPE, 1); + fcntl(sp[1], F_SETNOSIGPIPE, 1); + + client = ssl_client_handle_create(sp[0], any, ca?trusted_ca:trusted_ca2, caonly, leaf?NULL:trusted_ca, 300, 0xdeadbeef); + ok(client!=NULL, "trust: could not create client handle (%d:%d:%d:%d:%d)", any, ca, caonly, leaf, k); + require(client, errOut); + + server = ssl_server_handle_create(sp[1], server_certs, 300); + ok(server!=NULL, "trust: could not create server handle (%d:%d:%d:%d:%d)", any, ca, caonly, leaf, k); + require(server, errOut); + + pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client); + pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server); + + intptr_t server_err, client_err; + + pthread_join(client_thread, (void*)&client_err); + pthread_join(server_thread, (void*)&server_err); + + Boolean resumed; + unsigned char sessionID[32]; + size_t sessionIDLength = sizeof(sessionID); + + ok(client_err==0, "trust: unexpected error %ld (client %d:%d:%d:%d:%d)", client_err, any, ca, caonly, leaf, k); + ok(server_err==0, "trust: unexpected error %ld (server %d:%d:%d:%d:%d)", server_err, any, ca, caonly, leaf, k); + ok_status(SSLGetResumableSessionInfo(client->st, &resumed, sessionID, &sessionIDLength), "SSLGetResumableSessionInfo"); + + ok((bool)resumed == (bool)(k), "trust: Unexpected resumption state=%d (%d:%d:%d:%d:%d)", resumed, any, ca, caonly, leaf, k); + + errOut: + ssl_server_handle_destroy(server); + ssl_client_handle_destroy(client); + + } + } + + CFReleaseSafe(server_certs); + CFReleaseSafe(trusted_ca); +} + int ssl_55_sessioncache(int argc, char *const *argv) { - plan_tests(6 * 8 + 2 /*cert*/); +#if TARGET_OS_IPHONE +#define N_TRUST_TESTS 8 +#else +#define N_TRUST_TESTS 16 +#endif + + plan_tests(/*ttl :*/ 6 * 8 + 2 + /* trust:*/ N_TRUST_TESTS*6*2 + 3); + + tests_cache_ttl(); - tests(); + tests_cache_trust(); return 0; } diff --git a/OSX/libsecurity_ssl/regressions/ssl-56-renegotiate.c b/OSX/libsecurity_ssl/regressions/ssl-56-renegotiate.c new file mode 100644 index 00000000..a6525dbf --- /dev/null +++ b/OSX/libsecurity_ssl/regressions/ssl-56-renegotiate.c @@ -0,0 +1,464 @@ + +#include +#include +#include +#include +#include + +#include + +#include +#include /* SSLSetOption */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if TARGET_OS_IPHONE +#include +#endif + +#include "ssl_regressions.h" +#include "ssl-utils.h" + +/* + SSL Renegotiation tests: + + Test both the client and server side. + + Test Goal: + - Make sure that renegotiation works on both client and server. + + Behavior to verify: + - handshake pass or fail + +*/ + + +static OSStatus SocketWrite(SSLConnectionRef conn, const void *data, size_t *length) +{ + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + do { + ssize_t ret; + do { + ret = write((int)conn, ptr, len); + } while ((ret < 0) && (errno == EAGAIN || errno == EINTR)); + if (ret > 0) { + len -= ret; + ptr += ret; + } + else + return -36; + } while (len > 0); + + *length = *length - len; + return errSecSuccess; +} + +static OSStatus SocketRead(SSLConnectionRef conn, void *data, size_t *length) +{ + size_t len = *length; + uint8_t *ptr = (uint8_t *)data; + + do { + ssize_t ret; + do { + ret = read((int)conn, ptr, len); + } while ((ret < 0) && (errno == EINPROGRESS || errno == EAGAIN || errno == EINTR)); + if (ret > 0) { + len -= ret; + ptr += ret; + } else { + printf("read error(%d): ret=%zd, errno=%d\n", (int)conn, ret, errno); + return -errno; + } + } while (len > 0); + + *length = *length - len; + return errSecSuccess; +} + +typedef struct { + SSLContextRef st; + int comm; + unsigned dhe_size; + bool renegotiate; +} ssl_client_handle; + +static ssl_client_handle * +ssl_client_handle_create(int comm, bool renegotiate) +{ + ssl_client_handle *handle = calloc(1, sizeof(ssl_client_handle)); + SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType); + + require(handle, out); + require(ctx, out); + + require_noerr(SSLSetIOFuncs(ctx, + (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out); + static const char *peer_domain_name = "localhost"; + require_noerr(SSLSetPeerDomainName(ctx, peer_domain_name, + strlen(peer_domain_name)), out); + + require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, TRUE), out); + + require_noerr(SSLSetAllowsAnyRoot(ctx, TRUE), out); + + + handle->comm = comm; + handle->st = ctx; + handle->renegotiate = renegotiate; + + return handle; + +out: + if (ctx) + CFRelease(ctx); + if (handle) + free(handle); + + return NULL; +} + +static void +ssl_client_handle_destroy(ssl_client_handle *handle) +{ + if(handle) { + SSLClose(handle->st); + CFRelease(handle->st); + free(handle); + } +} + +static void *securetransport_ssl_client_thread(void *arg) +{ + OSStatus ortn; + ssl_client_handle * ssl = (ssl_client_handle *)arg; + SSLContextRef ctx = ssl->st; + SSLSessionState ssl_state; + bool peer_auth_received = false; + + pthread_setname_np("client thread"); + + require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out); + require_action(ssl_state==kSSLIdle, out, ortn = -1); + + do { + ortn = SSLHandshake(ctx); + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); + + if (ortn == errSSLPeerAuthCompleted) { + require_action(!peer_auth_received, out, ortn = -1); + peer_auth_received = true; + } + if (ortn == errSSLWouldBlock) { + require_string(ssl_state==kSSLHandshake, out, "Wrong client handshake state after errSSLWouldBlock"); + } + } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted); + + require_noerr(ortn, out); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + require_action(peer_auth_received, out, ortn = -1); + + if(ssl->renegotiate) { + // Renegotiate then write + require_noerr(SSLReHandshake(ctx), out); + + peer_auth_received = false; + + do { + ortn = SSLHandshake(ctx); + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); + if (ortn == errSSLPeerAuthCompleted) { + require_action(!peer_auth_received, out, ortn = -1); + peer_auth_received = true; + } + if (ortn == errSSLWouldBlock) { + require_action(ssl_state==kSSLHandshake, out, ortn = -1); + } + } while (ortn == errSSLWouldBlock || ortn == errSSLPeerAuthCompleted); + + require_noerr(ortn, out); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + require_action(peer_auth_received, out, ortn = -1); + + unsigned char obuf[100]; + + size_t len = sizeof(obuf); + size_t olen; + unsigned char *p = obuf; + + require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1); + + while (len) { + require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out); + len -= olen; + p += olen; + } + } else { + // just read. + unsigned char ibuf[100]; + + peer_auth_received = false; + + size_t len = sizeof(ibuf); + size_t olen; + unsigned char *p = ibuf; + while (len) { + ortn = SSLRead(ctx, p, len, &olen); + + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); + + if (ortn == errSSLPeerAuthCompleted) { + require_action(!peer_auth_received, out, ortn = -1); + peer_auth_received = true; + } else { + require_noerr(ortn, out); + } + + /* If we get data, we should have renegotiated */ + if(olen) { + require_noerr(ortn, out); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + require_action(peer_auth_received, out, ortn = -1); + } + + len -= olen; + p += olen; + } + } + +out: + SSLClose(ssl->st); + close(ssl->comm); + pthread_exit((void *)(intptr_t)ortn); + return NULL; +} + + +typedef struct { + SSLContextRef st; + int comm; + CFArrayRef certs; + bool renegotiate; +} ssl_server_handle; + +static ssl_server_handle * +ssl_server_handle_create(int comm, CFArrayRef certs, bool renegotiate) +{ + ssl_server_handle *handle = calloc(1, sizeof(ssl_server_handle)); + SSLContextRef ctx = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType); + SSLCipherSuite cipher = TLS_RSA_WITH_AES_256_CBC_SHA256; + + require(handle, out); + require(ctx, out); + + require_noerr(SSLSetIOFuncs(ctx, + (SSLReadFunc)SocketRead, (SSLWriteFunc)SocketWrite), out); + require_noerr(SSLSetConnection(ctx, (SSLConnectionRef)(intptr_t)comm), out); + + require_noerr(SSLSetCertificate(ctx, certs), out); + + require_noerr(SSLSetEnabledCiphers(ctx, &cipher, 1), out); + + require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnClientHello, TRUE), out); + require_noerr(SSLSetSessionOption(ctx, kSSLSessionOptionAllowRenegotiation, TRUE), out); + + handle->comm = comm; + handle->certs = certs; + handle->st = ctx; + handle->renegotiate = renegotiate; + + return handle; + +out: + if (ctx) + CFRelease(ctx); + if (handle) + free(handle); + + return NULL; +} + +static void +ssl_server_handle_destroy(ssl_server_handle *handle) +{ + if(handle) { + SSLClose(handle->st); + CFRelease(handle->st); + free(handle); + } +} + +static void *securetransport_ssl_server_thread(void *arg) +{ + OSStatus ortn; + ssl_server_handle * ssl = (ssl_server_handle *)arg; + SSLContextRef ctx = ssl->st; + SSLSessionState ssl_state; + bool client_hello_received = false; + + pthread_setname_np("server thread"); + + require_noerr(ortn=SSLGetSessionState(ctx,&ssl_state), out); + require_action(ssl_state==kSSLIdle, out, ortn = -1); + + do { + ortn = SSLHandshake(ctx); + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); + if (ortn == errSSLClientHelloReceived) { + require_action(!client_hello_received, out, ortn = -1); + client_hello_received = true; + } + if (ortn == errSSLWouldBlock) { + require_action(ssl_state==kSSLHandshake, out, ortn = -1); + } + } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived); + + require_noerr(ortn, out); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + require_action(client_hello_received, out, ortn = -1); + + if(ssl->renegotiate) { + // Renegotiate then write + require_noerr(SSLReHandshake(ctx), out); + + client_hello_received = false; + + do { + ortn = SSLHandshake(ctx); + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); + if (ortn == errSSLClientHelloReceived) { + require_action(!client_hello_received, out, ortn = -1); + client_hello_received = true; + } + if (ortn == errSSLWouldBlock) { + require_action(ssl_state==kSSLHandshake, out, ortn = -1); + } + } while (ortn == errSSLWouldBlock || ortn == errSSLClientHelloReceived); + + require_noerr(ortn, out); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + require_action(client_hello_received, out, ortn = -1); + + unsigned char obuf[100]; + + size_t len = sizeof(obuf); + size_t olen; + unsigned char *p = obuf; + + require_action(errSecSuccess==SecRandomCopyBytes(kSecRandomDefault, len, p), out, ortn = -1); + + while (len) { + require_noerr(ortn = SSLWrite(ctx, p, len, &olen), out); + len -= olen; + p += olen; + } + } else { + // just read + unsigned char ibuf[100]; + + client_hello_received = false; + + size_t len = sizeof(ibuf); + size_t olen; + unsigned char *p = ibuf; + while (len) { + ortn = SSLRead(ctx, p, len, &olen); + + require_noerr(SSLGetSessionState(ctx,&ssl_state), out); + + if (ortn == errSSLClientHelloReceived) { + require_action(!client_hello_received, out, ortn = -1); + client_hello_received = true; + } else { + require_noerr(ortn, out); + } + + /* If we get data, we should have renegotiated */ + if(olen) { + require_noerr(ortn, out); + require_action(ssl_state==kSSLConnected, out, ortn = -1); + require_action(client_hello_received, out, ortn = -1); + } + + len -= olen; + p += olen; + } + } + +out: + SSLClose(ssl->st); + close(ssl->comm); + pthread_exit((void *)(intptr_t)ortn); + return NULL; +} + + +static void +test_renego(bool client_renego) +{ + pthread_t client_thread, server_thread; + CFArrayRef server_certs = server_chain(); + + ok(server_certs, "renego: got server certs"); + + + int sp[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) exit(errno); + fcntl(sp[0], F_SETNOSIGPIPE, 1); + fcntl(sp[1], F_SETNOSIGPIPE, 1); + + ssl_client_handle *client; + client = ssl_client_handle_create(sp[0], client_renego); + ok(client!=NULL, "renego: could not create client handle"); + + + ssl_server_handle *server; + server = ssl_server_handle_create(sp[1], server_certs, !client_renego); + ok(server!=NULL, "renego: could not create server handle"); + + pthread_create(&client_thread, NULL, securetransport_ssl_client_thread, client); + pthread_create(&server_thread, NULL, securetransport_ssl_server_thread, server); + + intptr_t server_err, client_err; + + pthread_join(client_thread, (void*)&client_err); + pthread_join(server_thread, (void*)&server_err); + + ok(client_err==0, "renego: unexpected error %ld (client)", client_err); + ok(server_err==0, "renego: unexpected error %ld (server)", server_err); + + ssl_server_handle_destroy(server); + ssl_client_handle_destroy(client); + + + CFReleaseSafe(server_certs); +} + + +int ssl_56_renegotiate(int argc, char *const *argv) +{ + plan_tests(10); + + test_renego(false); // server side trigger renego. + test_renego(true); // client side trigger renego. + + return 0; +} diff --git a/OSX/libsecurity_ssl/regressions/ssl-utils.h b/OSX/libsecurity_ssl/regressions/ssl-utils.h index 3878afe4..68016da6 100644 --- a/OSX/libsecurity_ssl/regressions/ssl-utils.h +++ b/OSX/libsecurity_ssl/regressions/ssl-utils.h @@ -30,12 +30,12 @@ #define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) { CFRelease(_cf); } } #define CFReleaseNull(CF) { CFTypeRef _cf = (CF); if (_cf) { (CF) = NULL; CFRelease(_cf); } } -CFArrayRef trusted_roots(void); -CFArrayRef server_chain(void); -CFArrayRef server_ec_chain(void); -CFArrayRef trusted_client_chain(void); -CFArrayRef trusted_ec_client_chain(void); -CFArrayRef untrusted_client_chain(void); +CFArrayRef CF_RETURNS_RETAINED trusted_roots(void); +CFArrayRef CF_RETURNS_RETAINED server_chain(void); +CFArrayRef CF_RETURNS_RETAINED server_ec_chain(void); +CFArrayRef CF_RETURNS_RETAINED trusted_client_chain(void); +CFArrayRef CF_RETURNS_RETAINED trusted_ec_client_chain(void); +CFArrayRef CF_RETURNS_RETAINED untrusted_client_chain(void); #define client_chain trusted_client_chain diff --git a/OSX/libsecurity_ssl/regressions/ssl_regressions.h b/OSX/libsecurity_ssl/regressions/ssl_regressions.h index f4c4e7f3..4c1203b3 100644 --- a/OSX/libsecurity_ssl/regressions/ssl_regressions.h +++ b/OSX/libsecurity_ssl/regressions/ssl_regressions.h @@ -32,4 +32,5 @@ ONE_TEST(ssl_52_noconn) ONE_TEST(ssl_53_clientauth) ONE_TEST(ssl_54_dhe) ONE_TEST(ssl_55_sessioncache) +ONE_TEST(ssl_56_renegotiate) diff --git a/OSX/libsecurity_ssl/sslViewer/fileIo.c b/OSX/libsecurity_ssl/sslViewer/fileIo.c deleted file mode 100644 index 802de34e..00000000 --- a/OSX/libsecurity_ssl/sslViewer/fileIo.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2001-2003,2006-2012,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@ - */ - -/* - * fileIo.c - simple file read/write utilities - */ - -#include -#include -#include -#include -#include -#include -#include -#include "fileIo.h" - -int writeFile( - const char *fileName, - const unsigned char *bytes, - unsigned numBytes) -{ - int rtn; - int fd; - - fd = open(fileName, O_RDWR | O_CREAT | O_TRUNC, 0600); - if(fd < 0) { - return errno; - } - rtn = lseek(fd, 0, SEEK_SET); - if(rtn < 0) { - return errno; - } - rtn = write(fd, bytes, (size_t)numBytes); - if(rtn != (int)numBytes) { - if(rtn >= 0) { - printf("writeFile: short write\n"); - } - rtn = EIO; - } - else { - rtn = 0; - } - close(fd); - return rtn; -} - -/* - * Read entire file. - */ -int readFile( - const char *fileName, - unsigned char **bytes, // mallocd and returned - unsigned *numBytes) // returned -{ - int rtn; - int fd; - unsigned char *buf; - struct stat sb; - unsigned size; - - *numBytes = 0; - *bytes = NULL; - fd = open(fileName, O_RDONLY, 0); - if(fd < 0) { - return errno; - } - rtn = fstat(fd, &sb); - if(rtn) { - goto errOut; - } - size = sb.st_size; - buf = malloc(size); - if(buf == NULL) { - rtn = ENOMEM; - goto errOut; - } - rtn = lseek(fd, 0, SEEK_SET); - if(rtn < 0) { - goto errOut; - } - rtn = read(fd, buf, (size_t)size); - if(rtn != (int)size) { - if(rtn >= 0) { - printf("readFile: short read\n"); - } - rtn = EIO; - } - else { - rtn = 0; - *bytes = buf; - *numBytes = size; - } -errOut: - close(fd); - return rtn; -} diff --git a/OSX/libsecurity_ssl/sslViewer/ioSock.c b/OSX/libsecurity_ssl/sslViewer/ioSock.c deleted file mode 100644 index 3c9b12db..00000000 --- a/OSX/libsecurity_ssl/sslViewer/ioSock.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-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@ - */ - -/* - * ioSock.c - socket-based I/O routines for use with Secure Transport - */ - -#include "ioSock.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* debugging for this module */ -#define SSL_OT_DEBUG 1 - -/* log errors to stdout */ -#define SSL_OT_ERRLOG 1 - -/* trace all low-level network I/O */ -#define SSL_OT_IO_TRACE 0 - -/* if SSL_OT_IO_TRACE, only log non-zero length transfers */ -#define SSL_OT_IO_TRACE_NZ 1 - -/* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ -#define SSL_OT_IO_PAUSE 0 - -/* print a stream of dots while I/O pending */ -#define SSL_OT_DOT 1 - -/* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */ -#define SSL_OT_IO_DUMP 0 -#define SSL_OT_IO_DUMP_SIZE 256 - -/* indicate errSSLWouldBlock with a '.' */ -#define SSL_DISPL_WOULD_BLOCK 0 - -/* general, not-too-verbose debugging */ -#if SSL_OT_DEBUG -#define dprintf(s) printf s -#else -#define dprintf(s) -#endif - -/* errors --> stdout */ -#if SSL_OT_ERRLOG -#define eprintf(s) printf s -#else -#define eprintf(s) -#endif - -/* trace completion of every r/w */ -#if SSL_OT_IO_TRACE -static void tprintf( - const char *str, - UInt32 req, - UInt32 act, - const UInt8 *buf) -{ - #if SSL_OT_IO_TRACE_NZ - if(act == 0) { - return; - } - #endif - printf("%s(%u): moved (%u) bytes\n", str, (unsigned)req, (unsigned)act); - #if SSL_OT_IO_DUMP - { - unsigned i; - - for(i=0; i= (SSL_OT_IO_DUMP_SIZE - 1)) { - break; - } - } - printf("\n"); - } - #endif - #if SSL_OT_IO_PAUSE - { - char instr[20]; - printf("CR to continue: "); - gets(instr); - } - #endif -} - -#else -#define tprintf(str, req, act, buf) -#endif /* SSL_OT_IO_TRACE */ - -/* - * If SSL_OT_DOT, output a '.' every so often while waiting for - * connection. This gives user a chance to do something else with the - * UI. - */ - -#if SSL_OT_DOT - -static time_t lastTime = (time_t)0; -#define TIME_INTERVAL 3 - -static void outputDot() -{ - time_t thisTime = time(0); - - if((thisTime - lastTime) >= TIME_INTERVAL) { - printf("."); fflush(stdout); - lastTime = thisTime; - } -} -#else -#define outputDot() -#endif - - -/* - * One-time only init. - */ -void initSslOt(void) -{ - -} - -/* - * Connect to server. - */ -#define GETHOST_RETRIES 3 - -OSStatus MakeServerConnection( - const char *hostName, - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo, // RETURNED - PeerSpec *peer) // RETURNED -{ - struct sockaddr_in addr; - struct hostent *ent; - struct in_addr host; - int sock = 0; - - *socketNo = 0; - if (hostName[0] >= '0' && hostName[0] <= '9') - { - host.s_addr = inet_addr(hostName); - } - else { - unsigned dex; - /* seeing a lot of soft failures here that I really don't want to track down */ - for(dex=0; dexh_addr, sizeof(struct in_addr)); - } - sock = socket(AF_INET, SOCK_STREAM, 0); - addr.sin_addr = host; - addr.sin_port = htons((u_short)port); - - addr.sin_family = AF_INET; - if (connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) != 0) - { printf("connect returned error\n"); - return errSecIO; - } - - if(nonBlocking) { - /* OK to do this after connect? */ - int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); - if(rtn == -1) { - perror("fctnl(O_NONBLOCK)"); - return errSecIO; - } - } - - peer->ipAddr = addr.sin_addr.s_addr; - peer->port = htons((u_short)port); - *socketNo = (otSocket)sock; - return errSecSuccess; -} - -/* - * Set up an otSocket to listen for client connections. Call once, then - * use multiple AcceptClientConnection calls. - */ -OSStatus ListenForClients( - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo) // RETURNED -{ - struct sockaddr_in addr; - struct hostent *ent; - int len; - int sock; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 1) { - perror("socket"); - return errSecIO; - } - - int reuse = 1; - int err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); - if (err != 0) { - perror("setsockopt"); - return err; - } - - ent = gethostbyname("localhost"); - if (!ent) { - perror("gethostbyname"); - return errSecIO; - } - memcpy(&addr.sin_addr, ent->h_addr, sizeof(struct in_addr)); - - addr.sin_port = htons((u_short)port); - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_family = AF_INET; - len = sizeof(struct sockaddr_in); - if (bind(sock, (struct sockaddr *) &addr, len)) { - int theErr = errno; - perror("bind"); - if(theErr == EADDRINUSE) { - return errSecOpWr; - } - else { - return errSecIO; - } - } - if(nonBlocking) { - int rtn = fcntl(sock, F_SETFL, O_NONBLOCK); - if(rtn == -1) { - perror("fctnl(O_NONBLOCK)"); - return errSecIO; - } - } - - for(;;) { - int rtn = listen(sock, 1); - switch(rtn) { - case 0: - *socketNo = (otSocket)sock; - rtn = errSecSuccess; - break; - case EWOULDBLOCK: - continue; - default: - perror("listen"); - rtn = errSecIO; - break; - } - return rtn; - } - /* NOT REACHED */ - return 0; -} - -/* - * Accept a client connection. - */ - -/* - * Currently we always get back a different peer port number on successive - * connections, no matter what the client is doing. To test for resumable - * session support, force peer port = 0. - */ -#define FORCE_ACCEPT_PEER_PORT_ZERO 1 - -OSStatus AcceptClientConnection( - otSocket listenSock, // obtained from ListenForClients - otSocket *acceptSock, // RETURNED - PeerSpec *peer) // RETURNED -{ - struct sockaddr_in addr; - int sock; - socklen_t len; - - len = sizeof(struct sockaddr_in); - do { - sock = accept((int)listenSock, (struct sockaddr *) &addr, &len); - if (sock < 0) { - if(errno == EAGAIN) { - /* nonblocking, no connection yet */ - continue; - } - else { - perror("accept"); - return errSecIO; - } - } - else { - break; - } - } while(1); - *acceptSock = (otSocket)sock; - peer->ipAddr = addr.sin_addr.s_addr; - #if FORCE_ACCEPT_PEER_PORT_ZERO - peer->port = 0; - #else - peer->port = ntohs(addr.sin_port); - #endif - return errSecSuccess; -} - -/* - * Shut down a connection. - */ -void endpointShutdown( - otSocket sock) -{ - close((int)sock); -} - -/* - * R/W. Called out from SSL. - */ -OSStatus SocketRead( - SSLConnectionRef connection, - void *data, /* owned by - * caller, data - * RETURNED */ - size_t *dataLength) /* IN/OUT */ -{ - UInt32 bytesToGo = *dataLength; - UInt32 initLen = bytesToGo; - UInt8 *currData = (UInt8 *)data; - int sock = (int)((long)connection); - OSStatus rtn = errSecSuccess; - UInt32 bytesRead; - ssize_t rrtn; - - *dataLength = 0; - - for(;;) { - bytesRead = 0; - /* paranoid check, ensure errno is getting written */ - errno = -555; - rrtn = recv(sock, currData, bytesToGo, 0); - if (rrtn <= 0) { - if(rrtn == 0) { - /* closed, EOF */ - rtn = errSSLClosedGraceful; - break; - } - int theErr = errno; - switch(theErr) { - case ENOENT: - /* - * Undocumented but I definitely see this. - * Non-blocking sockets only. Definitely retriable - * just like an EAGAIN. - */ - dprintf(("SocketRead RETRYING on ENOENT, rrtn %d\n", - (int)rrtn)); - /* normal... */ - //rtn = errSSLWouldBlock; - /* ...for temp testing.... */ - rtn = errSecIO; - break; - case ECONNRESET: - /* explicit peer abort */ - rtn = errSSLClosedAbort; - break; - case EAGAIN: - /* nonblocking, no data */ - rtn = errSSLWouldBlock; - break; - default: - dprintf(("SocketRead: read(%u) error %d, rrtn %d\n", - (unsigned)bytesToGo, theErr, (int)rrtn)); - rtn = errSecIO; - break; - } - /* in any case, we're done with this call if rrtn <= 0 */ - break; - } - bytesRead = rrtn; - bytesToGo -= bytesRead; - currData += bytesRead; - - if(bytesToGo == 0) { - /* filled buffer with incoming data, done */ - break; - } - } - *dataLength = initLen - bytesToGo; - tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data); - - #if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE) - if((rtn == 0) && (*dataLength == 0)) { - /* keep UI alive */ - outputDot(); - } - #endif - #if SSL_DISPL_WOULD_BLOCK - if(rtn == errSSLWouldBlock) { - printf("."); fflush(stdout); - } - #endif - return rtn; -} - -int oneAtATime = 0; - -OSStatus SocketWrite( - SSLConnectionRef connection, - const void *data, - size_t *dataLength) /* IN/OUT */ -{ - size_t bytesSent = 0; - int sock = (int)((long)connection); - int length; - size_t dataLen = *dataLength; - const UInt8 *dataPtr = (UInt8 *)data; - OSStatus ortn; - - if(oneAtATime && (*dataLength > 1)) { - size_t i; - size_t outLen; - size_t thisMove; - - outLen = 0; - for(i=0; i 0) && - ( (bytesSent += length) < dataLen) ); - - if(length <= 0) { - int theErr = errno; - switch(theErr) { - case EAGAIN: - ortn = errSSLWouldBlock; break; - case EPIPE: - ortn = errSSLClosedAbort; break; - default: - dprintf(("SocketWrite: write(%u) error %d\n", - (unsigned)(dataLen - bytesSent), theErr)); - ortn = errSecIO; - break; - } - } - else { - ortn = errSecSuccess; - } - tprintf("SocketWrite", dataLen, bytesSent, dataPtr); - *dataLength = bytesSent; - return ortn; -} diff --git a/OSX/libsecurity_ssl/sslViewer/ioSock.h b/OSX/libsecurity_ssl/sslViewer/ioSock.h deleted file mode 100644 index 1faf47b4..00000000 --- a/OSX/libsecurity_ssl/sslViewer/ioSock.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012,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@ - */ - -/* - * ioSock.h - socket-based I/O routines for use with Secure Transport - */ - -#ifndef _IO_SOCK_H_ -#define _IO_SOCK_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Opaque reference to an Open Transport connection. - */ -typedef int otSocket; - -/* - * info about a peer returned from MakeServerConnection() and - * AcceptClientConnection(). - */ -typedef struct -{ UInt32 ipAddr; - int port; -} PeerSpec; - -/* - * Ont-time only init. - */ -void initSslOt(void); - -/* - * Connect to server. - */ -extern OSStatus MakeServerConnection( - const char *hostName, - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo, // RETURNED - PeerSpec *peer); // RETURNED - -/* - * Set up an otSocket to listen for client connections. Call once, then - * use multiple AcceptClientConnection calls. - */ -OSStatus ListenForClients( - int port, - int nonBlocking, // 0 or 1 - otSocket *socketNo); // RETURNED - -/* - * Accept a client connection. Call endpointShutdown() for each successful; - * return from this function. - */ -OSStatus AcceptClientConnection( - otSocket listenSock, // obtained from ListenForClients - otSocket *acceptSock, // RETURNED - PeerSpec *peer); // RETURNED - -/* - * Shut down a connection. - */ -void endpointShutdown( - otSocket socket); - -/* - * R/W. Called out from SSL. - */ -OSStatus SocketRead( - SSLConnectionRef connection, - void *data, /* owned by - * caller, data - * RETURNED */ - size_t *dataLength); /* IN/OUT */ - -OSStatus SocketWrite( - SSLConnectionRef connection, - const void *data, - size_t *dataLength); /* IN/OUT */ - -#ifdef __cplusplus -} -#endif - -#endif /* _IO_SOCK_H_ */ diff --git a/OSX/libsecurity_ssl/sslViewer/printCert.c b/OSX/libsecurity_ssl/sslViewer/printCert.c deleted file mode 100644 index 9857fe0a..00000000 --- a/OSX/libsecurity_ssl/sslViewer/printCert.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2003-2008,2011-2012,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@ - */ - -/* - * printCert.c - utility functions for printing certificate info - */ - -#include "printCert.h" -#include -#include -#include - -void fprint_string(CFStringRef string, FILE *file) { - UInt8 buf[256]; - CFRange range = { .location = 0 }; - range.length = CFStringGetLength(string); - while (range.length > 0) { - CFIndex bytesUsed = 0; - CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed); - fwrite(buf, 1, bytesUsed, file); - range.length -= converted; - range.location += converted; - } -} - -void print_line(CFStringRef line) { - fprint_string(line, stdout); - fputc('\n', stdout); -} - -static void printPlist(CFArrayRef plist, CFIndex indent, CFIndex maxWidth) { - CFIndex count = CFArrayGetCount(plist); - CFIndex ix; - for (ix = 0; ix < count ; ++ix) { - CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, - ix); - CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyType); - CFStringRef label = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyLabel); - CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyLocalizedLabel); - CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, - kSecPropertyKeyValue); - - bool isSection = CFEqual(pType, kSecPropertyTypeSection); - CFMutableStringRef line = CFStringCreateMutable(NULL, 0); - CFIndex jx = 0; - for (jx = 0; jx < indent; ++jx) { - CFStringAppend(line, CFSTR(" ")); - } - if (llabel) { - CFStringAppend(line, llabel); - if (!isSection) { - for (jx = CFStringGetLength(llabel) + indent * 4; - jx < maxWidth; ++jx) { - CFStringAppend(line, CFSTR(" ")); - } - CFStringAppend(line, CFSTR(" : ")); - } - } - if (CFEqual(pType, kSecPropertyTypeWarning)) { - CFStringAppend(line, CFSTR("*WARNING* ")); - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeError)) { - CFStringAppend(line, CFSTR("*ERROR* ")); - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeSuccess)) { - CFStringAppend(line, CFSTR("*OK* ")); - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeTitle)) { - CFStringAppend(line, CFSTR("*")); - CFStringAppend(line, (CFStringRef)value); - CFStringAppend(line, CFSTR("*")); - } else if (CFEqual(pType, kSecPropertyTypeSection)) { - } else if (CFEqual(pType, kSecPropertyTypeData)) { - CFDataRef data = (CFDataRef)value; - CFIndex length = CFDataGetLength(data); - if (length > 20) - CFStringAppendFormat(line, NULL, CFSTR("[%d bytes] "), length); - const UInt8 *bytes = CFDataGetBytePtr(data); - for (jx = 0; jx < length; ++jx) { - if (jx == 0) - CFStringAppendFormat(line, NULL, CFSTR("%02X"), bytes[jx]); - else if (jx < 15 || length <= 20) - CFStringAppendFormat(line, NULL, CFSTR(" %02X"), - bytes[jx]); - else { - CFStringAppend(line, CFSTR(" ...")); - break; - } - } - } else if (CFEqual(pType, kSecPropertyTypeString)) { - CFStringAppend(line, (CFStringRef)value); - } else if (CFEqual(pType, kSecPropertyTypeDate)) { - CFDateRef date = (CFDateRef)value; - CFLocaleRef lc = CFLocaleCopyCurrent(); - CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, kCFDateFormatterMediumStyle, kCFDateFormatterLongStyle); - CFStringRef ds; - if (df) { - CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(NULL, 0.0); - CFDateFormatterSetProperty(df, kCFDateFormatterTimeZone, tz); - CFRelease(tz); - ds = CFDateFormatterCreateStringWithDate(NULL, df, date); - CFRelease(df); - } else { - ds = CFStringCreateWithFormat(NULL, NULL, CFSTR("%g"), CFDateGetAbsoluteTime(date)); - } - CFStringAppend(line, ds); - CFRelease(ds); - CFRelease(lc); - } else if (CFEqual(pType, kSecPropertyTypeURL)) { - CFURLRef url = (CFURLRef)value; - CFStringAppend(line, CFSTR("<")); - CFStringAppend(line, CFURLGetString(url)); - CFStringAppend(line, CFSTR(">")); - } else { - CFStringAppendFormat(line, NULL, CFSTR("*unknown type %@* = %@"), - pType, value); - } - - if (!isSection || label) - print_line(line); - CFRelease(line); - if (isSection) { - printPlist((CFArrayRef)value, indent + 1, maxWidth); - } - } -} - -static CFIndex maxLabelWidth(CFArrayRef plist, CFIndex indent) { - CFIndex count = CFArrayGetCount(plist); - CFIndex ix; - CFIndex maxWidth = 0; - for (ix = 0; ix < count ; ++ix) { - CFDictionaryRef prop = (CFDictionaryRef)CFArrayGetValueAtIndex(plist, - ix); - CFStringRef pType = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyType); - CFStringRef llabel = (CFStringRef)CFDictionaryGetValue(prop, - kSecPropertyKeyLocalizedLabel); - CFTypeRef value = (CFTypeRef)CFDictionaryGetValue(prop, - kSecPropertyKeyValue); - - if (CFEqual(pType, kSecPropertyTypeSection)) { - CFIndex width = maxLabelWidth((CFArrayRef)value, indent + 1); - if (width > maxWidth) - maxWidth = width; - } else if (llabel) { - CFIndex width = indent * 4 + CFStringGetLength(llabel); - if (width > maxWidth) - maxWidth = width; - } - } - - return maxWidth; -} - -void print_plist(CFArrayRef plist) { - if (plist) - printPlist(plist, 0, maxLabelWidth(plist, 0)); - else - printf("NULL plist\n"); -} - -void print_cert(SecCertificateRef cert, bool verbose) { -// TODO: merge these when all SecCertificate APIs are present on both iOS and OS X -#if TARGET_OS_IOS - CFArrayRef plist; - if (verbose) - plist = SecCertificateCopyProperties(cert); - else { - CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); - plist = SecCertificateCopySummaryProperties(cert, now); - } - - CFStringRef subject = SecCertificateCopySubjectString(cert); - if (subject) { - print_line(subject); - CFRelease(subject); - } else { - print_line(CFSTR("no subject")); - } - - print_plist(plist); - CFRelease(plist); -#else - CFStringRef certName = NULL; - OSStatus status = SecCertificateInferLabel(cert, &certName); - if (certName) { - print_line(certName); - CFRelease(certName); - } - else { - fprintf(stdout, "ERROR: unable to read certificate name\n"); - } -#endif -} diff --git a/OSX/libsecurity_ssl/sslViewer/sslAppUtils.cpp b/OSX/libsecurity_ssl/sslViewer/sslAppUtils.cpp deleted file mode 100644 index e3ba62d1..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslAppUtils.cpp +++ /dev/null @@ -1,1592 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2014 Apple Inc. All Rights Reserved. - */ - -#include "sslAppUtils.h" -#include "fileIo.h" -#include -#include -#include -#include - -#include -#include -#include -#include - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } - -const char *sslGetCipherSuiteString(SSLCipherSuite cs) -{ - static char noSuite[40]; - - switch (cs) { - /* TLS cipher suites, RFC 2246 */ - case SSL_NULL_WITH_NULL_NULL: return "TLS_NULL_WITH_NULL_NULL"; - case SSL_RSA_WITH_NULL_MD5: return "TLS_RSA_WITH_NULL_MD5"; - case SSL_RSA_WITH_NULL_SHA: return "TLS_RSA_WITH_NULL_SHA"; - case SSL_RSA_EXPORT_WITH_RC4_40_MD5: return "TLS_RSA_EXPORT_WITH_RC4_40_MD5"; - case SSL_RSA_WITH_RC4_128_MD5: return "TLS_RSA_WITH_RC4_128_MD5"; - case SSL_RSA_WITH_RC4_128_SHA: return "TLS_RSA_WITH_RC4_128_SHA"; - case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: return "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; - case SSL_RSA_WITH_IDEA_CBC_SHA: return "TLS_RSA_WITH_IDEA_CBC_SHA"; - case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_RSA_WITH_DES_CBC_SHA: return "TLS_RSA_WITH_DES_CBC_SHA"; - case SSL_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; - case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DH_DSS_WITH_DES_CBC_SHA: return "TLS_DH_DSS_WITH_DES_CBC_SHA"; - case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; - case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DH_RSA_WITH_DES_CBC_SHA: return "TLS_DH_RSA_WITH_DES_CBC_SHA"; - case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; - case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DHE_DSS_WITH_DES_CBC_SHA: return "TLS_DHE_DSS_WITH_DES_CBC_SHA"; - case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; - case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DHE_RSA_WITH_DES_CBC_SHA: return "TLS_DHE_RSA_WITH_DES_CBC_SHA"; - case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; - case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: return "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"; - case SSL_DH_anon_WITH_RC4_128_MD5: return "TLS_DH_anon_WITH_RC4_128_MD5"; - case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; - case SSL_DH_anon_WITH_DES_CBC_SHA: return "TLS_DH_anon_WITH_DES_CBC_SHA"; - case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; - - /* SSLv3 Fortezza cipher suites, from NSS */ - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; - case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; - - /* TLS addenda using AES-CBC, RFC 3268 */ - case TLS_RSA_WITH_AES_128_CBC_SHA: return "TLS_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; - case TLS_DH_anon_WITH_AES_128_CBC_SHA: return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; - case TLS_RSA_WITH_AES_256_CBC_SHA: return "TLS_RSA_WITH_AES_256_CBC_SHA"; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; - case TLS_DH_anon_WITH_AES_256_CBC_SHA: return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; - - /* ECDSA addenda, RFC 4492 */ - case TLS_ECDH_ECDSA_WITH_NULL_SHA: return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_NULL_SHA: return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDH_RSA_WITH_NULL_SHA: return "TLS_ECDH_RSA_WITH_NULL_SHA"; - case TLS_ECDH_RSA_WITH_RC4_128_SHA: return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_NULL_SHA: return "TLS_ECDHE_RSA_WITH_NULL_SHA"; - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; - case TLS_ECDH_anon_WITH_NULL_SHA: return "TLS_ECDH_anon_WITH_NULL_SHA"; - case TLS_ECDH_anon_WITH_RC4_128_SHA: return "TLS_ECDH_anon_WITH_RC4_128_SHA"; - case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; - case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; - case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; - - /* TLS 1.2 addenda, RFC 5246 */ - case TLS_RSA_WITH_AES_128_CBC_SHA256: return "TLS_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_RSA_WITH_AES_256_CBC_SHA256: return "TLS_RSA_WITH_AES_256_CBC_SHA256"; - case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; - case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; - case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; - case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; - case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; - case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; - case TLS_DH_anon_WITH_AES_128_CBC_SHA256: return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; - case TLS_DH_anon_WITH_AES_256_CBC_SHA256: return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; - - /* TLS addenda using AES-GCM, RFC 5288 */ - case TLS_RSA_WITH_AES_128_GCM_SHA256: return "TLS_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; - case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; - case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; - case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; - case TLS_DH_anon_WITH_AES_128_GCM_SHA256: return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; - case TLS_DH_anon_WITH_AES_256_GCM_SHA384: return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; - - /* ECDSA addenda, RFC 5289 */ - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; - - /* - * Tags for SSL 2 cipher kinds which are not specified for SSL 3. - */ - case SSL_RSA_WITH_RC2_CBC_MD5: return "TLS_RSA_WITH_RC2_CBC_MD5"; - case SSL_RSA_WITH_IDEA_CBC_MD5: return "TLS_RSA_WITH_IDEA_CBC_MD5"; - case SSL_RSA_WITH_DES_CBC_MD5: return "TLS_RSA_WITH_DES_CBC_MD5"; - case SSL_RSA_WITH_3DES_EDE_CBC_MD5: return "TLS_RSA_WITH_3DES_EDE_CBC_MD5"; - case SSL_NO_SUCH_CIPHERSUITE: return "SSL_NO_SUCH_CIPHERSUITE"; - - default: - snprintf(noSuite, sizeof(noSuite), "Unknown ciphersuite 0x%04x", (unsigned)cs); - return noSuite; - } -} - -/* - * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion - - * return a string representation. - */ -const char *sslGetProtocolVersionString(SSLProtocol prot) -{ - static char noProt[20]; - - switch(prot) { - case kSSLProtocolUnknown: return "kSSLProtocolUnknown"; - case kSSLProtocol2: return "kSSLProtocol2"; - case kSSLProtocol3: return "kSSLProtocol3"; - case kSSLProtocol3Only: return "kSSLProtocol3Only"; - case kTLSProtocol1: return "kTLSProtocol1"; - case kTLSProtocol1Only: return "kTLSProtocol1Only"; - case kTLSProtocol11: return "kTLSProtocol11"; - case kTLSProtocol12: return "kTLSProtocol12"; - default: - sprintf(noProt, "Unknown (%d)", (unsigned)prot); - return noProt; - } -} - -/* - * Return string representation of SecureTransport-related OSStatus. - */ -const char *sslGetSSLErrString(OSStatus err) -{ - static char errSecSuccessStr[20]; - - switch(err) { - case errSecSuccess: return "errSecSuccess"; - case errSecAllocate: return "errSecAllocate"; - case errSecParam: return "errSecParam"; - case errSecUnimplemented: return "errSecUnimplemented"; - case errSecIO: return "errSecIO"; - case errSecBadReq: return "errSecBadReq"; - /* SSL errors */ - case errSSLProtocol: return "errSSLProtocol"; - case errSSLNegotiation: return "errSSLNegotiation"; - case errSSLFatalAlert: return "errSSLFatalAlert"; - case errSSLWouldBlock: return "errSSLWouldBlock"; - case errSSLSessionNotFound: return "errSSLSessionNotFound"; - case errSSLClosedGraceful: return "errSSLClosedGraceful"; - case errSSLClosedAbort: return "errSSLClosedAbort"; - case errSSLXCertChainInvalid: return "errSSLXCertChainInvalid"; - case errSSLBadCert: return "errSSLBadCert"; - case errSSLCrypto: return "errSSLCrypto"; - case errSSLInternal: return "errSSLInternal"; - case errSSLModuleAttach: return "errSSLModuleAttach"; - case errSSLUnknownRootCert: return "errSSLUnknownRootCert"; - case errSSLNoRootCert: return "errSSLNoRootCert"; - case errSSLCertExpired: return "errSSLCertExpired"; - case errSSLCertNotYetValid: return "errSSLCertNotYetValid"; - case errSSLClosedNoNotify: return "errSSLClosedNoNotify"; - case errSSLBufferOverflow: return "errSSLBufferOverflow"; - case errSSLBadCipherSuite: return "errSSLBadCipherSuite"; - /* TLS/Panther addenda */ - case errSSLPeerUnexpectedMsg: return "errSSLPeerUnexpectedMsg"; - case errSSLPeerBadRecordMac: return "errSSLPeerBadRecordMac"; - case errSSLPeerDecryptionFail: return "errSSLPeerDecryptionFail"; - case errSSLPeerRecordOverflow: return "errSSLPeerRecordOverflow"; - case errSSLPeerDecompressFail: return "errSSLPeerDecompressFail"; - case errSSLPeerHandshakeFail: return "errSSLPeerHandshakeFail"; - case errSSLPeerBadCert: return "errSSLPeerBadCert"; - case errSSLPeerUnsupportedCert: return "errSSLPeerUnsupportedCert"; - case errSSLPeerCertRevoked: return "errSSLPeerCertRevoked"; - case errSSLPeerCertExpired: return "errSSLPeerCertExpired"; - case errSSLPeerCertUnknown: return "errSSLPeerCertUnknown"; - case errSSLIllegalParam: return "errSSLIllegalParam"; - case errSSLPeerUnknownCA: return "errSSLPeerUnknownCA"; - case errSSLPeerAccessDenied: return "errSSLPeerAccessDenied"; - case errSSLPeerDecodeError: return "errSSLPeerDecodeError"; - case errSSLPeerDecryptError: return "errSSLPeerDecryptError"; - case errSSLPeerExportRestriction: return "errSSLPeerExportRestriction"; - case errSSLPeerProtocolVersion: return "errSSLPeerProtocolVersion"; - case errSSLPeerInsufficientSecurity:return "errSSLPeerInsufficientSecurity"; - case errSSLPeerInternalError: return "errSSLPeerInternalError"; - case errSSLPeerUserCancelled: return "errSSLPeerUserCancelled"; - case errSSLPeerNoRenegotiation: return "errSSLPeerNoRenegotiation"; - case errSSLHostNameMismatch: return "errSSLHostNameMismatch"; - case errSSLConnectionRefused: return "errSSLConnectionRefused"; - case errSSLDecryptionFail: return "errSSLDecryptionFail"; - case errSSLBadRecordMac: return "errSSLBadRecordMac"; - case errSSLRecordOverflow: return "errSSLRecordOverflow"; - case errSSLBadConfiguration: return "errSSLBadConfiguration"; - - /* some from the Sec layer */ - case errSecNotAvailable: return "errSecNotAvailable"; - case errSecDuplicateItem: return "errSecDuplicateItem"; - case errSecItemNotFound: return "errSecItemNotFound"; -#if !TARGET_OS_IPHONE - case errSecReadOnly: return "errSecReadOnly"; - case errSecAuthFailed: return "errSecAuthFailed"; - case errSecNoSuchKeychain: return "errSecNoSuchKeychain"; - case errSecInvalidKeychain: return "errSecInvalidKeychain"; - case errSecNoSuchAttr: return "errSecNoSuchAttr"; - case errSecInvalidItemRef: return "errSecInvalidItemRef"; - case errSecInvalidSearchRef: return "errSecInvalidSearchRef"; - case errSecNoSuchClass: return "errSecNoSuchClass"; - case errSecNoDefaultKeychain: return "errSecNoDefaultKeychain"; - case errSecWrongSecVersion: return "errSecWrongSecVersion"; - case errSecInvalidTrustSettings: return "errSecInvalidTrustSettings"; - case errSecNoTrustSettings: return "errSecNoTrustSettings"; -#endif - default: -#if 0 - if (err < (CSSM_BASE_ERROR + - (CSSM_ERRORCODE_MODULE_EXTENT * 8))) - { - /* assume CSSM error */ - return cssmErrToStr(err); - } - else -#endif - { - sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err); - return errSecSuccessStr; - } - } -} - -void printSslErrStr( - const char *op, - OSStatus err) -{ - printf("*** %s: %s\n", op, sslGetSSLErrString(err)); -} - -const char *sslGetClientCertStateString(SSLClientCertificateState state) -{ - static char noState[20]; - - switch(state) { - case kSSLClientCertNone: return "ClientCertNone"; - case kSSLClientCertRequested: return "CertRequested"; - case kSSLClientCertSent: return "ClientCertSent"; - case kSSLClientCertRejected: return "ClientCertRejected"; - default: - sprintf(noState, "Unknown (%d)", (unsigned)state); - return noState; - } - -} - -const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType) -{ - static char noType[20]; - - switch(authType) { - case SSLClientAuthNone: return "None"; - case SSLClientAuth_RSASign: return "RSASign"; - case SSLClientAuth_DSSSign: return "DSSSign"; - case SSLClientAuth_RSAFixedDH: return "RSAFixedDH"; - case SSLClientAuth_DSS_FixedDH: return "DSS_FixedDH"; - case SSLClientAuth_ECDSASign: return "ECDSASign"; - case SSLClientAuth_RSAFixedECDH: return "RSAFixedECDH"; - case SSLClientAuth_ECDSAFixedECDH: return "ECDSAFixedECDH"; - default: - sprintf(noType, "Unknown (%d)", (unsigned)authType); - return noType; - } -} - -/* - * Convert a keychain name (which may be NULL) into the CFArrayRef required - * by SSLSetCertificate. This is a bare-bones example of this operation, - * since it requires and assumes that there is exactly one SecIdentity - * in the keychain - i.e., there is exactly one matching cert/private key - * pair. A real world server would probably search a keychain for a SecIdentity - * matching some specific criteria. - */ -CFArrayRef getSslCerts( - const char *kcName, // may be NULL, i.e., use default - bool encryptOnly, - bool completeCertChain, - const char *anchorFile, // optional trusted anchor - SecKeychainRef *pKcRef) // RETURNED -{ -#if 0 - SecKeychainRef kcRef = nil; - OSStatus ortn; - - *pKcRef = nil; - - /* pick a keychain */ - if(kcName) { - ortn = SecKeychainOpen(kcName, &kcRef); - if(ortn) { - printf("SecKeychainOpen returned %d.\n", (int)ortn); - printf("Cannot open keychain at %s. Aborting.\n", kcName); - return NULL; - } - } - else { - /* use default keychain */ - ortn = SecKeychainCopyDefault(&kcRef); - if(ortn) { - printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); - return nil; - } - } - *pKcRef = kcRef; - return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); -#elif TARGET_OS_IOS - SecCertificateRef cert = NULL; - SecIdentityRef identity = NULL; - CFMutableArrayRef certificates = NULL, result = NULL; - CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; - SecTrustRef trust = NULL; - SecKeyRef key = NULL; - CFTypeRef pkdigest = NULL; - - // Find the first private key in the keychain and return both its - // attributes and a ref to it. - require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); - CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); - CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); - CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); - require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), - errOut); - require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), - errOut); - require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), - errOut); - - // Find the first certificate that has the same public key hash as the - // returned private key and return it as a ref. - require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); - CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); - CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); - CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); - require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); - - // Create an identity from the key and certificate. - require(identity = SecIdentityCreate(NULL, cert, key), errOut); - - // Build a (partial) certificate chain from cert - require(certificates = CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks), errOut); - CFArrayAppendValue(certificates, cert); - require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), - errOut); - SecTrustResultType tresult; - require_noerr(SecTrustEvaluate(trust, &tresult), errOut); - - CFIndex certCount, ix; - // We need at least 1 certificate - require(certCount = SecTrustGetCertificateCount(trust), errOut); - - // Build a result where element 0 is the identity and the other elements - // are the certs in the chain starting at the first intermediate up to the - // anchor, if we found one, or as far as we were able to build the chain - // if not. - require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), - errOut); - - // We are commited to returning a result now, so do not use require below - // this line without setting result to NULL again. - CFArrayAppendValue(result, identity); - for (ix = 1; ix < certCount; ++ix) { - CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); - } - -errOut: - CFReleaseSafe(trust); - CFReleaseSafe(certificates); - CFReleaseSafe(identity); - CFReleaseSafe(cert); - CFReleaseSafe(certQuery); - CFReleaseSafe(keyResult); - CFReleaseSafe(keyQuery); - - return result; - -#else /* !TARGET_OS_IOS */ - SecIdentityRef identity = NULL; - CFMutableDictionaryRef query = NULL; - CFArrayRef items = NULL; - require(query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); - CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); - CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); - require_noerr(SecItemCopyMatching(query, (CFTypeRef *)&identity), errOut); - - items = CFArrayCreate(kCFAllocatorDefault, - (const void **)&identity, 1, &kCFTypeArrayCallBacks); - -errOut: - CFReleaseSafe(identity); - CFReleaseSafe(query); - - return items; - -#endif - -} - -#if 0 -/* - * Determine if specified SecCertificateRef is a self-signed cert. - * We do this by comparing the subject and issuerr names; no cryptographic - * verification is performed. - * - * Returns true if the cert appears to be a root. - */ -static bool isCertRefRoot( - SecCertificateRef certRef) -{ - bool brtn = false; -#if 0 - /* just search for the two attrs we want */ - UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr}; - SecKeychainAttributeInfo attrInfo; - attrInfo.count = 2; - attrInfo.tag = tags; - attrInfo.format = NULL; - SecKeychainAttributeList *attrList = NULL; - SecKeychainAttribute *attr1 = NULL; - SecKeychainAttribute *attr2 = NULL; - - OSStatus ortn = SecKeychainItemCopyAttributesAndData( - (SecKeychainItemRef)certRef, - &attrInfo, - NULL, // itemClass - &attrList, - NULL, // length - don't need the data - NULL); // outData - if(ortn) { - cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); - /* may want to be a bit more robust here, but this should - * never happen */ - return false; - } - /* subsequent errors to errOut: */ - - if((attrList == NULL) || (attrList->count != 2)) { - printf("***Unexpected result fetching label attr\n"); - goto errOut; - } - - /* rootness is just byte-for-byte compare of the two names */ - attr1 = &attrList->attr[0]; - attr2 = &attrList->attr[1]; - if(attr1->length == attr2->length) { - if(memcmp(attr1->data, attr2->data, attr1->length) == 0) { - brtn = true; - } - } -errOut: - SecKeychainItemFreeAttributesAndData(attrList, NULL); -#endif - return brtn; -} -#endif - -#if 0 -/* - * Given a SecIdentityRef, do our best to construct a complete, ordered, and - * verified cert chain, returning the result in a CFArrayRef. The result is - * suitable for use when calling SSLSetCertificate(). - */ -OSStatus sslCompleteCertChain( - SecIdentityRef identity, - SecCertificateRef trustedAnchor, // optional additional trusted anchor - bool includeRoot, // include the root in outArray - CFArrayRef *outArray) // created and RETURNED -{ - CFMutableArrayRef certArray; - SecTrustRef secTrust = NULL; - SecPolicyRef policy = NULL; - SecPolicySearchRef policySearch = NULL; - SecTrustResultType secTrustResult; - CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; // not used - CFArrayRef certChain = NULL; // constructed chain - CFIndex numResCerts; - - certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - CFArrayAppendValue(certArray, identity); - - /* - * Case 1: identity is a root; we're done. Note that this case - * overrides the includeRoot argument. - */ - SecCertificateRef certRef; - OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef); - if(ortn) { - /* should never happen */ - cssmPerror("SecIdentityCopyCertificate", ortn); - return ortn; - } - bool isRoot = isCertRefRoot(certRef); - if(isRoot) { - *outArray = certArray; - CFRelease(certRef); - return errSecSuccess; - } - - /* - * Now use SecTrust to get a complete cert chain, using all of the - * user's keychains to look for intermediate certs. - * NOTE this does NOT handle root certs which are not in the system - * root cert DB. (The above case, where the identity is a root cert, does.) - */ - CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); - CFArraySetValueAtIndex(subjCerts, 0, certRef); - - /* the array owns the subject cert ref now */ - CFRelease(certRef); - - /* Get a SecPolicyRef for generic X509 cert chain verification */ - ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, - &CSSMOID_APPLE_X509_BASIC, - NULL, // value - &policySearch); - if(ortn) { - cssmPerror("SecPolicySearchCreate", ortn); - goto errOut; - } - ortn = SecPolicySearchCopyNext(policySearch, &policy); - if(ortn) { - cssmPerror("SecPolicySearchCopyNext", ortn); - goto errOut; - } - - /* build a SecTrustRef for specified policy and certs */ - ortn = SecTrustCreateWithCertificates(subjCerts, - policy, &secTrust); - if(ortn) { - cssmPerror("SecTrustCreateWithCertificates", ortn); - goto errOut; - } - - if(trustedAnchor) { - /* - * Tell SecTrust to trust this one in addition to the current - * trusted system-wide anchors. - */ - CFMutableArrayRef newAnchors; - CFArrayRef currAnchors; - - ortn = SecTrustCopyAnchorCertificates(&currAnchors); - if(ortn) { - /* should never happen */ - cssmPerror("SecTrustCopyAnchorCertificates", ortn); - goto errOut; - } - newAnchors = CFArrayCreateMutableCopy(NULL, - CFArrayGetCount(currAnchors) + 1, - currAnchors); - CFRelease(currAnchors); - CFArrayAppendValue(newAnchors, trustedAnchor); - ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors); - CFRelease(newAnchors); - if(ortn) { - cssmPerror("SecTrustSetAnchorCertificates", ortn); - goto errOut; - } - } - /* evaluate: GO */ - ortn = SecTrustEvaluate(secTrust, &secTrustResult); - if(ortn) { - cssmPerror("SecTrustEvaluate", ortn); - goto errOut; - } - switch(secTrustResult) { - case kSecTrustResultUnspecified: - /* cert chain valid, no special UserTrust assignments */ - case kSecTrustResultProceed: - /* cert chain valid AND user explicitly trusts this */ - break; - default: - /* - * Cert chain construction failed. - * Just go with the single subject cert we were given. - */ - printf("***Warning: could not construct completed cert chain\n"); - ortn = errSecSuccess; - goto errOut; - } - - /* get resulting constructed cert chain */ - ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv); - if(ortn) { - cssmPerror("SecTrustEvaluate", ortn); - goto errOut; - } - - /* - * Copy certs from constructed chain to our result array, skipping - * the leaf (which is already there, as a SecIdentityRef) and possibly - * a root. - */ - numResCerts = CFArrayGetCount(certChain); - if(numResCerts < 2) { - /* - * Can't happen: if subject was a root, we'd already have returned. - * If chain doesn't verify to a root, we'd have bailed after - * SecTrustEvaluate(). - */ - printf("***sslCompleteCertChain screwup: numResCerts %d\n", - (int)numResCerts); - ortn = errSecSuccess; - goto errOut; - } - if(!includeRoot) { - /* skip the last (root) cert) */ - numResCerts--; - } - for(CFIndex dex=1; dexacceptedProts) { - printf(" Allowed SSL versions : %s\n", params->acceptedProts); - } - else { - printf(" Attempted SSL version : %s\n", - sslGetProtocolVersionString(params->tryVersion)); - } - printf(" Result : %s\n", sslGetSSLErrString(params->ortn)); - printf(" Negotiated SSL version : %s\n", - sslGetProtocolVersionString(params->negVersion)); - printf(" Negotiated CipherSuite : %s\n", - sslGetCipherSuiteString(params->negCipher)); - if(params->certState != kSSLClientCertNone) { - printf(" Client Cert State : %s\n", - sslGetClientCertStateString(params->certState)); - } -} -#endif - -/* print a '.' every few seconds to keep UI alive while connecting */ -static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0; -#define TIME_INTERVAL 3.0 - -void sslOutputDot() -{ - CFAbsoluteTime thisTime = CFAbsoluteTimeGetCurrent(); - - // throttle down. - usleep(1000); - - if(lastTime == 0.0) { - /* avoid printing first time thru */ - lastTime = thisTime; - return; - } - if((thisTime - lastTime) >= TIME_INTERVAL) { - printf("."); fflush(stdout); - lastTime = thisTime; - } -} - -#if 0 -/* main server pthread body */ -static void *sslServerThread(void *arg) -{ - SslAppTestParams *testParams = (SslAppTestParams *)arg; - OSStatus status; - - status = sslAppServe(testParams); - pthread_exit((void*)status); - /* NOT REACHED */ - return (void *)status; -} - -/* - * Run one session, with the server in a separate thread. - * On entry, serverParams->port is the port we attempt to run on; - * the server thread may overwrite that with a different port if it's - * unable to open the port we specify. Whatever is left in - * serverParams->port is what's used for the client side. - */ -#define CLIENT_WAIT_SECONDS 1 -int sslRunSession( - SslAppTestParams*serverParams, - SslAppTestParams *clientParams, - const char *testDesc) -{ - pthread_t serverPthread; - OSStatus clientRtn; - void *serverRtn; - - if(testDesc && !clientParams->quiet) { - printf("===== %s =====\n", testDesc); - } - - if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) { - printf("***Error initializing mutex; aborting.\n"); - return -1; - } - if(pthread_cond_init(&serverParams->pthreadCond, NULL)) { - printf("***Error initializing pthreadCond; aborting.\n"); - return -1; - } - serverParams->serverReady = false; // server sets true - - int result = pthread_create(&serverPthread, NULL, - sslServerThread, serverParams); - if(result) { - printf("***Error starting up server thread; aborting.\n"); - return result; - } - - /* wait for server to set up a socket we can connect to */ - if(pthread_mutex_lock(&serverParams->pthreadMutex)) { - printf("***Error acquiring server lock; aborting.\n"); - return -1; - } - while(!serverParams->serverReady) { - if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) { - printf("***Error waiting server thread; aborting.\n"); - return -1; - } - } - pthread_mutex_unlock(&serverParams->pthreadMutex); - pthread_cond_destroy(&serverParams->pthreadCond); - pthread_mutex_destroy(&serverParams->pthreadMutex); - - clientParams->port = serverParams->port; - clientRtn = sslAppClient(clientParams); - /* server doesn't shut down its socket until it sees this */ - serverParams->clientDone = 1; - result = pthread_join(serverPthread, &serverRtn); - if(result) { - printf("***pthread_join returned %d, aborting\n", result); - return result; - } - - if(serverParams->verbose) { - sslShowResult("server", serverParams); - } - if(clientParams->verbose) { - sslShowResult("client", clientParams); - } - - /* verify results */ - int ourRtn = 0; - ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn); - ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn); - ourRtn += sslVerifyProtVers("server", serverParams->expectVersion, - serverParams->negVersion); - ourRtn += sslVerifyProtVers("client", clientParams->expectVersion, - clientParams->negVersion); - ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState, - serverParams->certState); - ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState, - clientParams->certState); - if(serverParams->ortn == errSecSuccess) { - ourRtn += sslVerifyCipher("server", serverParams->expectCipher, - serverParams->negCipher); - } - if(clientParams->ortn == errSecSuccess) { - ourRtn += sslVerifyCipher("client", clientParams->expectCipher, - clientParams->negCipher); - } - return ourRtn; -} - -/* - * Add all of the roots in a given KC to SSL ctx's trusted anchors. - */ -OSStatus sslAddTrustedRoots( - SSLContextRef ctx, - SecKeychainRef keychain, - bool *foundOne) // RETURNED, true if we found - // at least one root cert -{ - OSStatus ortn; - SecCertificateRef secCert; - SecKeychainSearchRef srch; - - *foundOne = false; - ortn = SecKeychainSearchCreateFromAttributes(keychain, - kSecCertificateItemClass, - NULL, // any attrs - &srch); - if(ortn) { - printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn); - return ortn; - } - - /* - * Only use root certs. Not an error if we don't find any. - */ - do { - ortn = SecKeychainSearchCopyNext(srch, - (SecKeychainItemRef *)&secCert); - if(ortn) { - break; - } - - /* see if it's a root */ - if(!isCertRoot(secCert)) { - continue; - } - - /* Tell Secure Transport to trust this one. */ - ortn = addTrustedSecCert(ctx, secCert, false); - if(ortn) { - /* fatal */ - printSslErrStr("addTrustedSecCert", ortn); - return ortn; - } - CFRelease(secCert); - *foundOne = true; - } while(ortn == errSecSuccess); - CFRelease(srch); - return errSecSuccess; -} - -/* - * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. - */ -OSStatus sslIdentityPicker( - SecKeychainRef kcRef, // NULL means use default list - const char *trustedAnchor, // optional additional trusted anchor - bool includeRoot, // true --> root is appended to outArray - // false --> root not included - CFArrayRef *outArray) // created and RETURNED -{ - SecCertificateRef trustedCert = NULL; - OSStatus ortn; - - if(trustedAnchor) { - ortn = sslReadAnchor(trustedAnchor, &trustedCert); - if(ortn) { - printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n", - trustedAnchor); - trustedCert = NULL; - } - } - ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray); - if(trustedCert) { - CFRelease(trustedCert); - } - return ortn; -} - -/* - * Given a keychain name, convert it into a full path using the "SSL regression - * test suite algorithm". The Sec layer by default locates root root's keychains - * in different places depending on whether we're actually logged in as root - * or running via e.g. cron, so we force the location of root keychains to - * a hard-coded path. User keychain names we leave alone. - */ -void sslKeychainPath( - const char *kcName, - char *kcPath) // allocd by caller, MAXPATHLEN -{ - if(kcName[0] == '\0') { - kcPath[0] = '\0'; - } - else if(geteuid() == 0) { - /* root */ - sprintf(kcPath, "/Library/Keychains/%s", kcName); - } - else { - /* user, leave alone */ - strcpy(kcPath, kcName); - } -} - -/* Verify presence of required file. Returns nonzero if not found. */ -int sslCheckFile(const char *path) -{ - struct stat sb; - - if(stat(path, &sb)) { - printf("***Can't find file %s.\n", path); - printf(" Try running in the build directory, perhaps after running the\n" - " makeLocalCert script.\n"); - return 1; - } - return 0; -} - -#endif - -/* Stringify a SSL_ECDSA_NamedCurve */ -extern const char *sslCurveString( - SSL_ECDSA_NamedCurve namedCurve) -{ - static char unk[100]; - - switch(namedCurve) { - case SSL_Curve_None: return "Curve_None"; - case SSL_Curve_secp256r1: return "secp256r1"; - case SSL_Curve_secp384r1: return "secp384r1"; - case SSL_Curve_secp521r1: return "secp521r1"; - default: - sprintf(unk, "Unknown <%d>", (int)namedCurve); - return unk; - } -} diff --git a/OSX/libsecurity_ssl/sslViewer/sslAppUtils.h b/OSX/libsecurity_ssl/sslViewer/sslAppUtils.h deleted file mode 100644 index 5448105e..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslAppUtils.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2006-2008,2010-2012,2014 Apple Inc. All Rights Reserved. - */ - -#ifndef _SSLS_APP_UTILS_H_ -#define _SSLS_APP_UTILS_H_ 1 - -#include -#include -#include -#include -#include - -#include - -#if TARGET_OS_IPHONE -typedef void *SecKeychainRef; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -const char *sslGetCipherSuiteString(SSLCipherSuite cs); -const char *sslGetProtocolVersionString(SSLProtocol prot); -const char *sslGetSSLErrString(OSStatus err); -void printSslErrStr(const char *op, OSStatus err); -const char *sslGetClientCertStateString(SSLClientCertificateState state); -const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType); - -CFArrayRef getSslCerts( - const char *kcName, // may be NULL, i.e., use default - bool encryptOnly, - bool completeCertChain, - const char *anchorFile, // optional trusted anchor - SecKeychainRef *pKcRef); // RETURNED -OSStatus sslCompleteCertChain( - SecIdentityRef identity, - SecCertificateRef trustedAnchor, // optional additional trusted anchor - bool includeRoot, // include the root in outArray -// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL - CFArrayRef *outArray); // created and RETURNED -CFArrayRef sslKcRefToCertArray( - SecKeychainRef kcRef, - bool encryptOnly, - bool completeCertChain, -// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL policy to complete - const char *trustedAnchorFile); - -OSStatus addTrustedSecCert( - SSLContextRef ctx, - SecCertificateRef secCert, - bool replaceAnchors); -OSStatus sslReadAnchor( - const char *anchorFile, - SecCertificateRef *certRef); -OSStatus sslAddTrustedRoot( - SSLContextRef ctx, - const char *anchorFile, - bool replaceAnchors); - -/* - * Assume incoming identity contains a root (e.g., created by - * certtool) and add that cert to ST's trusted anchors. This - * enables ST's verify of the incoming chain to succeed without - * a kludgy "AllowAnyRoot" specification. - */ -OSStatus addIdentityAsTrustedRoot( - SSLContextRef ctx, - CFArrayRef identArray); - -OSStatus sslAddTrustedRoots( - SSLContextRef ctx, - SecKeychainRef keychain, - bool *foundOne); - -void sslOutputDot(); - -/* - * Lists of SSLCipherSuites used in sslSetCipherRestrictions. - */ -extern const SSLCipherSuite suites40[]; -extern const SSLCipherSuite suitesDES[]; -extern const SSLCipherSuite suitesDES40[]; -extern const SSLCipherSuite suites3DES[]; -extern const SSLCipherSuite suitesRC4[]; -extern const SSLCipherSuite suitesRC4_40[]; -extern const SSLCipherSuite suitesRC2[]; -extern const SSLCipherSuite suitesAES128[]; -extern const SSLCipherSuite suitesAES256[]; -extern const SSLCipherSuite suitesDH[]; -extern const SSLCipherSuite suitesDHAnon[]; -extern const SSLCipherSuite suitesDH_RSA[]; -extern const SSLCipherSuite suitesDH_DSS[]; -extern const SSLCipherSuite suites_SHA1[]; -extern const SSLCipherSuite suites_MD5[]; -extern const SSLCipherSuite suites_ECDHE[]; -extern const SSLCipherSuite suites_ECDH[]; - -/* - * Given an SSLContextRef and an array of SSLCipherSuites, terminated by - * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library - * supports and do a SSLSetEnabledCiphers() specifying those. - */ -OSStatus sslSetEnabledCiphers( - SSLContextRef ctx, - const SSLCipherSuite *ciphers); - -/* - * Specify restricted sets of cipherspecs and protocols. - */ -OSStatus sslSetCipherRestrictions( - SSLContextRef ctx, - char cipherRestrict); - -#ifndef SPHINX -OSStatus sslSetProtocols( - SSLContextRef ctx, - const char *acceptedProts, - SSLProtocol tryVersion); // only used if acceptedProts NULL -#endif - -int sslVerifyRtn( - const char *whichSide, // "client" or "server" - OSStatus expectRtn, - OSStatus gotRtn); -int sslVerifyProtVers( - const char *whichSide, // "client" or "server" - SSLProtocol expectProt, - SSLProtocol gotProt); -int sslVerifyClientCertState( - const char *whichSide, // "client" or "server" - SSLClientCertificateState expectState, - SSLClientCertificateState gotState); -int sslVerifyCipher( - const char *whichSide, // "client" or "server" - SSLCipherSuite expectCipher, - SSLCipherSuite gotCipher); - - -/* - * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename. - */ -OSStatus sslIdentityPicker( - SecKeychainRef kcRef, // NULL means use default list - const char *trustedAnchor, // optional additional trusted anchor - bool includeRoot, // true --> root is appended to outArray - // false --> root not included -// const CSSM_OID *vfyPolicy, // optional - if NULL, use SSL - CFArrayRef *outArray); // created and RETURNED - -void sslKeychainPath( - const char *kcName, - char *kcPath); // allocd by caller, MAXPATHLEN - -/* Verify presence of required file. Returns nonzero if not found. */ -int sslCheckFile(const char *path); - -/* Stringify a SSL_ECDSA_NamedCurve */ -extern const char *sslCurveString( - SSL_ECDSA_NamedCurve namedCurve); - -#ifdef __cplusplus -} -#endif - -#endif /* _SSLS_APP_UTILS_H_ */ diff --git a/OSX/libsecurity_ssl/sslViewer/sslServer.1 b/OSX/libsecurity_ssl/sslViewer/sslServer.1 deleted file mode 100644 index e46751b0..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslServer.1 +++ /dev/null @@ -1,79 +0,0 @@ -.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. -.\"See Also: -.\"man mdoc.samples for a complete listing of options -.\"man mdoc for the short list of editing options -.\"/usr/share/misc/mdoc.template -.Dd 5/2/12 \" DATE -.Dt sslServer 1 \" Program name and manual section number -.Os Darwin -.Sh NAME \" Section Header - required - don't modify -.Nm sslServer, -.\" The following lines are read in generating the apropos(man -k) database. Use only key -.\" words here as the database is built based on the words here and in the .ND line. -.Nm Other_name_for_same_program(), -.Nm Yet another name for the same program. -.\" Use .Nm macro to designate other names for the documented program. -.Nd This line parsed for whatis database. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm -.Op Fl abcd \" [-abcd] -.Op Fl a Ar path \" [-a path] -.Op Ar file \" [file] -.Op Ar \" [file ...] -.Ar arg0 \" Underlined argument - use .Ar anywhere to underline -arg2 ... \" Arguments -.Sh DESCRIPTION \" Section Header - required - don't modify -Use the .Nm macro to refer to your program throughout the man page like such: -.Nm -Underlining is accomplished with the .Ar macro like this: -.Ar underlined text . -.Pp \" Inserts a space -A list of items with descriptions: -.Bl -tag -width -indent \" Begins a tagged list -.It item a \" Each item preceded by .It macro -Description of item a -.It item b -Description of item b -.El \" Ends the list -.Pp -A list of flags and their descriptions: -.Bl -tag -width -indent \" Differs from above in tag removed -.It Fl a \"-a flag as a list item -Description of -a flag -.It Fl b -Description of -b flag -.El \" Ends the list -.Pp -.\" .Sh ENVIRONMENT \" May not be needed -.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 -.\" .It Ev ENV_VAR_1 -.\" Description of ENV_VAR_1 -.\" .It Ev ENV_VAR_2 -.\" Description of ENV_VAR_2 -.\" .El -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact -.It Pa /usr/share/file_name -FILE_1 description -.It Pa /Users/joeuser/Library/really_long_file_name -FILE_2 description -.El \" Ends the list -.\" .Sh DIAGNOSTICS \" May not be needed -.\" .Bl -diag -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.\" Please do not reference files that do not exist without filing a bug report -.Xr a 1 , -.Xr b 1 , -.Xr c 1 , -.Xr a 2 , -.Xr b 2 , -.Xr a 3 , -.Xr b 3 -.\" .Sh BUGS \" Document known, unremedied bugs -.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/OSX/libsecurity_ssl/sslViewer/sslServer.cpp b/OSX/libsecurity_ssl/sslViewer/sslServer.cpp deleted file mode 100644 index c8fe63e3..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslServer.cpp +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Copyright (c) 2008-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@ - */ - -/* - * Trivial SSL server example, using SecureTransport / OS X version. - * - */ - -#include -#include -#include "sslAppUtils.h" -#include "ioSock.h" -#include "fileIo.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include "printCert.h" - -#if NO_SERVER -#include -#endif - -/* Set true when PR-3074739 is merged to TOT */ -#define SET_DH_PARAMS_ENABLE 1 - -/* true when using SSLCopyPeerCertificates() per Radar 3311892 */ -#define USE_COPY_PEER_CERTS 1 - -/* - * Defaults, overridable by user. - */ -#define SERVER_MESSAGE "HTTP/1.0 200 OK\015\012Content-Type: text/html\015\012\015\012" \ - "SecureTransport Test Server" \ - "

Secure connection established.

" \ - "Message from the 'sslServer' sample application.\015\012" \ - "\015\012" - -/* For ease of debugging, pick a non-privileged port */ -#define DEFAULT_PORT 1200 -// #define DEFAULT_PORT 443 - -#define DEFAULT_HOST "localhost" - -#define DEFAULT_KC "certkc" - -static void usage(char **argv) -{ - printf("Usage: %s [option ...]\n", argv[0]); - printf("Options:\n"); - printf(" P=port Port to listen on; default is %d\n", DEFAULT_PORT); - printf(" k=keychain Contains server cert and keys.\n"); - printf(" y=keychain Encryption-only cert and keys.\n"); - printf(" e Allow Expired Certs\n"); - printf(" r Allow any root cert\n"); - printf(" E Allow Expired Roots\n"); - printf(" x Disable Cert Verification\n"); - printf(" f=fileBase Write Peer Certs to fileBase*\n"); - printf(" c Display peer certs\n"); - printf(" d Display received data\n"); - printf(" C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 $=40-bit RC4\n" - " 2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n" - " n=RSA/NULL\n"); - printf(" 2 SSLv2 only (default is best fit)\n"); - printf(" 3 SSLv3 only (default is best fit)\n"); - printf(" t TLSv1 only (default is best fit)\n"); - printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); - printf(" g={prot...} Specify legal protocols; prot = any combo of [23t]\n"); - printf(" T=[nrsj] Verify client cert state = " - "none/requested/sent/rejected\n"); - printf(" R Disable resumable session support\n"); - printf(" i=timeout Session cache timeout\n"); - printf(" u=[nat] Authentication: n=never; a=always; t=try\n"); - printf(" b Non-blocking I/O\n"); - printf(" a fileNmae Add fileName to list of trusted roots\n"); - printf(" A fileName fileName is ONLY trusted root\n"); - printf(" U filename Add filename to acceptable DNList (multiple times OK)\n"); - printf(" D filename Diffie-Hellman parameters from filename\n"); - printf(" z=password Unlock server keychain with password.\n"); - printf(" H Do SecIdentityRef search instead of specific keychain\n"); - printf(" M Complete cert chain (default assumes that our identity is root)\n"); - printf(" 4 Disable anonymous ciphers\n"); - printf(" p Pause after each phase\n"); - printf(" l[=loops] Loop, performing multiple transactions\n"); - printf(" q Quiet/diagnostic mode (site names and errors only)\n"); - printf(" h Help\n"); - exit(1); -} - -/* snag a copy of current connection's peer certs so we can - * examine them later after the connection is closed */ -static OSStatus copyPeerCerts( - SSLContext *ctx, - CFArrayRef *peerCerts) // mallocd & RETURNED -{ - #if USE_COPY_PEER_CERTS - OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts); - #else - OSStatus ortn = SSLGetPeerCertificates(ctx, peerCerts); - #endif - if(ortn) { - printf("***Error obtaining peer certs: %s\n", - sslGetSSLErrString(ortn)); - } - return ortn; -} - -/* free the cert array obtained via SSLGetPeerCertificates() */ -static void freePeerCerts( - CFArrayRef peerCerts) -{ - if(peerCerts == NULL) { - return; - } - - #if USE_COPY_PEER_CERTS - - /* Voila! Problem fixed. */ - CFRelease(peerCerts); - return; - - #else - - CFIndex numCerts; - SecCertificateRef certData; - CFIndex i; - - numCerts = CFArrayGetCount(peerCerts); - for(i=0; i", ((unsigned)c) & 0xff); - } - break; - } - - } - printf("\n"); -} - -static void doPause(const char *prompt) { - if(prompt) { - printf("%s. ", prompt); - } - fpurge(stdin); - printf("Continue (n/anything)? "); - char c = getchar(); - if(c == 'n') { - exit(0); - } -} - -/* - * Perform one SSL diagnostic server-side session. Returns nonzero on error. - * Normally no output to stdout except initial "waiting for connection" message, - * unless there is a really screwed up error (i.e., something not directly related - * to the SSL connection). - */ -#define RCV_BUF_SIZE 256 - -static OSStatus sslServe( - otSocket listenSock, - unsigned short portNum, - SSLProtocol tryVersion, // only used if acceptedProts NULL - const char *acceptedProts, - CFArrayRef serverCerts, // required - char *password, // optional - CFArrayRef encryptServerCerts, // optional - bool allowExpired, - bool allowAnyRoot, - bool allowExpiredRoot, - bool disableCertVerify, - char *anchorFile, - bool replaceAnchors, - char cipherRestrict, // '2', 'd'. etc...'\0' for no - // restriction - SSLAuthenticate authenticate, - unsigned char *dhParams, // optional D-H parameters - unsigned dhParamsLen, - CFArrayRef acceptableDNList, // optional - bool resumableEnable, - uint32_t sessionCacheTimeout,// optional - bool disableAnonCiphers, - bool silent, // no stdout - bool pause, - SSLProtocol *negVersion, // RETURNED - SSLCipherSuite *negCipher, // RETURNED - SSLClientCertificateState *certState, // RETURNED - Boolean *sessionWasResumed, // RETURNED - unsigned char *sessionID, // mallocd by caller, RETURNED - size_t *sessionIDLength, // RETURNED - CFArrayRef *peerCerts, // mallocd & RETURNED - char **argv) -{ - otSocket acceptSock; - PeerSpec peerId; - OSStatus ortn; - SSLContextRef ctx = NULL; - size_t length; - uint8_t rcvBuf[RCV_BUF_SIZE]; - const char *outMsg = SERVER_MESSAGE; - - *negVersion = kSSLProtocolUnknown; - *negCipher = SSL_NULL_WITH_NULL_NULL; - *peerCerts = NULL; - - #if IGNORE_SIGPIPE - signal(SIGPIPE, sigpipe); - #endif - - /* first wait for a connection */ - if(!silent) { - printf("Waiting for client connection on port %u...", portNum); - fflush(stdout); - } - ortn = AcceptClientConnection(listenSock, &acceptSock, &peerId); - if(ortn) { - printf("AcceptClientConnection returned %d; aborting\n", (int)ortn); - return ortn; - } - - /* - * Set up a SecureTransport session. - * First the standard calls. - */ - ortn = SSLNewContext(true, &ctx); - if(ortn) { - printSslErrStr("SSLNewContext", ortn); - goto cleanup; - } - ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); - if(ortn) { - printSslErrStr("SSLSetIOFuncs", ortn); - goto cleanup; - } - ortn = SSLSetConnection(ctx, (SSLConnectionRef)acceptSock); - if(ortn) { - printSslErrStr("SSLSetConnection", ortn); - goto cleanup; - } - - /* have to do these options befor setting server certs */ - if(allowExpired) { - ortn = SSLSetAllowsExpiredCerts(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowExpiredCerts", ortn); - goto cleanup; - } - } - if(allowAnyRoot) { - ortn = SSLSetAllowsAnyRoot(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowAnyRoot", ortn); - goto cleanup; - } - } - - if(anchorFile) { - ortn = sslAddTrustedRoot(ctx, anchorFile, replaceAnchors); - if(ortn) { - printf("***Error obtaining anchor file %s\n", anchorFile); - goto cleanup; - } - } - if(serverCerts != NULL) { - if(anchorFile == NULL) { - /* no specific anchors, so assume we want to trust this one */ - ortn = addIdentityAsTrustedRoot(ctx, serverCerts); - if(ortn) { - goto cleanup; - } - } - ortn = SSLSetCertificate(ctx, serverCerts); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - goto cleanup; - } - } - if(encryptServerCerts) { - ortn = SSLSetEncryptionCertificate(ctx, encryptServerCerts); - if(ortn) { - printSslErrStr("SSLSetEncryptionCertificate", ortn); - goto cleanup; - } - } - if(allowExpiredRoot) { - ortn = SSLSetAllowsExpiredRoots(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowsExpiredRoots", ortn); - goto cleanup; - } - } - if(disableCertVerify) { - ortn = SSLSetEnableCertVerify(ctx, false); - if(ortn) { - printSslErrStr("SSLSetEnableCertVerify", ortn); - goto cleanup; - } - } - - /* - * SecureTransport options. - */ - if(acceptedProts) { - ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); - if(ortn) { - printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); - goto cleanup; - } - for(const char *cp = acceptedProts; *cp; cp++) { - SSLProtocol prot = kSSLProtocolUnknown; - switch(*cp) { - case '2': - prot = kSSLProtocol2; - break; - case '3': - prot = kSSLProtocol3; - break; - case 't': - prot = kTLSProtocol1; - break; - default: - usage(argv); - } - ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); - if(ortn) { - printSslErrStr("SSLSetProtocolVersionEnabled", ortn); - goto cleanup; - } - } - } - else { - ortn = SSLSetProtocolVersion(ctx, tryVersion); - if(ortn) { - printSslErrStr("SSLSetProtocolVersion", ortn); - goto cleanup; - } - } - if(resumableEnable) { - ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); - if(ortn) { - printSslErrStr("SSLSetPeerID", ortn); - goto cleanup; - } - } - if(cipherRestrict != '\0') { - ortn = sslSetCipherRestrictions(ctx, cipherRestrict); - if(ortn) { - goto cleanup; - } - } - if(authenticate != kNeverAuthenticate) { - ortn = SSLSetClientSideAuthenticate(ctx, authenticate); - if(ortn) { - printSslErrStr("SSLSetClientSideAuthenticate", ortn); - goto cleanup; - } - } - if(dhParams) { - ortn = SSLSetDiffieHellmanParams(ctx, dhParams, dhParamsLen); - if(ortn) { - printSslErrStr("SSLSetDiffieHellmanParams", ortn); - goto cleanup; - } - } - if(sessionCacheTimeout) { - ortn = SSLSetSessionCacheTimeout(ctx, sessionCacheTimeout); - if(ortn) { - printSslErrStr("SSLSetSessionCacheTimeout", ortn); - goto cleanup; - } - } - if(disableAnonCiphers) { - ortn = SSLSetAllowAnonymousCiphers(ctx, false); - if(ortn) { - printSslErrStr("SSLSetAllowAnonymousCiphers", ortn); - goto cleanup; - } - /* quickie test of the getter */ - Boolean e; - ortn = SSLGetAllowAnonymousCiphers(ctx, &e); - if(ortn) { - printSslErrStr("SSLGetAllowAnonymousCiphers", ortn); - goto cleanup; - } - if(e) { - printf("***SSLGetAllowAnonymousCiphers() returned true; expected false\n"); - ortn = errSecIO; - goto cleanup; - } - } -/* XXX/cs - if(acceptableDNList) { - ortn = SSLSetCertificateAuthorities(ctx, acceptableDNList, TRUE); - if(ortn) { - printSslErrStr("SSLSetCertificateAuthorities", ortn); - goto cleanup; - } - } -*/ - /* end options */ - - if(pause) { - doPause("SSLContext initialized"); - } - - /* Perform SSL/TLS handshake */ - do - { ortn = SSLHandshake(ctx); - if((ortn == errSSLWouldBlock) && !silent) { - /* keep UI responsive */ - sslOutputDot(); - } - } while (ortn == errSSLWouldBlock); - - /* this works even if handshake failed due to cert chain invalid */ - copyPeerCerts(ctx, peerCerts); - - SSLGetClientCertificateState(ctx, certState); - SSLGetNegotiatedCipher(ctx, negCipher); - SSLGetNegotiatedProtocolVersion(ctx, negVersion); - *sessionIDLength = MAX_SESSION_ID_LENGTH; - SSLGetResumableSessionInfo(ctx, sessionWasResumed, sessionID, - sessionIDLength); - - if(!silent) { - printf("\n"); - } - if(ortn) { - goto cleanup; - } - if(pause) { - doPause("SSLContext handshake complete"); - } - - /* wait for one complete line or user says they've had enough */ - while(ortn == errSecSuccess) { - length = sizeof(rcvBuf); - ortn = SSLRead(ctx, rcvBuf, length, &length); - if(length == 0) { - /* keep UI responsive */ - sslOutputDot(); - } - else { - /* print what we have */ - printf("client request: "); - dumpAscii(rcvBuf, length); - } - if(pause) { - /* allow user to bail */ - char resp; - - fpurge(stdin); - printf("\nMore client request (y/anything): "); - resp = getchar(); - if(resp != 'y') { - break; - } - } - - /* poor person's line completion scan */ - for(unsigned i=0; i SSLSetProtocolVersionEnabled - bool quiet = false; - bool resumableEnable = true; - bool pause = false; - char *keyChainName = NULL; - char *encryptKeyChainName = NULL; - int loops = 1; - SSLAuthenticate authenticate = kNeverAuthenticate; - bool nonBlocking = false; - bool allowExpiredRoot = false; - bool disableCertVerify = false; - char *anchorFile = NULL; - bool replaceAnchors = false; - bool vfyCertState = false; - SSLClientCertificateState expectCertState = kSSLClientCertNone; - char *password = NULL; - char *dhParamsFile = NULL; - unsigned char *dhParams = NULL; - unsigned dhParamsLen = 0; - bool doIdSearch = false; - bool completeCertChain = false; - uint32_t sessionCacheTimeout = 0; - bool disableAnonCiphers = false; - CFMutableArrayRef acceptableDNList = NULL; - - for(arg=1; arg loop forever */ - loops = 0; - break; - } - else if(argp[1] != '=') { - usage(argv); - } - loops = atoi(&argp[2]); - break; - default: - usage(argv); - } - } - -#if NO_SERVER -# if DEBUG - securityd_init(); -# endif -#endif - - /* get server cert and optional encryption cert as CFArrayRef */ - if(keyChainName) { - serverCerts = getSslCerts(keyChainName, false, completeCertChain, - anchorFile, &serverKc); - if(serverCerts == nil) { - exit(1); - } - } - else -#if 0 - if(doIdSearch) { - OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts); - if(ortn) { - printf("***IdentitySearch failure; aborting.\n"); - exit(1); - } - } - if(password) { - OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true); - if(ortn) { - printf("SecKeychainUnlock returned %d\n", (int)ortn); - /* oh well */ - } - } - if(encryptKeyChainName) { - encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain, - anchorFile, &encryptKc); - if(encryptCerts == nil) { - exit(1); - } - } -#endif - if(protXOnly) { - switch(attemptProt) { - case kTLSProtocol1: - attemptProt = kTLSProtocol1Only; - break; - case kSSLProtocol3: - attemptProt = kSSLProtocol3Only; - break; - default: - break; - } - } -#if 0 - if(dhParamsFile) { - int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen); - if(r) { - printf("***Error reading diffie-hellman params from %s; aborting\n", - dhParamsFile); - } - } -#endif - - /* one-time only server port setup */ - err = ListenForClients(portNum, nonBlocking, &listenSock); - if(err) { - printf("ListenForClients returned %d; aborting\n", (int)err); - exit(1); - } - - for(loopNum=1; ; loopNum++) { - err = sslServe(listenSock, - portNum, - attemptProt, - acceptedProts, - serverCerts, - password, - encryptCerts, - allowExpired, - allowAnyRoot, - allowExpiredRoot, - disableCertVerify, - anchorFile, - replaceAnchors, - cipherRestrict, - authenticate, - dhParams, - dhParamsLen, - acceptableDNList, - resumableEnable, - sessionCacheTimeout, - disableAnonCiphers, - quiet, - pause, - &negVersion, - &negCipher, - &certState, - &sessionWasResumed, - sessionID, - &sessionIDLength, - &peerCerts, - argv); - if(err) { - errCount++; - } - if(!quiet) { - SSLProtocol tryProt = attemptProt; - showSSLResult(tryProt, - acceptedProts, - err, - negVersion, - negCipher, - sessionWasResumed, - sessionID, - sessionIDLength, - peerCerts, - displayCerts, - certState, - fileBase ? fullFileBase : NULL); - } - errCount += verifyClientCertState(vfyCertState, expectCertState, - certState); - freePeerCerts(peerCerts); - if(loops && (loopNum == loops)) { - break; - } - }; - - endpointShutdown(listenSock); - - if(serverKc) { - CFRelease(serverKc); - } - if(encryptKc) { - CFRelease(encryptKc); - } - return errCount; - -} - - diff --git a/OSX/libsecurity_ssl/sslViewer/sslViewer.1 b/OSX/libsecurity_ssl/sslViewer/sslViewer.1 deleted file mode 100644 index 00e88081..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslViewer.1 +++ /dev/null @@ -1,79 +0,0 @@ -.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. -.\"See Also: -.\"man mdoc.samples for a complete listing of options -.\"man mdoc for the short list of editing options -.\"/usr/share/misc/mdoc.template -.Dd 5/2/12 \" DATE -.Dt sslViewer 1 \" Program name and manual section number -.Os Darwin -.Sh NAME \" Section Header - required - don't modify -.Nm sslViewer, -.\" The following lines are read in generating the apropos(man -k) database. Use only key -.\" words here as the database is built based on the words here and in the .ND line. -.Nm Other_name_for_same_program(), -.Nm Yet another name for the same program. -.\" Use .Nm macro to designate other names for the documented program. -.Nd This line parsed for whatis database. -.Sh SYNOPSIS \" Section Header - required - don't modify -.Nm -.Op Fl abcd \" [-abcd] -.Op Fl a Ar path \" [-a path] -.Op Ar file \" [file] -.Op Ar \" [file ...] -.Ar arg0 \" Underlined argument - use .Ar anywhere to underline -arg2 ... \" Arguments -.Sh DESCRIPTION \" Section Header - required - don't modify -Use the .Nm macro to refer to your program throughout the man page like such: -.Nm -Underlining is accomplished with the .Ar macro like this: -.Ar underlined text . -.Pp \" Inserts a space -A list of items with descriptions: -.Bl -tag -width -indent \" Begins a tagged list -.It item a \" Each item preceded by .It macro -Description of item a -.It item b -Description of item b -.El \" Ends the list -.Pp -A list of flags and their descriptions: -.Bl -tag -width -indent \" Differs from above in tag removed -.It Fl a \"-a flag as a list item -Description of -a flag -.It Fl b -Description of -b flag -.El \" Ends the list -.Pp -.\" .Sh ENVIRONMENT \" May not be needed -.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 -.\" .It Ev ENV_VAR_1 -.\" Description of ENV_VAR_1 -.\" .It Ev ENV_VAR_2 -.\" Description of ENV_VAR_2 -.\" .El -.Sh FILES \" File used or created by the topic of the man page -.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact -.It Pa /usr/share/file_name -FILE_1 description -.It Pa /Users/joeuser/Library/really_long_file_name -FILE_2 description -.El \" Ends the list -.\" .Sh DIAGNOSTICS \" May not be needed -.\" .Bl -diag -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .It Diagnostic Tag -.\" Diagnostic informtion here. -.\" .El -.Sh SEE ALSO -.\" List links in ascending order by section, alphabetically within a section. -.\" Please do not reference files that do not exist without filing a bug report -.Xr a 1 , -.Xr b 1 , -.Xr c 1 , -.Xr a 2 , -.Xr b 2 , -.Xr a 3 , -.Xr b 3 -.\" .Sh BUGS \" Document known, unremedied bugs -.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/OSX/libsecurity_ssl/sslViewer/sslViewer.cpp b/OSX/libsecurity_ssl/sslViewer/sslViewer.cpp deleted file mode 100644 index eca0ed36..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslViewer.cpp +++ /dev/null @@ -1,1870 +0,0 @@ -/* - * Copyright (c) 2006-2013 Apple Inc. All Rights Reserved. - * - * SSL viewer tool, Secure Transport. - */ - -#include "SecureTransport.h" - -#include -#include -#include -#include -#include -#include "sslAppUtils.h" -#include "printCert.h" -#include "ioSock.h" -#include "fileIo.h" - -#include -#include -#include -#include -#include -#include -#include - -#if NO_SERVER -#include -#endif - -#define DEFAULT_GETMSG "GET" -#define DEFAULT_PATH "/" -#define DEFAULT_GET_SUFFIX "HTTP/1.0\r\n\r\n" - -#define DEFAULT_HOST "store.apple.com" -#define DEFAULT_PORT 443 - -#define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); } -#define CFReleaseNull(CF) { CFTypeRef _cf = (CF); \ - if (_cf) { (CF) = NULL; CFRelease(_cf); } } - -static void usageNorm(char **argv) -{ - printf("Usage: %s [hostname|-] [path] [option ...]\n", argv[0]); - printf(" %s hostname [path] [option ...]\n", argv[0]); - printf("Specifying '-' for hostname, or no args, uses default of %s.\n", - DEFAULT_HOST); - printf("Optional path argument must start with leading '/'.\n"); - printf("Options:\n"); - printf(" e Allow Expired Certs\n"); - printf(" E Allow Expired Roots\n"); - printf(" r Allow any root cert\n"); - printf(" c Display peer certs\n"); - printf(" cc Display peer SecTrust\n"); - printf(" d Display received data\n"); - printf(" S Display enabled cipher suites\n"); - printf(" 2 SSLv2 only\n"); - printf(" 3 SSLv3 only\n"); - printf(" tls10 | t TLSv1 only\n"); - printf(" tls11 TLSv1.1 only\n"); - printf(" tls12 TLSv1.2 only\n"); - printf(" L all - TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2 (default = TLSv1.2)\n"); - printf(" g={prot...} Specify legal protocols; prot = any combo of" - " [2|3|t|tls10|tls11|tls12]\n"); - printf(" k=keychain Contains (client|server) cert and keys. Optional.\n"); - printf(" l=loopCount Perform loopCount ops (default = 1)\n"); - printf(" P=port Default = %d\n", DEFAULT_PORT); - printf(" p Pause after each loop\n"); - printf(" q Quiet/diagnostic mode (site names and errors" - " only)\n"); - printf(" a fileName Add fileName to list of trusted roots\n"); - printf(" A fileName fileName is ONLY trusted root\n"); - printf(" Z fileName fileName is a trusted leaf cert\n"); - printf(" x Disable Cert Verification\n"); - printf(" z=password Unlock client keychain with password.\n"); - printf(" 8 Complete cert chains (default is out cert is a root)\n"); - printf(" s Silent\n"); - printf(" V Verbose\n"); - printf(" h Help\n"); - printf(" hv More, verbose help\n"); -} - -static void usageVerbose(char **argv) __attribute__((noreturn)); -static void usageVerbose(char **argv) -{ - usageNorm(argv); - printf("Obscure Usage:\n"); - printf(" u kSSLProtocolUnknown only (TLSv1)\n"); - printf(" M Manual cert verification via " - "SecTrustEvaluate\n"); - printf(" f fileBase Write Peer Certs to fileBase*\n"); - printf(" o TLSv1, SSLv3 use kSSLProtocol__X__Only\n"); - printf(" C=cipherSuite (e=40-bit d=DES D=40-bit DES 3=3DES 4=RC4 " - "$=40-bit RC4\n" - " 2=RC2 a=AES128 A=AES256 h=DH H=Anon DH r=DHE/RSA s=DH/DSS\n"); - printf(" y=keychain Encryption-only cert and keys. Optional.\n"); - printf(" K Keep connected until server disconnects\n"); - printf(" n Require closure notify message in TLSv1, " - "SSLv3 mode (implies K)\n"); - printf(" R Disable resumable session support\n"); - printf(" b Non-blocking I/O\n"); - printf(" v Verify negotiated protocol equals attempted\n"); - printf(" m=[23t] Max protocol supported as specified; implies " - "v\n"); - printf(" T=[nrsj] Verify client cert state = " - "none/requested/sent/rejected\n"); - printf(" H allow hostname spoofing\n"); - printf(" F=vfyHost Verify certs with specified host name\n"); - printf(" G=getMsg Specify entire GET, POST, etc.\n"); - printf(" N Log handshake timing\n"); - printf(" 7 Pause only after first loop\n"); - exit(1); -} - -static void usage(char **argv) __attribute__((noreturn)); -static void usage(char **argv) -{ - usageNorm(argv); - exit(1); -} - -/* - * Arguments to top-level sslPing() - */ -typedef struct { - SSLProtocol tryVersion; // only used if acceptedProts NULL - // uses SSLSetProtocolVersion - char *acceptedProts; // optional, any combo of {2,3,t} - // uses SSLSetProtocolVersionEnabled - const char *hostName; // e.g., "store.apple.com" - const char *vfyHostName; // use this for cert vfy if non-NULL, - // else use hostName - unsigned short port; - const char *getMsg; // e.g., - // "GET / HTTP/1.0\r\n\r\n" - bool allowExpired; - bool allowAnyRoot; - bool allowExpiredRoot; - bool disableCertVerify; - bool manualCertVerify; - bool dumpRxData; // display server data - char cipherRestrict; // '2', 'd'. etc...; '\0' for - // no restriction - bool keepConnected; - bool requireNotify; // require closure notify - // in V3 mode - bool resumableEnable; - bool allowHostnameSpoof; - bool nonBlocking; - char *anchorFile; - char *trustedLeafFile; - bool replaceAnchors; - bool interactiveAuth; - CFArrayRef clientCerts; // optional - CFArrayRef encryptClientCerts; // optional - uint32 sessionCacheTimeout;// optional - bool disableAnonCiphers; - bool showCipherSuites; - bool quiet; // minimal stdout - bool silent; // no stdout - bool verbose; - SSLProtocol negVersion; // RETURNED - SSLCipherSuite negCipher; // RETURNED - CFArrayRef peerCerts; // mallocd & RETURNED - SecTrustRef peerTrust; // RETURNED - SSLClientCertificateState certState; // RETURNED -#if TARGET_OS_MAC && MAC_OS_X_VERSION_MAX_ALLOWED < 1060 - int authType; -#else - SSLClientAuthenticationType authType; // RETURNED -#endif - CFArrayRef dnList; // RETURNED - char *password; // optional to open clientCerts - char **argv; - Boolean sessionWasResumed; - unsigned char sessionID[MAX_SESSION_ID_LENGTH]; - size_t sessionIDLength; - CFAbsoluteTime handshakeTimeOp; // time for this op - CFAbsoluteTime handshakeTimeFirst; // time for FIRST op, not averaged - CFAbsoluteTime handshakeTimeTotal; // time for all ops except first - unsigned numHandshakes; - -} sslPingArgs; - -#include -static void sigpipe(int sig) -{ - fflush(stdin); - printf("***SIGPIPE***\n"); -} - -/* - * Snag a copy of current connection's peer certs so we can - * examine them later after the connection is closed. - * SecureTransport actually does the create and retain for us. - */ -static OSStatus copyPeerCerts( - SSLContext *ctx, - CFArrayRef *peerCerts) // mallocd & RETURNED -{ - OSStatus ortn = SSLCopyPeerCertificates(ctx, peerCerts); - if(ortn) { - printf("***Error obtaining peer certs: %s\n", - sslGetSSLErrString(ortn)); - } - return ortn; -} - -/* - * Manually evaluate session's SecTrustRef. - */ - -static OSStatus sslEvaluateTrust( - SSLContext *ctx, - bool verbose, - bool silent, - CFArrayRef *peerCerts) // fetched and retained -{ - OSStatus ortn = errSecSuccess; -#if USE_CDSA_CRYPTO - SecTrustRef secTrust = NULL; - ortn = SSLGetPeerSecTrust(ctx, &secTrust); - if(ortn) { - printf("\n***Error obtaining peer SecTrustRef: %s\n", - sslGetSSLErrString(ortn)); - return ortn; - } - if(secTrust == NULL) { - /* this is the normal case for resumed sessions, in which - * no cert evaluation is performed */ - if(!silent) { - printf("...No SecTrust available - this is a resumed session, right?\n"); - } - return errSecSuccess; - } - SecTrustResultType secTrustResult; - ortn = SecTrustEvaluate(secTrust, &secTrustResult); - if(ortn) { - printf("\n***Error on SecTrustEvaluate: %d\n", (int)ortn); - return ortn; - } - if(verbose) { - const char *res = NULL; - switch(secTrustResult) { - case kSecTrustResultInvalid: - res = "kSecTrustResultInvalid"; break; - case kSecTrustResultProceed: - res = "kSecTrustResultProceed"; break; - case kSecTrustResultConfirm: - res = "kSecTrustResultConfirm"; break; - case kSecTrustResultDeny: - res = "kSecTrustResultDeny"; break; - case kSecTrustResultUnspecified: - res = "kSecTrustResultUnspecified"; break; - case kSecTrustResultRecoverableTrustFailure: - res = "kSecTrustResultRecoverableTrustFailure"; break; - case kSecTrustResultFatalTrustFailure: - res = "kSecTrustResultFatalTrustFailure"; break; - case kSecTrustResultOtherError: - res = "kSecTrustResultOtherError"; break; - default: - res = "UNKNOWN"; break; - } - printf("\nSecTrustEvaluate(): secTrustResult %s\n", res); - } - - switch(secTrustResult) { - case kSecTrustResultUnspecified: - /* cert chain valid, no special UserTrust assignments */ - case kSecTrustResultProceed: - /* cert chain valid AND user explicitly trusts this */ - break; - default: - printf("\n***SecTrustEvaluate reported secTrustResult %d\n", - (int)secTrustResult); - ortn = errSSLXCertChainInvalid; - break; - } -#endif - - *peerCerts = NULL; - -#ifdef USE_CDSA_CRYPTO - /* one more thing - get peer certs in the form of an evidence chain */ - CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv; - OSStatus thisRtn = SecTrustGetResult(secTrust, &secTrustResult, - peerCerts, &dummyEv); - if(thisRtn) { - printSslErrStr("SecTrustGetResult", thisRtn); - } -#endif - return ortn; -} - -static void sslShowEnabledCipherSuites( - SSLContextRef ctx) -{ - OSStatus status; - SSLCipherSuite *ciphers; - size_t numCiphers, totalCiphers; - unsigned int i; - - status = SSLGetNumberSupportedCiphers(ctx, &totalCiphers); - status = SSLGetNumberEnabledCiphers(ctx, &numCiphers); - ciphers = (SSLCipherSuite *)malloc(sizeof(SSLCipherSuite) * numCiphers); - status = SSLGetEnabledCiphers(ctx, ciphers, &numCiphers); - - printf(" Total enabled ciphers : %ld of %ld\n", numCiphers, totalCiphers); - - for(i=0; i", ((unsigned)c) & 0xff); - } - break; - } - - } - printf("\n"); -} - -/* - * Perform one SSL diagnostic session. Returns nonzero on error. Normally no - * output to stdout except initial "connecting to" message, unless there - * is a really screwed up error (i.e., something not directly related - * to the SSL connection). - */ -#define RCV_BUF_SIZE 256 - -static OSStatus sslPing( - sslPingArgs *pargs) -{ - PeerSpec peerId; - otSocket sock = 0; - OSStatus ortn; - SSLContextRef ctx = NULL; - size_t length; - size_t actLen; - uint8_t rcvBuf[RCV_BUF_SIZE]; - CFAbsoluteTime startHandshake; - CFAbsoluteTime endHandshake; - - pargs->negVersion = kSSLProtocolUnknown; - pargs->negCipher = SSL_NULL_WITH_NULL_NULL; - pargs->peerCerts = NULL; - - /* first make sure requested server is there */ - ortn = MakeServerConnection(pargs->hostName, pargs->port, pargs->nonBlocking, - &sock, &peerId); - if(ortn) { - printf("MakeServerConnection returned %d; aborting\n", (int)ortn); - return ortn; - } - if(pargs->verbose) { - printf("...connected to server; starting SecureTransport\n"); - } - - /* - * Set up a SecureTransport session. - * First the standard calls. - */ - ortn = SSLNewContext(false, &ctx); - if(ortn) { - printSslErrStr("SSLNewContext", ortn); - goto cleanup; - } - ortn = SSLSetIOFuncs(ctx, SocketRead, SocketWrite); - if(ortn) { - printSslErrStr("SSLSetIOFuncs", ortn); - goto cleanup; - } - ortn = SSLSetConnection(ctx, (SSLConnectionRef)sock); - if(ortn) { - printSslErrStr("SSLSetConnection", ortn); - goto cleanup; - } - SSLConnectionRef getConn; - ortn = SSLGetConnection(ctx, &getConn); - if(ortn) { - printSslErrStr("SSLGetConnection", ortn); - goto cleanup; - } - if(getConn != (SSLConnectionRef)sock) { - printf("***SSLGetConnection error\n"); - ortn = errSecParam; - goto cleanup; - } - if(!pargs->allowHostnameSpoof) { - /* if this isn't set, it isn't checked by AppleX509TP */ - const char *vfyHost = pargs->hostName; - if(pargs->vfyHostName) { - /* generally means we're expecting an error */ - vfyHost = pargs->vfyHostName; - } - ortn = SSLSetPeerDomainName(ctx, vfyHost, strlen(vfyHost)); - if(ortn) { - printSslErrStr("SSLSetPeerDomainName", ortn); - goto cleanup; - } - } - - /* - * SecureTransport options. - */ - if(pargs->acceptedProts) { - ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false); - if(ortn) { - printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn); - goto cleanup; - } - for(const char *cp = pargs->acceptedProts; *cp; cp++) { - SSLProtocol prot; - switch(*cp) { - case '2': - prot = kSSLProtocol2; - break; - case '3': - prot = kSSLProtocol3; - break; - case 't': - prot = kTLSProtocol1; - if (cp[1] == 'l' && cp[2] == 's' && cp[3] == '1') { - cp += 3; - if (cp[1] == '1') { - cp++; - prot = kTLSProtocol11; - } - else if (cp[1] == '2') { - cp++; - prot = kTLSProtocol12; - } - } - break; - default: - usage(pargs->argv); - } - ortn = SSLSetProtocolVersionEnabled(ctx, prot, true); - if(ortn) { - printSslErrStr("SSLSetProtocolVersionEnabled", ortn); - goto cleanup; - } - } - } - else { - ortn = SSLSetProtocolVersion(ctx, pargs->tryVersion); - if(ortn) { - printSslErrStr("SSLSetProtocolVersion", ortn); - goto cleanup; - } - SSLProtocol getVers; - ortn = SSLGetProtocolVersion(ctx, &getVers); - if(ortn) { - printSslErrStr("SSLGetProtocolVersion", ortn); - goto cleanup; - } - if(getVers != pargs->tryVersion && getVers != kSSLProtocolAll) { - printf("***SSLGetProtocolVersion screwup: try %s get %s\n", - sslGetProtocolVersionString(pargs->tryVersion), - sslGetProtocolVersionString(getVers)); - ortn = errSecParam; - goto cleanup; - } - } - if(pargs->resumableEnable) { - const void *rtnId = NULL; - size_t rtnIdLen = 0; - - ortn = SSLSetPeerID(ctx, &peerId, sizeof(PeerSpec)); - if(ortn) { - printSslErrStr("SSLSetPeerID", ortn); - goto cleanup; - } - /* quick test of the get fcn */ - ortn = SSLGetPeerID(ctx, &rtnId, &rtnIdLen); - if(ortn) { - printSslErrStr("SSLGetPeerID", ortn); - goto cleanup; - } - if((rtnId == NULL) || (rtnIdLen != sizeof(PeerSpec))) { - printf("***SSLGetPeerID screwup\n"); - } - else if(memcmp(&peerId, rtnId, rtnIdLen) != 0) { - printf("***SSLGetPeerID data mismatch\n"); - } - } - if(pargs->allowExpired) { - ortn = SSLSetAllowsExpiredCerts(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowExpiredCerts", ortn); - goto cleanup; - } - } - if(pargs->allowExpiredRoot) { - ortn = SSLSetAllowsExpiredRoots(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowsExpiredRoots", ortn); - goto cleanup; - } - } - if(pargs->disableCertVerify) { - ortn = SSLSetEnableCertVerify(ctx, false); - if(ortn) { - printSslErrStr("SSLSetEnableCertVerify", ortn); - goto cleanup; - } - } - if(pargs->allowAnyRoot) { - ortn = SSLSetAllowsAnyRoot(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowAnyRoot", ortn); - goto cleanup; - } - } - if(pargs->cipherRestrict != '\0') { - ortn = sslSetCipherRestrictions(ctx, pargs->cipherRestrict); - if(ortn) { - goto cleanup; - } - } - if(pargs->anchorFile) { - ortn = sslAddTrustedRoot(ctx, pargs->anchorFile, pargs->replaceAnchors); - if(ortn) { - printf("***Error obtaining anchor file %s\n", pargs->anchorFile); - goto cleanup; - } - } - if(pargs->trustedLeafFile) { - SecCertificateRef leafCertRef = NULL; - CFMutableArrayRef leafCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - /* sslReadAnchor is a misnomer; it just creates a SecCertificateRef from a file */ - ortn = sslReadAnchor(pargs->trustedLeafFile, &leafCertRef); - if (!ortn) { - CFArrayAppendValue(leafCerts, leafCertRef); - CFRelease(leafCertRef); - ortn = SSLSetTrustedLeafCertificates(ctx, leafCerts); - CFRelease(leafCerts); - } - if(ortn) { - goto cleanup; - } - } - if(pargs->interactiveAuth) { - /* we want to get errSSLServerAuthCompleted from SSLHandshake on server auth completion */ - SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnServerAuth, true); - /* we want to get errSSLClientCertRequested from SSLHandshake on client auth request */ - SSLSetSessionOption(ctx, kSSLSessionOptionBreakOnCertRequested, true); - } - else if(pargs->clientCerts) { - CFArrayRef dummy; - if(pargs->anchorFile == NULL) { - /* assume this is a root we want to implicitly trust */ - ortn = addIdentityAsTrustedRoot(ctx, pargs->clientCerts); - if(ortn) { - goto cleanup; - } - } - ortn = SSLSetCertificate(ctx, pargs->clientCerts); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - goto cleanup; - } - /* quickie test for this new function */ - ortn = SSLGetCertificate(ctx, &dummy); - if(ortn) { - printSslErrStr("SSLGetCertificate", ortn); - goto cleanup; - } - if(dummy != pargs->clientCerts) { - printf("***SSLGetCertificate error\n"); - ortn = errSecIO; - goto cleanup; - } - } - if(pargs->encryptClientCerts) { - if(pargs->anchorFile == NULL) { - ortn = addIdentityAsTrustedRoot(ctx, pargs->encryptClientCerts); - if(ortn) { - goto cleanup; - } - } - ortn = SSLSetEncryptionCertificate(ctx, pargs->encryptClientCerts); - if(ortn) { - printSslErrStr("SSLSetEncryptionCertificate", ortn); - goto cleanup; - } - } - if(pargs->sessionCacheTimeout) { - ortn = SSLSetSessionCacheTimeout(ctx, pargs->sessionCacheTimeout); - if(ortn) { - printSslErrStr("SSLSetSessionCacheTimeout", ortn); - goto cleanup; - } - } - if(!pargs->disableAnonCiphers) { - ortn = SSLSetAllowAnonymousCiphers(ctx, true); - if(ortn) { - printSslErrStr("SSLSetAllowAnonymousCiphers", ortn); - goto cleanup; - } - /* quickie test of the getter */ - Boolean e; - ortn = SSLGetAllowAnonymousCiphers(ctx, &e); - if(ortn) { - printSslErrStr("SSLGetAllowAnonymousCiphers", ortn); - goto cleanup; - } - if(!e) { - printf("***SSLGetAllowAnonymousCiphers() returned false; expected true\n"); - ortn = errSecIO; - goto cleanup; - } - } - if(pargs->showCipherSuites) { - sslShowEnabledCipherSuites(ctx); - } - /*** end options ***/ - - if(pargs->verbose) { - printf("...starting SSL handshake\n"); - } - startHandshake = CFAbsoluteTimeGetCurrent(); - - do - { ortn = SSLHandshake(ctx); - if((ortn == errSSLWouldBlock) && !pargs->silent) { - /* keep UI responsive */ - sslOutputDot(); - } - else if(ortn == errSSLServerAuthCompleted) { - if(pargs->verbose) { - printf("...server authentication completed\n"); - } - } - else if(ortn == errSSLClientCertRequested) { - if(pargs->verbose) { - printf("...received client cert request\n"); - } - /* %%% could prompt interactively here for client cert to use; - * for now, just use the client cert passed on the command line - */ - if(pargs->clientCerts) { - CFArrayRef dummy; - if(pargs->anchorFile == NULL) { - /* assume this is a root we want to implicitly trust */ - ortn = addIdentityAsTrustedRoot(ctx, pargs->clientCerts); - if(ortn) { - goto cleanup; - } - } - if(pargs->verbose) { - printf("...setting client certificate\n"); - } - ortn = SSLSetCertificate(ctx, pargs->clientCerts); - if(ortn) { - printSslErrStr("SSLSetCertificate", ortn); - goto cleanup; - } - /* quickie test for this new function */ - ortn = SSLGetCertificate(ctx, &dummy); - if(ortn) { - printSslErrStr("SSLGetCertificate", ortn); - goto cleanup; - } - if(dummy != pargs->clientCerts) { - printf("***SSLGetCertificate error\n"); - ortn = errSecIO; - goto cleanup; - } - } - else { - printf("***no client certificate specified!\n"); - } - } - } while (ortn == errSSLWouldBlock || - ortn == errSSLServerAuthCompleted || - ortn == errSSLClientCertRequested); - - endHandshake = CFAbsoluteTimeGetCurrent(); - pargs->handshakeTimeOp = endHandshake - startHandshake; - if(pargs->numHandshakes == 0) { - /* special case, this one is always way longer */ - pargs->handshakeTimeFirst = pargs->handshakeTimeOp; - } - else { - /* normal running total */ - pargs->handshakeTimeTotal += pargs->handshakeTimeOp; - } - pargs->numHandshakes++; - - /* this works even if handshake failed due to cert chain invalid */ - CFReleaseSafe(pargs->peerCerts); - if(!pargs->manualCertVerify) { - copyPeerCerts(ctx, &pargs->peerCerts); - } - else { - /* else fetched via SecTrust later */ - pargs->peerCerts = NULL; - } - - ortn = SSLCopyPeerTrust(ctx, &pargs->peerTrust); - if(ortn) { - printf("***SSLCopyPeerTrust error %d\n", (int)ortn); - pargs->peerTrust = NULL; - } - - /* ditto */ - SSLGetClientCertificateState(ctx, &pargs->certState); -#if TARGET_OS_MAC && MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 - SSLGetNegotiatedClientAuthType(ctx, &pargs->authType); -#endif - SSLGetNegotiatedCipher(ctx, &pargs->negCipher); - SSLGetNegotiatedProtocolVersion(ctx, &pargs->negVersion); - CFReleaseSafe(pargs->dnList); - SSLCopyDistinguishedNames(ctx, &pargs->dnList); - pargs->sessionIDLength = MAX_SESSION_ID_LENGTH; - SSLGetResumableSessionInfo(ctx, &pargs->sessionWasResumed, pargs->sessionID, - &pargs->sessionIDLength); - if(pargs->manualCertVerify) { - OSStatus certRtn = sslEvaluateTrust(ctx, pargs->verbose, pargs->silent, - &pargs->peerCerts); - if(certRtn && !ortn ) { - ortn = certRtn; - } - } - - if(ortn) { - if(!pargs->silent) { - printf("\n"); - } - goto cleanup; - } - - if(pargs->verbose) { - printf("...SSL handshake complete\n"); - } - - /* Write our GET request */ - length = strlen(pargs->getMsg); - ortn = SSLWrite(ctx, pargs->getMsg, length, &actLen); - if(ortn) { - printf("***SSLWrite error: %d\n", (int)ortn); - } else if((actLen > 0) && pargs->dumpRxData) { - dumpAscii((uint8_t*)pargs->getMsg, actLen); - } - - /* - * Try to snag RCV_BUF_SIZE bytes. Exit if (!keepConnected and we get any data - * at all), or (keepConnected and err != (none, wouldBlock)). - */ - while (ortn == errSecSuccess) { - actLen = 0; - if(pargs->dumpRxData) { - size_t avail = 0; - - ortn = SSLGetBufferedReadSize(ctx, &avail); - if(ortn) { - printf("***SSLGetBufferedReadSize error\n"); - break; - } - if(avail != 0) { - printf("\n%d bytes available: ", (int)avail); - } - } - ortn = SSLRead(ctx, rcvBuf, RCV_BUF_SIZE, &actLen); - if((actLen == 0) && !pargs->silent) { - sslOutputDot(); - } - if((actLen == 0) && (ortn == errSecSuccess)) { - printf("***Radar 2984932 confirmed***\n"); - } - if (ortn == errSSLWouldBlock) { - /* for this loop, these are identical */ - ortn = errSecSuccess; - } - if(ortn == errSSLServerAuthCompleted || - ortn == errSSLClientCertRequested) { - /* should never get these once the handshake is complete */ - printf("***SSLRead returned unexpected handshake error!\n"); - } - - if((actLen > 0) && pargs->dumpRxData) { - dumpAscii(rcvBuf, actLen); - } - if(ortn != errSecSuccess) { - /* connection closed by server or by error */ - break; - } - if(!pargs->keepConnected && (actLen > 0)) { - /* good enough, we connected */ - break; - } - } - if(!pargs->silent) { - printf("\n"); - } - - /* snag these again in case of renegotiate */ - SSLGetClientCertificateState(ctx, &pargs->certState); - SSLGetNegotiatedCipher(ctx, &pargs->negCipher); - SSLGetNegotiatedProtocolVersion(ctx, &pargs->negVersion); - CFReleaseSafe(pargs->dnList); - SSLCopyDistinguishedNames(ctx, &pargs->dnList); - - /* convert normal "shutdown" into zero err rtn */ - if(ortn == errSSLClosedGraceful) { - ortn = errSecSuccess; - } - if((ortn == errSSLClosedNoNotify) && !pargs->requireNotify) { - /* relaxed disconnect rules */ - ortn = errSecSuccess; - } -cleanup: - /* - * always do close, even on error - to flush outgoing write queue - */ - OSStatus cerr = SSLClose(ctx); - if(ortn == errSecSuccess) { - ortn = cerr; - } - if(sock) { - endpointShutdown(sock); - } - if(ctx) { - SSLDisposeContext(ctx); - } - return ortn; -} - -static void add_key(const void *key, const void *value, void *context) { - CFArrayAppendValue((CFMutableArrayRef)context, key); -} - -static void showInfo(CFDictionaryRef info) { - CFIndex dict_count, key_ix, key_count; - CFMutableArrayRef keys = NULL; - CFIndex maxWidth = 20; /* Maybe precompute this or grab from context? */ - - dict_count = CFDictionaryGetCount(info); - keys = CFArrayCreateMutable(kCFAllocatorDefault, dict_count, - &kCFTypeArrayCallBacks); - CFDictionaryApplyFunction(info, add_key, keys); - key_count = CFArrayGetCount(keys); - CFArraySortValues(keys, CFRangeMake(0, key_count), - (CFComparatorFunction)CFStringCompare, 0); - - for (key_ix = 0; key_ix < key_count; ++key_ix) { - CFStringRef key = (CFStringRef)CFArrayGetValueAtIndex(keys, key_ix); - CFTypeRef value = CFDictionaryGetValue(info, key); - CFMutableStringRef line = CFStringCreateMutable(NULL, 0); - - CFStringAppend(line, key); - CFIndex jx; - for (jx = CFStringGetLength(key); - jx < maxWidth; ++jx) { - CFStringAppend(line, CFSTR(" ")); - } - CFStringAppend(line, CFSTR(" : ")); - if (CFStringGetTypeID() == CFGetTypeID(value)) { - CFStringAppend(line, (CFStringRef)value); - } else if (CFDateGetTypeID() == CFGetTypeID(value)) { - CFLocaleRef lc = CFLocaleCopyCurrent(); - CFDateFormatterRef df = CFDateFormatterCreate(NULL, lc, - kCFDateFormatterFullStyle, kCFDateFormatterFullStyle); - CFDateRef date = (CFDateRef)value; - CFStringRef ds = CFDateFormatterCreateStringWithDate(NULL, df, - date); - CFStringAppend(line, ds); - CFRelease(ds); - CFRelease(df); - CFRelease(lc); - } else if (CFURLGetTypeID() == CFGetTypeID(value)) { - CFURLRef url = (CFURLRef)value; - CFStringAppend(line, CFSTR("<")); - CFStringAppend(line, CFURLGetString(url)); - CFStringAppend(line, CFSTR(">")); - } else if (CFDataGetTypeID() == CFGetTypeID(value)) { - CFDataRef v_d = (CFDataRef)value; - CFStringRef v_s = CFStringCreateFromExternalRepresentation( - kCFAllocatorDefault, v_d, kCFStringEncodingUTF8); - if (v_s) { - CFStringAppend(line, CFSTR("/")); - CFStringAppend(line, v_s); - CFStringAppend(line, CFSTR("/ ")); - CFRelease(v_s); - } - const uint8_t *bytes = CFDataGetBytePtr(v_d); - CFIndex len = CFDataGetLength(v_d); - for (jx = 0; jx < len; ++jx) { - CFStringAppendFormat(line, NULL, CFSTR("%.02X"), bytes[jx]); - } - } else { - CFStringAppendFormat(line, NULL, CFSTR("%@"), value); - } - print_line(line); - CFRelease(line); - } - CFRelease(keys); -} - -static void showPeerTrust(SecTrustRef peerTrust, bool verbose) { - CFIndex numCerts; - CFIndex i; - - if(peerTrust == NULL) { - return; - } -#if TARGET_OS_EMBEDDED - printf("\n=============== Peer Trust Properties ===============\n"); - CFArrayRef plist = SecTrustCopyProperties(peerTrust); - if (plist) { - print_plist(plist); - CFRelease(plist); - } - - printf("\n================== Peer Trust Info ==================\n"); - CFDictionaryRef info = SecTrustCopyInfo(peerTrust); - if (info && CFDictionaryGetCount(info)) { - showInfo(info); - CFRelease(info); - } - - numCerts = SecTrustGetCertificateCount(peerTrust); - for(i=0; i= 1060 - printf(" Client Auth Type : %s\n", - sslGetClientAuthTypeString(pargs.authType)); -#endif - } - if(pargs.verbose) { - printf(" Resumed Session : "); - if(pargs.sessionWasResumed) { - for(unsigned dex=0; dex maxProtocol) { - /* known not to support this attempt, relax */ - reqProtocol = maxProtocol; - } - if(reqProtocol != negProtocol) { - printf("***Expected protocol %s; negotiated %s\n", - sslGetProtocolVersionString(reqProtocol), - sslGetProtocolVersionString(negProtocol)); - return 1; - } - else { - return 0; - } -} - -static int verifyClientCertState( - bool verifyCertState, - SSLClientCertificateState expectState, - SSLClientCertificateState gotState) -{ - if(!verifyCertState) { - return 0; - } - if(expectState == gotState) { - return 0; - } - printf("***Expected clientCertState %s; got %s\n", - sslGetClientCertStateString(expectState), - sslGetClientCertStateString(gotState)); - return 1; -} - -/* - * Free everything allocated by sslPing in an sslPingArgs. - * Mainly for looping and malloc debugging. - */ -static void freePingArgs( - sslPingArgs *pargs) -{ - CFReleaseNull(pargs->peerCerts); - CFReleaseNull(pargs->peerTrust); - CFReleaseNull(pargs->dnList); - /* more, later, for client retry/identity fetch */ -} - -static SSLProtocol strToProt( - const char *c, // 2, 3, t, tls10, tls11, tls12 - char **argv) -{ - if (c == NULL) - return kSSLProtocolUnknown; - - switch(c[0]) { - case '2': - return kSSLProtocol2; - case '3': - return kSSLProtocol3; - case 't': - if (c[1] == '\0') - return kTLSProtocol1; - if (c[1] == 'l' && c[2] == 's' && c[3] == '1') { - if (c[4] == '0') - return kTLSProtocol1; - if (c[4] == '1') - return kTLSProtocol11; - if (c[4] == '2') - return kTLSProtocol12; - } - default: - usage(argv); - } - /* NOT REACHED */ - return kSSLProtocolUnknown; -} - -int main(int argc, char **argv) -{ - OSStatus err; - int arg; - char *argp; - char getMsg[300]; - char fullFileBase[100]; - int ourRtn = 0; // exit status - sum of all errors - unsigned loop; - SecKeychainRef serverKc = nil; - SecKeychainRef encryptKc = nil; - sslPingArgs pargs; - - /* user-spec'd parameters */ - char *getPath = (char *)DEFAULT_PATH; - char *fileBase = NULL; - bool displayCerts = false; - bool doSslV2 = false; - bool doSslV3 = false; - bool doTlsV1 = true; - bool doTlsV11 = true; - bool doTlsV12 = true; - bool protXOnly = false; // kSSLProtocol3Only, kTLSProtocol1Only - bool doProtUnknown = false; - unsigned loopCount = 1; - bool doPause = false; - bool pauseFirstLoop = false; - bool verifyProt = false; - SSLProtocol maxProtocol = kTLSProtocol12; // for verifying negotiated - // protocol - char *acceptedProts = NULL; - char *keyChainName = NULL; - char *encryptKeyChainName = NULL; - char *getMsgSpec = NULL; - bool vfyCertState = false; - SSLClientCertificateState expectCertState = kSSLClientCertNone; - bool displayHandshakeTimes = false; - bool completeCertChain = false; - char *dnFileBase = NULL; - - /* special case - one arg of "h" or "-h" or "hv" */ - if(argc == 2) { - if((strcmp(argv[1], "h") == 0) || (strcmp(argv[1], "-h") == 0)) { - usage(argv); - } - if(strcmp(argv[1], "hv") == 0) { - usageVerbose(argv); - } - } - - /* set up defaults */ - memset(&pargs, 0, sizeof(sslPingArgs)); - pargs.hostName = DEFAULT_HOST; - pargs.port = DEFAULT_PORT; - pargs.resumableEnable = true; - pargs.argv = argv; - - for(arg=1; arg 1) ? "errors" : "error", pargs.hostName); - } - return ourRtn; - -} - - diff --git a/OSX/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj b/OSX/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj deleted file mode 100644 index 28692e94..00000000 --- a/OSX/libsecurity_ssl/sslViewer/sslViewer.xcodeproj/project.pbxproj +++ /dev/null @@ -1,454 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - BEF16C401553365F0074AFAD /* world */ = { - isa = PBXAggregateTarget; - buildConfigurationList = BEF16C431553365F0074AFAD /* Build configuration list for PBXAggregateTarget "world" */; - buildPhases = ( - ); - dependencies = ( - BEF16C4B155343F10074AFAD /* PBXTargetDependency */, - BEF16C4E155343F30074AFAD /* PBXTargetDependency */, - ); - name = world; - productName = world; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - BE022AF51552191100564DFE /* sslServer.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BE022AF41552191100564DFE /* sslServer.1 */; }; - BE022AF9155219D300564DFE /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE4E516815520B380015140F /* CFNetwork.framework */; }; - BE022AFA155219D500564DFE /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE4E516615520B2F0015140F /* CoreFoundation.framework */; }; - BE022AFB155219D700564DFE /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE4E516415520AE20015140F /* Security.framework */; }; - BE022AFD15521A1900564DFE /* sslServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE022AFC15521A1900564DFE /* sslServer.cpp */; }; - BE022AFE15521A2100564DFE /* fileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4E516A15520CF00015140F /* fileIo.c */; }; - BE022AFF15521A2400564DFE /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4E515E15520AC30015140F /* ioSock.c */; }; - BE022B0015521A2800564DFE /* printCert.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4E516215520AD30015140F /* printCert.c */; }; - BE022B0115521A2B00564DFE /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE4E516015520AC80015140F /* sslAppUtils.cpp */; }; - BE43DE031552106C004BE474 /* fileIo.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4E516A15520CF00015140F /* fileIo.c */; }; - BE4E515115520A150015140F /* sslViewer.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = BE4E515015520A150015140F /* sslViewer.1 */; }; - BE4E516515520AE20015140F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE4E516415520AE20015140F /* Security.framework */; }; - BE4E516715520B2F0015140F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE4E516615520B2F0015140F /* CoreFoundation.framework */; }; - BE4E516915520B380015140F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE4E516815520B380015140F /* CFNetwork.framework */; }; - BE4E516E15520D460015140F /* sslViewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE4E515C15520AB90015140F /* sslViewer.cpp */; }; - BE4E516F15520D480015140F /* sslAppUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BE4E516015520AC80015140F /* sslAppUtils.cpp */; }; - BE4E517115520D530015140F /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4E515E15520AC30015140F /* ioSock.c */; }; - BE4E517215520D570015140F /* printCert.c in Sources */ = {isa = PBXBuildFile; fileRef = BE4E516215520AD30015140F /* printCert.c */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - BEF16C4A155343F10074AFAD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BE4E514115520A150015140F /* Project object */; - proxyType = 1; - remoteGlobalIDString = BE4E514915520A150015140F; - remoteInfo = sslViewer; - }; - BEF16C4D155343F30074AFAD /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BE4E514115520A150015140F /* Project object */; - proxyType = 1; - remoteGlobalIDString = BE022AEE1552191100564DFE; - remoteInfo = sslServer; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - BE022AED1552191100564DFE /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - BE022AF51552191100564DFE /* sslServer.1 in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; - BE4E514815520A150015140F /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - BE4E515115520A150015140F /* sslViewer.1 in CopyFiles */, - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - BE022AEF1552191100564DFE /* sslServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sslServer; sourceTree = BUILT_PRODUCTS_DIR; }; - BE022AF41552191100564DFE /* sslServer.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sslServer.1; sourceTree = SOURCE_ROOT; }; - BE022AFC15521A1900564DFE /* sslServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sslServer.cpp; sourceTree = SOURCE_ROOT; }; - BE4E514A15520A150015140F /* sslViewer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sslViewer; sourceTree = BUILT_PRODUCTS_DIR; }; - BE4E515015520A150015140F /* sslViewer.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = sslViewer.1; sourceTree = SOURCE_ROOT; }; - BE4E515C15520AB90015140F /* sslViewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sslViewer.cpp; sourceTree = SOURCE_ROOT; }; - BE4E515E15520AC30015140F /* ioSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioSock.c; sourceTree = SOURCE_ROOT; }; - BE4E516015520AC80015140F /* sslAppUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sslAppUtils.cpp; sourceTree = SOURCE_ROOT; }; - BE4E516215520AD30015140F /* printCert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = printCert.c; sourceTree = SOURCE_ROOT; }; - BE4E516415520AE20015140F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - BE4E516615520B2F0015140F /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - BE4E516815520B380015140F /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - BE4E516A15520CF00015140F /* fileIo.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = fileIo.c; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - BE022AEC1552191100564DFE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - BE022AF9155219D300564DFE /* CFNetwork.framework in Frameworks */, - BE022AFA155219D500564DFE /* CoreFoundation.framework in Frameworks */, - BE022AFB155219D700564DFE /* Security.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - BE4E514715520A150015140F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - BE4E516515520AE20015140F /* Security.framework in Frameworks */, - BE4E516715520B2F0015140F /* CoreFoundation.framework in Frameworks */, - BE4E516915520B380015140F /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - BE022AF11552191100564DFE /* sslServer */ = { - isa = PBXGroup; - children = ( - BE022AFC15521A1900564DFE /* sslServer.cpp */, - BE022AF41552191100564DFE /* sslServer.1 */, - ); - path = sslServer; - sourceTree = SOURCE_ROOT; - }; - BE4E513F15520A150015140F = { - isa = PBXGroup; - children = ( - BE7168DA1552154E00483067 /* sslUtils */, - BE4E514D15520A150015140F /* sslViewer */, - BE022AF11552191100564DFE /* sslServer */, - BE7168D8155214F800483067 /* Frameworks */, - BE4E514B15520A150015140F /* Products */, - ); - sourceTree = ""; - }; - BE4E514B15520A150015140F /* Products */ = { - isa = PBXGroup; - children = ( - BE4E514A15520A150015140F /* sslViewer */, - BE022AEF1552191100564DFE /* sslServer */, - ); - name = Products; - sourceTree = ""; - }; - BE4E514D15520A150015140F /* sslViewer */ = { - isa = PBXGroup; - children = ( - BE4E515C15520AB90015140F /* sslViewer.cpp */, - BE4E515015520A150015140F /* sslViewer.1 */, - ); - path = sslViewer; - sourceTree = ""; - }; - BE7168D8155214F800483067 /* Frameworks */ = { - isa = PBXGroup; - children = ( - BE4E516815520B380015140F /* CFNetwork.framework */, - BE4E516615520B2F0015140F /* CoreFoundation.framework */, - BE4E516415520AE20015140F /* Security.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - BE7168DA1552154E00483067 /* sslUtils */ = { - isa = PBXGroup; - children = ( - BE4E516A15520CF00015140F /* fileIo.c */, - BE4E515E15520AC30015140F /* ioSock.c */, - BE4E516215520AD30015140F /* printCert.c */, - BE4E516015520AC80015140F /* sslAppUtils.cpp */, - ); - name = sslUtils; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - BE022AEE1552191100564DFE /* sslServer */ = { - isa = PBXNativeTarget; - buildConfigurationList = BE022AF61552191100564DFE /* Build configuration list for PBXNativeTarget "sslServer" */; - buildPhases = ( - BE022AEB1552191100564DFE /* Sources */, - BE022AEC1552191100564DFE /* Frameworks */, - BE022AED1552191100564DFE /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = sslServer; - productName = sslServer; - productReference = BE022AEF1552191100564DFE /* sslServer */; - productType = "com.apple.product-type.tool"; - }; - BE4E514915520A150015140F /* sslViewer */ = { - isa = PBXNativeTarget; - buildConfigurationList = BE4E515415520A150015140F /* Build configuration list for PBXNativeTarget "sslViewer" */; - buildPhases = ( - BE4E514615520A150015140F /* Sources */, - BE4E514715520A150015140F /* Frameworks */, - BE4E514815520A150015140F /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = sslViewer; - productName = sslViewer; - productReference = BE4E514A15520A150015140F /* sslViewer */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - BE4E514115520A150015140F /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0440; - }; - buildConfigurationList = BE4E514415520A150015140F /* Build configuration list for PBXProject "sslViewer" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = BE4E513F15520A150015140F; - productRefGroup = BE4E514B15520A150015140F /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - BEF16C401553365F0074AFAD /* world */, - BE4E514915520A150015140F /* sslViewer */, - BE022AEE1552191100564DFE /* sslServer */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - BE022AEB1552191100564DFE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BE022AFD15521A1900564DFE /* sslServer.cpp in Sources */, - BE022B0115521A2B00564DFE /* sslAppUtils.cpp in Sources */, - BE022AFE15521A2100564DFE /* fileIo.c in Sources */, - BE022AFF15521A2400564DFE /* ioSock.c in Sources */, - BE022B0015521A2800564DFE /* printCert.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - BE4E514615520A150015140F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - BE4E516E15520D460015140F /* sslViewer.cpp in Sources */, - BE4E516F15520D480015140F /* sslAppUtils.cpp in Sources */, - BE43DE031552106C004BE474 /* fileIo.c in Sources */, - BE4E517115520D530015140F /* ioSock.c in Sources */, - BE4E517215520D570015140F /* printCert.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - BEF16C4B155343F10074AFAD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BE4E514915520A150015140F /* sslViewer */; - targetProxy = BEF16C4A155343F10074AFAD /* PBXContainerItemProxy */; - }; - BEF16C4E155343F30074AFAD /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = BE022AEE1552191100564DFE /* sslServer */; - targetProxy = BEF16C4D155343F30074AFAD /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - BE022AF71552191100564DFE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - "HEADER_SEARCH_PATHS[arch=*]" = ( - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(HEADER_SEARCH_PATHS)", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - }; - name = Debug; - }; - BE022AF81552191100564DFE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - "HEADER_SEARCH_PATHS[arch=*]" = ( - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(HEADER_SEARCH_PATHS)", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - }; - name = Release; - }; - BE4E515215520A150015140F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - "HEADER_SEARCH_PATHS[arch=*]" = ( - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(HEADER_SEARCH_PATHS)", - "$(PROJECT_DIR)/../Security", - ); - MACOSX_DEPLOYMENT_TARGET = 10.8; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = ""; - }; - name = Debug; - }; - BE4E515315520A150015140F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - "HEADER_SEARCH_PATHS[arch=*]" = ( - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(HEADER_SEARCH_PATHS)", - "$(PROJECT_DIR)/../Security", - ); - MACOSX_DEPLOYMENT_TARGET = 10.8; - SDKROOT = ""; - }; - name = Release; - }; - BE4E515515520A150015140F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - "HEADER_SEARCH_PATHS[arch=*]" = ( - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(HEADER_SEARCH_PATHS)", - "$(PROJECT_DIR)", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - }; - name = Debug; - }; - BE4E515615520A150015140F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - "HEADER_SEARCH_PATHS[arch=*]" = ( - "$(SYSTEM_LIBRARY_DIR)/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers", - "$(HEADER_SEARCH_PATHS)", - "$(PROJECT_DIR)", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = ""; - }; - name = Release; - }; - BEF16C411553365F0074AFAD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - BEF16C421553365F0074AFAD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - BE022AF61552191100564DFE /* Build configuration list for PBXNativeTarget "sslServer" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BE022AF71552191100564DFE /* Debug */, - BE022AF81552191100564DFE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - BE4E514415520A150015140F /* Build configuration list for PBXProject "sslViewer" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BE4E515215520A150015140F /* Debug */, - BE4E515315520A150015140F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - BE4E515415520A150015140F /* Build configuration list for PBXNativeTarget "sslViewer" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BE4E515515520A150015140F /* Debug */, - BE4E515615520A150015140F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - BEF16C431553365F0074AFAD /* Build configuration list for PBXAggregateTarget "world" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - BEF16C411553365F0074AFAD /* Debug */, - BEF16C421553365F0074AFAD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = BE4E514115520A150015140F /* Project object */; -} diff --git a/OSX/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig b/OSX/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig index 80001ccd..2a6db42c 100644 --- a/OSX/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig +++ b/OSX/libsecurity_transform/Configurations/libsecurity_transform_core.xcconfig @@ -24,3 +24,4 @@ OTHER_LDFLAGS_normal = $(OPT_LDFLAGS) $(OTHER_LDFLAGS) OTHER_LDFLAGS_profile = $(OPT_LDFLAGS) $(OTHER_LDFLAGS) -pg GCC_ENABLE_CPP_EXCEPTIONS = NO GCC_ENABLE_CPP_RTTI = NO +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_transform/Configurations/security_transform_Default.xcconfig b/OSX/libsecurity_transform/Configurations/security_transform_Default.xcconfig index 9ef6111a..cb2357ee 100644 --- a/OSX/libsecurity_transform/Configurations/security_transform_Default.xcconfig +++ b/OSX/libsecurity_transform/Configurations/security_transform_Default.xcconfig @@ -6,3 +6,4 @@ WRAPPER_EXTENSION = framework EXECUTABLE_SUFFIX = GCC_ENABLE_CPP_EXCEPTIONS = NO GCC_ENABLE_CPP_RTTI = NO +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig b/OSX/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig index fd75ed9b..d79ea3fc 100644 --- a/OSX/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig +++ b/OSX/libsecurity_transform/Configurations/security_transform_Deployment.xcconfig @@ -8,3 +8,4 @@ EXECUTABLE_SUFFIX = ZERO_LINK = NO GCC_ENABLE_CPP_EXCEPTIONS = NO GCC_ENABLE_CPP_RTTI = NO +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_transform/Configurations/security_transform_Development.xcconfig b/OSX/libsecurity_transform/Configurations/security_transform_Development.xcconfig index 2dd2c64c..0d2deb5a 100644 --- a/OSX/libsecurity_transform/Configurations/security_transform_Development.xcconfig +++ b/OSX/libsecurity_transform/Configurations/security_transform_Development.xcconfig @@ -11,3 +11,4 @@ GCC_GENERATE_DEBUGGING_SYMBOLS = YES ZERO_LINK = YES GCC_ENABLE_CPP_EXCEPTIONS = NO GCC_ENABLE_CPP_RTTI = NO +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) OSSPINLOCK_USE_INLINED=0 diff --git a/OSX/libsecurity_transform/custom.h b/OSX/libsecurity_transform/custom.h index fc5a9464..3e308d53 100644 --- a/OSX/libsecurity_transform/custom.h +++ b/OSX/libsecurity_transform/custom.h @@ -22,10 +22,10 @@ */ -#import +#import -@interface custom : SenTestCase { +@interface custom : XCTestCase { } diff --git a/OSX/libsecurity_transform/lib/SecDigestTransform.h b/OSX/libsecurity_transform/lib/SecDigestTransform.h index cb6dfa65..83415105 100644 --- a/OSX/libsecurity_transform/lib/SecDigestTransform.h +++ b/OSX/libsecurity_transform/lib/SecDigestTransform.h @@ -93,7 +93,7 @@ extern const CFStringRef kSecDigestTypeAttribute; /*! @constant kSecDigestLengthAttribute Used with SecTransformGetAttribute to query the length attribute. - Returns a CFNumberRef that contains the length. + Returns a CFNumberRef that contains the length in bytes. */ extern const CFStringRef kSecDigestLengthAttribute; diff --git a/OSX/libsecurity_transform/lib/c++utils.cpp b/OSX/libsecurity_transform/lib/c++utils.cpp index cb00ea23..798ea84f 100644 --- a/OSX/libsecurity_transform/lib/c++utils.cpp +++ b/OSX/libsecurity_transform/lib/c++utils.cpp @@ -24,7 +24,7 @@ std::string StringFromCFString(CFStringRef theString) CFStringGetCString(theString, buffer, maxLength, 0); string result(buffer); - delete [] buffer; + delete[] buffer; return result; } diff --git a/OSX/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj b/OSX/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj index fcd899c4..a48f2532 100644 --- a/OSX/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_transform/libsecurity_transform.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 18C5A961148442000010EF34 /* libsecurity_transform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */; }; - 18C5A964148443F00010EF34 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C5A963148443F00010EF34 /* SenTestingKit.framework */; }; 18C5A9661484440D0010EF34 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 18C5A9651484440D0010EF34 /* Foundation.framework */; }; 4C010B9B121AE9960094CB72 /* speed-test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4C010B9A121AE9960094CB72 /* speed-test.mm */; }; 4C010BBB121AECF10094CB72 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D16D6FB114EA1000096BD75 /* Security.framework */; }; @@ -111,7 +110,6 @@ 18BBC73B1471F6DF00F2B224 /* lib.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = lib.xcconfig; sourceTree = ""; }; 18BBC73C1471F6DF00F2B224 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = ""; }; 18BBC73D1471F6DF00F2B224 /* security.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = security.xcconfig; sourceTree = ""; }; - 18C5A963148443F00010EF34 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 18C5A9651484440D0010EF34 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 4C010B87121AE8DF0094CB72 /* input-speed-test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "input-speed-test"; sourceTree = BUILT_PRODUCTS_DIR; }; 4C010B99121AE9960094CB72 /* speed-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "speed-test.h"; path = "misc/speed-test.h"; sourceTree = ""; }; @@ -129,7 +127,7 @@ 4C6E5965116D4E3E00A70E8F /* misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = misc.h; sourceTree = ""; }; 4C73822B112DCC4800EA003B /* SecCustomTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecCustomTransform.h; sourceTree = ""; }; 4C73822C112DCC4800EA003B /* SecCustomTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = SecCustomTransform.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; - 4C738257112DF65200EA003B /* unit-tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "unit-tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C738257112DF65200EA003B /* unit-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "unit-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 4C738258112DF65200EA003B /* unit-tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "unit-tests-Info.plist"; sourceTree = ""; }; 4C738260112DF68900EA003B /* custom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = custom.h; sourceTree = ""; }; 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_transform.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -216,7 +214,6 @@ buildActionMask = 2147483647; files = ( 18C5A9661484440D0010EF34 /* Foundation.framework in Frameworks */, - 18C5A964148443F00010EF34 /* SenTestingKit.framework in Frameworks */, 18C5A961148442000010EF34 /* libsecurity_transform.a in Frameworks */, 4CD6A669113F41990094F287 /* libz.dylib in Frameworks */, 4CC4A8B21264D22300075C8F /* Security.framework in Frameworks */, @@ -269,7 +266,6 @@ isa = PBXGroup; children = ( 18C5A9651484440D0010EF34 /* Foundation.framework */, - 18C5A963148443F00010EF34 /* SenTestingKit.framework */, 18BBC7381471F6DF00F2B224 /* config */, 4C27A37414F2D66C007FCA66 /* libcorecrypto.dylib */, 4C010BBE121AED340094CB72 /* libc++.dylib */, @@ -290,7 +286,7 @@ isa = PBXGroup; children = ( 4CA1FEBE052A3C8100F22E42 /* libsecurity_transform.a */, - 4C738257112DF65200EA003B /* unit-tests.octest */, + 4C738257112DF65200EA003B /* unit-tests.xctest */, 4CBCBEB61130A2D700CC18E9 /* 100-sha2 */, 4C010B87121AE8DF0094CB72 /* input-speed-test */, ); @@ -468,8 +464,8 @@ ); name = "unit-tests"; productName = "unit-tests"; - productReference = 4C738257112DF65200EA003B /* unit-tests.octest */; - productType = "com.apple.product-type.bundle.ocunit-test"; + productReference = 4C738257112DF65200EA003B /* unit-tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; }; 4CA1FEBD052A3C8100F22E42 /* libsecurity_transform */ = { isa = PBXNativeTarget; @@ -511,8 +507,8 @@ 4CA1FEAB052A3C3800F22E42 /* Project object */ = { isa = PBXProject; attributes = { - LastTestingUpgradeCheck = 0700; - LastUpgradeCheck = 0700; + LastTestingUpgradeCheck = 0730; + LastUpgradeCheck = 0800; }; buildConfigurationList = C27AD4040987FCDF001272E0 /* Build configuration list for PBXProject "libsecurity_transform" */; compatibilityVersion = "Xcode 3.2"; @@ -699,8 +695,8 @@ "$(inherited)", /usr/lib/system, ); + PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "unit-tests"; - WRAPPER_EXTENSION = octest; }; name = Debug; }; @@ -718,8 +714,8 @@ "$(inherited)", /usr/lib/system, ); + PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "unit-tests"; - WRAPPER_EXTENSION = octest; }; name = Release; }; @@ -806,6 +802,10 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18BBC73A1471F6DF00F2B224 /* debug.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = lossless; + ENABLE_TESTABILITY = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; }; name = Debug; @@ -814,6 +814,8 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18BBC73C1471F6DF00F2B224 /* release.xcconfig */; buildSettings = { + ASSETCATALOG_COMPRESSION = "respect-asset-catalog"; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; SDKROOT = macosx.internal; }; name = Release; diff --git a/OSX/libsecurity_transform/unit-tests-Info.plist b/OSX/libsecurity_transform/unit-tests-Info.plist index c285a472..66a5a8a2 100644 --- a/OSX/libsecurity_transform/unit-tests-Info.plist +++ b/OSX/libsecurity_transform/unit-tests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/OSX/libsecurity_translocate/lib/SecTranslocate.cpp b/OSX/libsecurity_translocate/lib/SecTranslocate.cpp new file mode 100644 index 00000000..a86aa4c8 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocate.cpp @@ -0,0 +1,500 @@ +/* + * 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 +#include +#include + +#include +#include + +#include +#include +#include + +#include "SecTranslocate.h" +#include "SecTranslocateShared.hpp" +#include "SecTranslocateInterface.hpp" +#include "SecTranslocateUtilities.hpp" + + +/* Strategy: + + This library exists to create and destroy app translocation points. To ensure that a given + process using this library is only making or destroying one mountpoint at a time, the two + interface functions are sychronized on a dispatch queue. + + **** App Translocation Strategy w/o a destination path **** + (This functionality is implemented in SecTranslocateShared.hpp/cpp) + + To create a translocation mountpoint, if no destination path is provided, first the app + path to be translocated is realpathed to ensure it exists and there are no symlink's in + the path we work with. Then the calling user's _CS_DARWIN_USER_TEMP_DIR is found. This + is used to calculate the user's AppTranslocation directory. The formula is: + User's App Translocation Directory = realpath(confstr(_CS_DARWIN_USER_TEMP_DIR))+/AppTranslocation/ + + Then the mount table is checked to see whether or not a translocation point already exists + for this user for the app being requested. The rule for an already existing mount is that + there must exist a mountpoint in the user's app translocation directory that is mounted + from realpath of the requested app. + + If a mount exists already for this user, then the path to the app in that mountpoint is + calculated and sanity checked. + + The rules to create the app path inside the mountpoint are: + + original app path = /some/path/ + new app path = realpath(confstr(_CS_DARWIN_USER_TEMP_DIR))+/AppTranslocation//d/ + + The sanity check for the new app path is that: + 1. new app path exists + 2. new app path is in a nullfs mount + 3. new app path is already completely resolved. + + If the sanity checks pass for the new app path, then that path is returned to the caller. + + If no translocation mount point exists already per the mount table then an AppTranslocation + directory is created within the temp dir if it doesn't already exist. After that a UUID is + generated, that UUID is used as the name of a new directory in the AppTranslocation directory. + Once the new directory has been created and sanity checked, mount is called to create the + translocation between the original path and the new directory. Then the new path to the app + within the mountpoint is calculated and sanity checked. + + The sanity check rules for the mountpoint before the mount are: + 1. Something exists at the expected path + 2. That something is a directory + 3. That something is not already a mountpoint + 4. The expected path is fully resolved + + The sanity check for the new app path is listed above (for the mountpoint exists case). + + **** App Translocation strategy w/ a destination path **** + (This functionality is implemented in SecTranslocateShared.hpp/cpp) + + If a destination path is provided, a sequence similar to that described above is followed + with the following modifications. + + The destination path is expected to be of the same form as new app path. This expectation + is verified. + + First we verify that the destination path ends with /d/ and that the + component of the destination path matches the of the original app app path + requested. If not, an error occurs. Everything before the /d/ is treated becomes the + requested destination mount point. + + After the user's app translocation directory is calculated, we ensure that the requested + destination mount point is prefixed by the translocation directory, and contains only one + path component after the user's app translocation path, otherwise an error occurs. + + When we check the mount table, we make sure that if the a translocation of the app already + exists for the user, then the translocation path must exactly match the requested + destination path, otherwise an error occurs. + + If no mountpoint exists for the app, then we attempt to create the requested directory within + the user's app translocation directory. This becomes the mount point, and the mount point + sanity checks listed above are applied. + + If the requested destination mountpoint is successfully created, the flow continues as above + to create the mount and verify the requested path within the mountpoint. The only extra step + here is that at the end, the requested app path, must exactly equal the created app path. + + **** App Translocation error cleanup **** + (This functionality is implemented in SecTranslocateShared.hpp/cpp) + + The error cleanup strategy for translocation creation is to try to destroy any directories + or mount points in the user's translocation directory that were created before an error + was detected. This means tracking whether we created a directory, or it already existed when + a caller asked for it. Clean up is considered best effort. + + **** Deleting an App Translocation point **** + (This functionality is implemented in SecTranslocateShared.hpp/cpp) + + To destroy an app translocation point, the first thing we do is calculate the user's app + translocation directory to ensure that the requested path is actually within that directory. + We also verify that it is in fact a nullfs mount point. If it is, then we attempt to unmount and + remove the translocation point. + + Regardless of whether or not the requested path is a translocation point, we opportunistically + attempt to cleanup the app translocation directory. Clean up means, looping through all the + directories currently in the user's app translocation directory and checking whether or not + they are a mount point. If a directory inside the user's app translocation directory is not + a mountpoint, then we attempt to delete it. + + **** Quarantine considerations **** + (This functionality is implemented in SecTranslocateShared.hpp/cpp and SecTranslocateUtilities.hpp/cpp) + + If the original app path includes files with quarantine extended attributes, then those extended + attributes will be readable through the created app translocation mountpoint. nullfs does not + support removing or setting extended attributes on its vnodes. Changes to the quarantine + attributes at the original path will be reflected in the app translocation mountpoint without + creating a new mount point. + + If the original app path is inside a quarantined mountpoint (such as a quarantined dmg), then + that the quarantine information for that mountpoint is read from the original app path's + mountpoint and applied to the created app translocation mountpoint. + + **** Concurrency considerations **** + This library treats the kernel as the source of truth for the status of the file system. + Unfortunately it has no way to lock the state of the file system and mount table while + it is operating. Because of this, there are two potential areas that have race windows. + + First, if any other system entity (thread within the same process, or other process + within the system) is adding or removing entries from the mount table while + SecTranslocateCreateSecureDirectoryForURL is executing, then there is the possibility that + an incorrect decision will be made about the current existence of a mount point for a user + for an app. This is because getfsstat gets a snapshot of the mount table state rather than a + locked window into the kernel and because we make two seperate calls to getfsstat, one to get + the number of mountpoints, and a second to actually read the mountpoint data. If more than + one process is using this library for the same user, then both processes could attempt to + create a translocation for the same app, and this could result in more than one translocation + for that app for the user. This shouldn't effect the user other than using additional + system resources. We attempt to mitigate this by allocating double the required memory from + the first call and then trying the process again (once) if the initial memory was filled. + + Second, if more than one process is using this library simultaneously and one process calls + SecTranslocateDeleteSecureDirectory for a user and the other calls + SecTranslocateCreateSecureDirectoryForURL for that same user, then the call to + SecTranslocateDeleteSecureDirectory may cause SecTranslocateCreateSecureDirectoryForURL to + fail. This will occur if the loop checking for unmounted directories in the user's app + translocation directory deletes a newly created directory before the mount call finishes. This + race condition will probably result in a failed app launch. A second attempt to launch the app + will probably succeed. + + Concurrency is now split between SecTranslocateClient.hpp/cpp, SecTranslocateServer.hpp/cpp, + SecTranslocateDANotification.hpp/cpp, SecTranslocateLSNotification.hpp/cpp, and + SecTranslocateXPCServer.hpp/cpp. Each of these represent different ways of entering translocation + functionality. + + **** Logging Strategy **** + Use warning logging for interesting conditions (e.g. translocation point created or destroyed). + Use error logging for non-fatal failures. Use critical logging for fatal failures. + */ + +/* Make a CFError from an POSIX error code */ +static CFErrorRef SecTranslocateMakePosixError(CFIndex errorCode) +{ + return CFErrorCreate(NULL, kCFErrorDomainPOSIX, errorCode, NULL); +} + +/* must be called before any other function in this SPI if the process is intended to be the server */ +Boolean SecTranslocateStartListening(CFErrorRef* __nullable error) +{ + Boolean result = false; + CFIndex errorCode = 0; + try + { + /* ask getTranslocator for the server */ + result = Security::SecTranslocate::getTranslocator(true) != NULL; + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocate: uncaught exception during server initialization"); + errorCode = EINVAL; + } + + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + + return result; +} + +/* placeholder api for now to allow for future options at startup */ +Boolean SecTranslocateStartListeningWithOptions(CFDictionaryRef __unused options, CFErrorRef * __nullable outError) +{ + return SecTranslocateStartListening(outError); +} + +/* Register that a (translocated) pid has launched */ +void SecTranslocateAppLaunchCheckin(pid_t pid) +{ + try + { + Security::SecTranslocate::getTranslocator()->appLaunchCheckin(pid); + } + catch (...) + { + Syslog::error("SecTranslocate: error in SecTranslocateAppLaunchCheckin"); + } +} + +/* Create an app translocation point given the original path and an optional destination path. */ +CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTranslocate, + CFURLRef __nullable destinationPath, + CFErrorRef* __nullable error) +{ + CFURLRef result = NULL; + CFIndex errorCode = 0; + + try + { + string sourcePath = cfString(pathToTranslocate); // returns an absolute path + + Security::SecTranslocate::TranslocationPath toTranslocatePath(sourcePath); + + if(!toTranslocatePath.shouldTranslocate()) + { + /* We shouldn't translocate so, just retain so that the return value can be treated as a copy */ + CFRetain(pathToTranslocate); + return pathToTranslocate; + } + + /* We need to translocate so keep going */ + string destPath; + + if(destinationPath) + { + destPath = cfString(destinationPath); //returns an absolute path + } + + string out_path = Security::SecTranslocate::getTranslocator()->translocatePathForUser(toTranslocatePath, destPath); + + if(!out_path.empty()) + { + result = makeCFURL(out_path, true); + } + else + { + Syslog::error("SecTranslocateCreateSecureDirectoryForURL: No mountpoint and no prior exception. Shouldn't be here"); + UnixError::throwMe(EINVAL); + } + + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocate: uncaught exception during mountpoint creation"); + errorCode = EACCES; + } + + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + return result; +} + +/* Destroy the specified translocated path, and clean up the user's translocation directory. */ +Boolean SecTranslocateDeleteSecureDirectory(CFURLRef translocatedPath, CFErrorRef* __nullable error) +{ + bool result = false; + int errorCode = 0; + + if(translocatedPath == NULL) + { + errorCode = EINVAL; + goto end; + } + + try + { + string pathToDestroy = cfString(translocatedPath); + result = Security::SecTranslocate::getTranslocator()->destroyTranslocatedPathForUser(pathToDestroy); + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocate: uncaught exception during mountpoint deletion"); + errorCode = EACCES; + } +end: + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + + return result; +} + +/* Decide whether we need to translocate */ +Boolean SecTranslocateURLShouldRunTranslocated(CFURLRef path, bool* shouldTranslocate, CFErrorRef* __nullable error) +{ + bool result = false; + int errorCode = 0; + + if(path == NULL || shouldTranslocate == NULL) + { + errorCode = EINVAL; + goto end; + } + + try + { + string pathToCheck = cfString(path); + Security::SecTranslocate::TranslocationPath tPath(pathToCheck); + *shouldTranslocate = tPath.shouldTranslocate(); + result = true; + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocate: uncaught exception during policy check"); + errorCode = EACCES; + } + +end: + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + + return result; +} + +/* Answer whether or not the passed in URL is a nullfs URL. This just checks nullfs rather than + nullfs + in the user's translocation path to allow callers like LaunchServices to apply special + handling to nullfs mounts regardless of the calling user (i.e. root lsd can identify all translocated + mount points for all users). + */ +Boolean SecTranslocateIsTranslocatedURL(CFURLRef path, bool* isTranslocated, CFErrorRef* __nullable error) +{ + bool result = false; + int errorCode = 0; + + if(path == NULL || isTranslocated == NULL) + { + if(error) + { + *error = SecTranslocateMakePosixError(EINVAL); + } + return result; + } + + *isTranslocated = false; + + try + { + string cpp_path = cfString(path); + /* "/" i.e. the root volume, cannot be translocated (or mounted on by other file system after boot) + so don't bother to make system calls if "/" is what is being asked about. + This is an optimization to help LaunchServices which expects to use SecTranslocateIsTranslocatedURL + on every App Launch. + */ + if (cpp_path != "/") + { + /* to avoid AppSandbox violations, use a path based check here. + We only look for nullfs file type anyway. */ + struct statfs sfb; + if (statfs(cpp_path.c_str(), &sfb) == 0) + { + *isTranslocated = (strcmp(sfb.f_fstypename, NULLFS_FSTYPE) == 0); + result = true; + } + else + { + errorCode = errno; + Syslog::error("SecTranslocate: can not access %s, error: %s", cpp_path.c_str(), strerror(errorCode)); + } + } + else + { + result = true; + } + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocate: uncaught exception during policy check"); + errorCode = EACCES; + } + + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + + return result; +} + +/* Find the original path for translocation mounts belonging to the calling user. + if the url isn't on a nullfs volume then returned a retained copy of the passed in url. + if the url is on a nullfs volume but that volume doesn't belong to the user, or another + error occurs then null is returned */ +CFURLRef __nullable SecTranslocateCreateOriginalPathForURL(CFURLRef translocatedPath, CFErrorRef* __nullable error) +{ + CFURLRef result = NULL; + int errorCode = 0; + + if(translocatedPath == NULL) + { + errorCode = EINVAL; + goto end; + } + try + { + string path = cfString(translocatedPath); + Security::SecTranslocate::ExtendedAutoFileDesc fd(path); + + if(fd.isFileSystemType(NULLFS_FSTYPE)) + { + bool isDir = false; + string out_path = Security::SecTranslocate::getOriginalPath(fd, &isDir); + if(!out_path.empty()) + { + result = makeCFURL(out_path, isDir); + } + else + { + Syslog::error("SecTranslocateCreateOriginalPath: No original and no prior exception. Shouldn't be here"); + UnixError::throwMe(EINVAL); + } + } + else + { + result = translocatedPath; + CFRetain(result); + } + } + catch (Security::UnixError err) + { + errorCode = err.unixError(); + } + catch(...) + { + Syslog::critical("SecTranslocate: uncaught exception during policy check"); + errorCode = EACCES; + } +end: + if (error && errorCode) + { + *error = SecTranslocateMakePosixError(errorCode); + } + return result; +} diff --git a/OSX/libsecurity_translocate/lib/SecTranslocate.h b/OSX/libsecurity_translocate/lib/SecTranslocate.h new file mode 100644 index 00000000..ba5a8136 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocate.h @@ -0,0 +1,218 @@ +/* + * 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@ + */ + +#ifndef H_LIBSECURITY_TRANSLOCATE +#define H_LIBSECURITY_TRANSLOCATE + +#include + +CF_ASSUME_NONNULL_BEGIN + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @function SecTranslocateStartListening + + @abstract Initialize the SecTranslocate Library as the XPC Server, Disk Arbitration Listener, and Launch Services Notification listener + + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result True on success False on failure + */ +Boolean SecTranslocateStartListening(CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateStartListeningWithOptions + + @abstract Initialize the SecTranslocate Library as the XPC Server, Disk Arbitration Listener, and Launch Services Notification listener + + @param option (currently unused) A dictionary of options that could impact server startup + @param outError On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result True on success False on failure + */ +Boolean SecTranslocateStartListeningWithOptions(CFDictionaryRef options, CFErrorRef * __nullable outError) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateCreateSecureDirectoryForURL + + @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, or NULL for a random UUID location + @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 SecTranslocateDeleteSecureDirectory are serialized to ensure only one call to either + is operating at a time. + Translocations will be created in the calling users's DARWIN_USER_TEMPDIR/AppTranslocation/ + + pathToTranslocated is expected to be of the form /some/dir/myApp.app + destinationPath is expected to be of the form //AppTranslocation//d/myApp.app + + Resulting translocations are of the form //AppTranslocation//d/myApp.app + will be a UUID if destinationPath isn't specified. + + 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 + + destinationPath will cause a failure if + 1. it doesn't match the app (last directory) specified by path to translocate + 2. it differs from an already existing mount location for pathToTranslocate + 3. It isn't in the user's current temp dir + 4. someone created a file with the same name as the provided path + 5. It doesn't match the form //AppTranslocation//d/myApp.app + + pathToTranslocate is returned if it should not be translocated based on policy. It is retained if so it can be treated as a copy. + + This function can be run from any process. If the process is not the xpc server, then an xpc call is made. + */ +CFURLRef __nullable SecTranslocateCreateSecureDirectoryForURL (CFURLRef pathToTranslocate, CFURLRef __nullable destinationPath, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateAppLaunchCheckin + + @abstract Register that a translocated pid is running + + @param pid the pid to register + + @discussion this function will log if there is a problem. The actual work is either sent to the server via xpc, or dispatched async. + + This function can be run from any process. If the process is not the xpc server, then an xpc call is made. + */ +void SecTranslocateAppLaunchCheckin(pid_t pid) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateURLShouldRunTranslocated + + @abstract Implements policy to decide whether the entity defined by path should be run translocated + + @param path URL to the entity in question + + @param shouldTranslocate true if the path should be translocated, false otherwise + + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result true on success, false on failure (on failure error is set if provided). shouldTranslocate gives the answer + + @discussion The policy is as follows: + 1. If path is already on a nullfs mountpoint - no translocation + 2. No quarantine attributes - no translocation + 3. If QTN_FLAG_DO_NOT_TRANSLOCATE is set or QTN_FLAG_TRANSLOCATE is not set - no translocations + 4. Otherwise, if QTN_FLAG_TRANSLOCATE is set - translocation + + This function can be called from any process or thread. + */ +Boolean SecTranslocateURLShouldRunTranslocated(CFURLRef path, bool* shouldTranslocate, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateIsTranslocatedURL + + @abstract indicates whether the provided path is an original path or a translocated path + + @param path path to check + + @param isTranslocated true if the path is translocated, false otherwise + + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result true on success, false on failure (on failure error is set if provided). isTranslocated gives the answer + + @discussion will return + 1. false and EPERM if the caller doesn't have read access to the path + 2. false and ENOENT if the path doesn't exist + 3. false and ENINVAL if the parameters are broken + 4. true and isTranslocated = true if the path is on a nullfs mount + 5. true and isTranslocated = false if the path is not on a nullfs mount + + If path is a symlink, the results will reflect whatever the symlink actually points to. + + This function can be called from any process or thread. +*/ +Boolean SecTranslocateIsTranslocatedURL(CFURLRef path, bool* isTranslocated, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateCreateOriginalPathForURL + + @abstract finds the original path to a file given a translocated path + + @param translocatedPath the path to look up + + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL) + + @result A valid, existant path, or NULL on error + + @discussion will return + 1. NULL and EPERM if the caller doesn't have read access to the path + 2. NULL and ENOENT if the path doesn't exist + 3. NULL and ENINVAL if the parameters are broken + 4. A retained copy of translocatedPath if it isn't translocated + 5. The real path to original untranslocated file/directory. + + If translocatedPath is a symlink, the results will reflect whatever the symlink actually points to. + + This function can be called from any process or thread. +*/ +CFURLRef __nullable SecTranslocateCreateOriginalPathForURL(CFURLRef translocatedPath, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.12); + +/*! + @function SecTranslocateDeleteSecureDirectory + + @abstract Unmount the translocated directory structure and delete the mount point directory. + + @param translocatedPath a CFURL pointing to a translocated location. + + @param error On error will be populated with an error object describing the failure (a posix domain error such as EINVAL). + + @result true on success, false on error. + + @discussion This function will make sure that the translocatedPath belongs to the calling user before unmounting. + After an unmount, this function will iterate through all the directories in the user's AppTranslocation directory + and delete any that aren't currently mounted on. + This function can only be called from the XPC Server. An error will be returned if this is called from any other process. + + */ +Boolean SecTranslocateDeleteSecureDirectory(CFURLRef translocatedPath, CFErrorRef* __nullable error) +__OSX_AVAILABLE(10.12); + + +#ifdef __cplusplus +} +#endif + +CF_ASSUME_NONNULL_END + +#endif /* H_LIBSECURITY_TRANSLOCATE */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp new file mode 100644 index 00000000..670f6c18 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateClient.cpp @@ -0,0 +1,190 @@ +/* + * 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 + +#include +#include +#include + +#include +#include + +#include "SecTranslocateClient.hpp" +#include "SecTranslocateShared.hpp" +#include "SecTranslocateInterface.hpp" + +namespace Security { + +namespace SecTranslocate { + +using namespace std; + +TranslocatorClient::TranslocatorClient(dispatch_queue_t q):syncQ(q) +{ + if(syncQ == NULL) + { + Syslog::critical("SecTranslocate::TranslocatorClient initialized without a queue."); + UnixError::throwMe(EINVAL); + } + + uint64_t flags = 0; + uid_t euid = geteuid(); + + /* 0 - is root so it gets the root lsd + 1-300 = are treated by launch services as "role users" They share a copy of the LS Database with root + and thus must be sent to the root lsd. */ + if (euid <= 300) + { + flags |= XPC_CONNECTION_MACH_SERVICE_PRIVILEGED; //forces call to the root lsd + } + + service = xpc_connection_create_mach_service(SECTRANSLOCATE_XPC_SERVICE_NAME, + syncQ, + flags); + if (service == NULL) + { + Syslog::critical("SecTranslocate: TranslocatorClient, failed to create xpc mach service"); + UnixError::throwMe(ENOMEM); + } + xpc_connection_set_event_handler(service, ^(xpc_object_t event) { + xpc_type_t type = xpc_get_type(event); + if (type == XPC_TYPE_ERROR) + { + Syslog::error("SecTranslocate, client, xpc error: %s", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); + } + else + { + char* description = xpc_copy_description(event); + Syslog::error("SecTranslocate, client, xpc unexpected type: %s", description); + free(description); + } + }); + + dispatch_retain(syncQ); + xpc_connection_resume(service); +} + +TranslocatorClient::~TranslocatorClient() +{ + xpc_connection_cancel(service); + dispatch_release(syncQ); +} + +string TranslocatorClient::translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +{ + 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); + + if( msg == NULL) + { + Syslog::error("SecTranslocate: TranslocatorClient, failed to allocate message to send"); + UnixError::throwMe(ENOMEM); + } + + 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, kSecTranslocateXPCMessageDestinationPath, destPath.c_str()); + } + + xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, msg); + xpc_release(msg); + + if(reply == NULL) + { + Syslog::error("SecTranslocate, TranslocatorClient, create, no reply returned"); + UnixError::throwMe(ENOMEM); + } + + xpc_type_t type = xpc_get_type(reply); + if (type == XPC_TYPE_DICTIONARY) + { + if(int64_t error = xpc_dictionary_get_int64(reply, kSecTranslocateXPCReplyError)) + { + Syslog::error("SecTranslocate, TranslocatorClient, create, error received %lld", error); + xpc_release(reply); + UnixError::throwMe((int)error); + } + const char * result = xpc_dictionary_get_string(reply, kSecTranslocateXPCReplySecurePath); + if (result == NULL) + { + Syslog::error("SecTranslocate, TranslocatorClient, create, no result path received"); + xpc_release(reply); + UnixError::throwMe(EINVAL); + } + outPath=result; + xpc_release(reply); + } + else + { + const char* errorMsg = NULL; + if (type == XPC_TYPE_ERROR) + { + errorMsg = "SecTranslocate, TranslocatorClient, create, xpc error returned: %s"; + } + else + { + errorMsg = "SecTranslocate, TranslocatorClient, create, unexpected type of return object: %s"; + } + const char *s = xpc_copy_description(reply); + Syslog::error(errorMsg, s); + free((char*)s); + xpc_release(reply); + UnixError::throwMe(EINVAL); + } + + return outPath; +} + +void TranslocatorClient::appLaunchCheckin(pid_t pid) +{ + xpc_object_t msg = xpc_dictionary_create(NULL, NULL, 0); + + xpc_dictionary_set_string(msg, kSecTranslocateXPCMessageFunction, kSecTranslocateXPCFuncCheckIn); + xpc_dictionary_set_int64(msg, kSecTranslocateXPCMessagePid, pid); + + /* no reply expected so just send the message and move along */ + xpc_connection_send_message(service, msg); + + xpc_release(msg); +} + +bool TranslocatorClient::destroyTranslocatedPathForUser(const string &translocatedPath) +{ + Syslog::error("SecTranslocate, TranslocatorClient, delete operation not allowed"); + UnixError::throwMe(EPERM); + return false; +} + +} //namespace SecTranslocate +} //namespace Security diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp new file mode 100644 index 00000000..bff27ef0 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateClient.hpp @@ -0,0 +1,63 @@ +/* + * 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@ + */ + +/* Purpose: + This header defines the client side interface (xpc client for translocation) + */ + +#ifndef SecTranslocateClient_hpp +#define SecTranslocateClient_hpp + +#include +#include + +#include "SecTranslocateInterface.hpp" +#include "SecTranslocateShared.hpp" + +namespace Security { + +namespace SecTranslocate { + +using namespace std; + +class TranslocatorClient: public Translocator +{ +public: + TranslocatorClient(dispatch_queue_t q); + ~TranslocatorClient(); + + string translocatePathForUser(const TranslocationPath &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; + dispatch_queue_t syncQ; + xpc_connection_t service; +}; + +} //namespace SecTranslocate +} //namespace Security + +#endif /* SecTranslocateClient_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateDANotification.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateDANotification.cpp new file mode 100644 index 00000000..f8dfaa16 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateDANotification.cpp @@ -0,0 +1,221 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include + +#include "SecTranslocateDANotification.hpp" +#include "SecTranslocateShared.hpp" +#include "SectranslocateUtilities.hpp" + +#define DA_FRAMEWORK_PATH "/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration" + +namespace Security { +namespace SecTranslocate { + +typedef CFDictionaryRef (*DiskCopyDescription_t)(DADiskRef); +typedef DASessionRef (*SessionCreate_t) (CFAllocatorRef); +typedef void (*SessionSetDispatchQueue_t)(DASessionRef,dispatch_queue_t); +typedef void (*RegisterDiskDisappearedCallback_t) (DASessionRef, CFDictionaryRef, DADiskDisappearedCallback, void*); +typedef void (*RegisterDiskUnmountApprovalCallback_t) (DASessionRef, CFDictionaryRef, DADiskUnmountApprovalCallback, void*); +typedef void (*UnregisterCallback_t)(DASessionRef, void*, void*); + +class DiskArbitrationProxy +{ +public: + static DiskArbitrationProxy* get(); + + inline CFDictionaryRef diskCopyDescription(DADiskRef disk) const + { return pDiskCopyDescription ? pDiskCopyDescription(disk) : NULL; }; + inline DASessionRef sessionCreate (CFAllocatorRef allocator) const + { return pSessionCreate ? pSessionCreate(allocator) : NULL; }; + inline void sessionSetDispatchQueue (DASessionRef s, dispatch_queue_t q) const + { if(pSessionSetDispatchQueue) pSessionSetDispatchQueue(s,q); }; + inline void registerDiskDisappearedCallback (DASessionRef s, CFDictionaryRef d, DADiskDisappearedCallback c, void* x) const + { if(pRegisterDiskDisappearedCallback) pRegisterDiskDisappearedCallback(s,d,c,x); }; + inline void registerDiskUnmountApprovalCallback (DASessionRef s, CFDictionaryRef d, DADiskUnmountApprovalCallback c, void* x) const + { if(pRegisterDiskUnmountApprovalCallback) pRegisterDiskUnmountApprovalCallback(s,d,c,x); }; + inline void unregisterCallback (DASessionRef s, void* c, void* x) const + { if(pUnregisterCallback) pUnregisterCallback(s,c,x); }; + inline CFDictionaryRef diskDescriptionMatchVolumeMountable() const + { return pDiskDescriptionMatchVolumeMountable ? *pDiskDescriptionMatchVolumeMountable : NULL; }; + inline CFStringRef diskDescriptionVolumePathKey() const + { return pDiskDescriptionVolumePathKey ? *pDiskDescriptionVolumePathKey : NULL; }; + +private: + DiskArbitrationProxy(); + + void* handle; + DiskCopyDescription_t pDiskCopyDescription; + SessionCreate_t pSessionCreate; + SessionSetDispatchQueue_t pSessionSetDispatchQueue; + RegisterDiskDisappearedCallback_t pRegisterDiskDisappearedCallback; + RegisterDiskUnmountApprovalCallback_t pRegisterDiskUnmountApprovalCallback; + UnregisterCallback_t pUnregisterCallback; + CFDictionaryRef* pDiskDescriptionMatchVolumeMountable; + CFStringRef* pDiskDescriptionVolumePathKey; +}; + +DiskArbitrationProxy::DiskArbitrationProxy() +{ + handle = checkedDlopen(DA_FRAMEWORK_PATH, RTLD_LAZY | RTLD_NOLOAD); + + pDiskCopyDescription = (DiskCopyDescription_t) checkedDlsym(handle, "DADiskCopyDescription"); + pSessionCreate = (SessionCreate_t) checkedDlsym(handle, "DASessionCreate"); + + pSessionSetDispatchQueue = (SessionSetDispatchQueue_t) checkedDlsym(handle, "DASessionSetDispatchQueue"); + pRegisterDiskDisappearedCallback = (RegisterDiskDisappearedCallback_t) checkedDlsym(handle, "DARegisterDiskDisappearedCallback"); + pRegisterDiskUnmountApprovalCallback = (RegisterDiskUnmountApprovalCallback_t) checkedDlsym(handle, "DARegisterDiskUnmountApprovalCallback"); + pUnregisterCallback = (UnregisterCallback_t) checkedDlsym(handle, "DAUnregisterCallback"); + pDiskDescriptionMatchVolumeMountable = (CFDictionaryRef*) checkedDlsym(handle, "kDADiskDescriptionMatchVolumeMountable"); + pDiskDescriptionVolumePathKey = (CFStringRef*) checkedDlsym(handle, "kDADiskDescriptionVolumePathKey"); +} + +DiskArbitrationProxy* DiskArbitrationProxy::get() +{ + static dispatch_once_t initialized; + static DiskArbitrationProxy* me = NULL; + __block exception_ptr exception(0); + + dispatch_once(&initialized, ^{ + try + { + me = new DiskArbitrationProxy(); + } + catch (...) + { + Syslog::critical("SecTranslocate: error while creating DiskArbitrationProxy"); + exception = current_exception(); + } + }); + + if (me == NULL) + { + if(exception) + { + rethrow_exception(exception); //already logged in this case + } + else + { + Syslog::critical("SecTranslocate: DiskArbitrationProxy initialization has failed"); + UnixError::throwMe(EINVAL); + } + } + + return me; +} +/* + For Disk Arbitration need to + 1. create a session and hold on to it. + 2. associate it with a queue + 3. register for call backs (DADiskDisappearedCallback and DADiskUnmountApprovalCallback) + 4. provide a function to get the mounton path from DADiskref + 5. Return a dissenter if unmount is gonna fail because something is in use (i.e. if my unmount fails) + */ + +/* Returns false if we failed an unmount call. anything else returns true */ +static bool cleanupDisksOnVolume(DADiskRef disk) +{ + bool result = true; + string fspathString; + try + { + DiskArbitrationProxy *dap = DiskArbitrationProxy::get(); + CFRef dict = dap->diskCopyDescription(disk); + + if(!dict) + { + Syslog::error("SecTranslocate:disk cleanup, failed to get disk description"); + UnixError::throwMe(EINVAL); + } + + CFURLRef fspath = (CFURLRef)CFDictionaryGetValue(dict, dap->diskDescriptionVolumePathKey()); + + if(fspath) + { + //For the disk disappeared call back, it looks like we won't get a volume path so we'll keep the empty string + fspathString = cfString(fspath); + } + + result = destroyTranslocatedPathsForUserOnVolume(fspathString); + } + catch (...) + { + // This function is called from inside a DiskArbitration callback so we need to consume the exception + // more specific errors are assumed to be logged by the thrower + Syslog::error("SecTranslocate: DiskArbitration callback: failed to clean up mountpoint(s) related to volume: %s", + fspathString.empty() ? "unknown" : fspathString.c_str()); + } + + return result; +} + +static void diskDisappearedCallback(DADiskRef disk, void* context) +{ + (void)cleanupDisksOnVolume(disk); +} + +static DADissenterRef unmountApprovalCallback(DADiskRef disk, void *context) +{ + (void)cleanupDisksOnVolume(disk); + return NULL; //For now, we won't raise a dissent, just let the unmount fail. The dissent text would get used by UI. +} + +DANotificationMonitor::DANotificationMonitor(dispatch_queue_t q) +{ + DiskArbitrationProxy *dap = DiskArbitrationProxy::get(); + if (q == NULL) + { + Syslog::critical("SecTranslocate::DANotificationMonitor initialized without a queue."); + UnixError::throwMe(EINVAL); + } + + diskArbitrationSession = dap->sessionCreate(kCFAllocatorDefault); + if(!diskArbitrationSession) + { + Syslog::critical("SecTranslocate: Failed to create the disk arbitration session"); + UnixError::throwMe(ENOMEM); + } + + dap->sessionSetDispatchQueue(diskArbitrationSession, q); + /* register so we can cleanup from force unmounts */ + dap->registerDiskDisappearedCallback( diskArbitrationSession, dap->diskDescriptionMatchVolumeMountable(), diskDisappearedCallback, NULL ); + /* register so we can clean up pre-unmount */ + dap->registerDiskUnmountApprovalCallback( diskArbitrationSession, dap->diskDescriptionMatchVolumeMountable(), unmountApprovalCallback, NULL ); +} + +DANotificationMonitor::~DANotificationMonitor() +{ + DiskArbitrationProxy::get()->unregisterCallback(diskArbitrationSession,(void*)diskDisappearedCallback, NULL); + DiskArbitrationProxy::get()->unregisterCallback(diskArbitrationSession,(void*)unmountApprovalCallback, NULL); + CFRelease(diskArbitrationSession); +} + +} //namespace SecTranslocate +} //namespace Security diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateDANotification.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateDANotification.hpp new file mode 100644 index 00000000..8899e47a --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateDANotification.hpp @@ -0,0 +1,50 @@ +/* + * 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@ + */ + +/* Purpose: This header defines the Disk Arbitration monitor for translocation */ + +#ifndef SecTranslocateDANotification_hpp +#define SecTranslocateDANotification_hpp + +#include +#include + +namespace Security { +namespace SecTranslocate { + +class DANotificationMonitor { +public: + DANotificationMonitor(dispatch_queue_t q); //throws + ~DANotificationMonitor(); +private: + DANotificationMonitor() = delete; + DANotificationMonitor(const DANotificationMonitor& that) = delete; + + DASessionRef diskArbitrationSession; +}; + +} //namespace SecTranslocate +} //namespace Security + + +#endif /* SecTranslocateDANotification_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateInterface.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.cpp new file mode 100644 index 00000000..73a69c43 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.cpp @@ -0,0 +1,95 @@ +/* + * 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 +#include + +#include +#include + +#include "SecTranslocateInterface.hpp" +#include "SecTranslocateServer.hpp" +#include "SecTranslocateClient.hpp" + +namespace Security { +namespace SecTranslocate { + +using namespace std; + +Translocator* getTranslocator(bool isServer) +{ + static dispatch_once_t initialized; + static Translocator* me = NULL; + static dispatch_queue_t q; + __block exception_ptr exception(0); + + if(isServer && me) + { + Syslog::critical("SecTranslocate: getTranslocator, asked for server but previously intialized as client"); + UnixError::throwMe(EINVAL); + } + + dispatch_once(&initialized, ^{ + try + { + q = dispatch_queue_create(isServer?"com.apple.security.translocate":"com.apple.security.translocate-client", DISPATCH_QUEUE_SERIAL); + if(q == NULL) + { + Syslog::critical("SecTranslocate: getTranslocator, failed to create queue"); + UnixError::throwMe(ENOMEM); + } + + if(isServer) + { + me = new TranslocatorServer(q); + } + else + { + me = new TranslocatorClient(q); + } + } + catch (...) + { + Syslog::critical("SecTranslocate: error while creating Translocator"); + exception = current_exception(); + } + }); + + if (me == NULL) + { + if (exception) + { + rethrow_exception(exception); //we already logged in this case. + } + else + { + Syslog::critical("SecTranslocate: Translocator initialization failed"); + UnixError::throwMe(EINVAL); + } + } + + return me; +} + +} //namespace SecTranslocate +} //namespace Security diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp new file mode 100644 index 00000000..8ed15544 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateInterface.hpp @@ -0,0 +1,56 @@ +/* + * 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@ + */ + +/* Purpose: This header defines the generic Translocator interface, implemented by the client and server, + and the Translocator factory method to make a client or server object + */ + +#ifndef SecTranslocateInterface_h +#define SecTranslocateInterface_h + +#include +#include + +#include "SecTranslocateShared.hpp" + +namespace Security { +namespace SecTranslocate { + +using namespace std; + +#define SECTRANSLOCATE_XPC_SERVICE_NAME "com.apple.security.translocation" + +class Translocator +{ +public: + virtual ~Translocator() {}; + virtual string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) = 0; + virtual bool destroyTranslocatedPathForUser(const string &translocatedPath) = 0; + virtual void appLaunchCheckin(pid_t pid) = 0; +}; + +Translocator* getTranslocator(bool isServer=false); + +} //namespace SecTranslocate +} //namespace Security +#endif /* SecTranslocateInterface_h */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.cpp new file mode 100644 index 00000000..c4354e90 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.cpp @@ -0,0 +1,282 @@ +/* + * 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 +#include + +#include +#include +#include + +#include +#include +#include + +#include "SecTranslocate.h" +#include "SecTranslocateLSNotification.hpp" +#include "SecTranslocateUtilities.hpp" +#include "SecTranslocateShared.hpp" + +#define LS_FRAMEWORK_PATH "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices" + +namespace Security { +namespace SecTranslocate { + +/* Types for the LaunchServices symbols that I am Pseudo weak linking */ +typedef void (^LSNotificationHandler_t) (LSNotificationCode, CFAbsoluteTime, CFTypeRef, LSASNRef, LSSessionID, LSNotificationID); +typedef LSNotificationID (*ScheduleNotificationOnQueueWithBlock_t) (LSSessionID, CFTypeRef, dispatch_queue_t,LSNotificationHandler_t); +typedef OSStatus (*ModifyNotification_t)(LSNotificationID, UInt32, const LSNotificationCode *, UInt32, const LSNotificationCode *, CFTypeRef, CFTypeRef); +typedef OSStatus (*UnscheduleNotificationFunction_t)(LSNotificationID); +typedef LSASNRef (*ASNCreateWithPid_t)(CFAllocatorRef, int); +typedef uint64_t (*ASNToUInt64_t)(LSASNRef); +typedef Boolean (*IsApplicationRunning_t)(LSSessionID, LSASNRef); + +/* Class to contain all the Launch Services functions I need to weak link */ +class LaunchServicesProxy +{ +public: + static LaunchServicesProxy* get(); + + inline LSNotificationID scheduleNotificationOnQueueWithBlock (LSSessionID s, CFTypeRef r, dispatch_queue_t q,LSNotificationHandler_t b) const + { return pScheduleNotificationOnQueueWithBlock ? pScheduleNotificationOnQueueWithBlock(s,r,q,b) : (LSNotificationID)kLSNotificationInvalidID; }; + inline OSStatus modifyNotification(LSNotificationID i, UInt32 c, const LSNotificationCode * s, UInt32 l, const LSNotificationCode *n, CFTypeRef a, CFTypeRef r) const + { return pModifyNotification ? pModifyNotification(i,c,s,l,n,a,r) : kLSUnknownErr; }; + inline OSStatus unscheduleNotificationFunction(LSNotificationID i) const + { return pUnscheduleNotificationFunction ? pUnscheduleNotificationFunction(i) : kLSUnknownErr; }; + inline LSASNRef asnCreateWithPid(CFAllocatorRef a, int p) const + { return pASNCreateWithPid ? pASNCreateWithPid(a,p) : NULL; }; + inline uint64_t asnToUInt64 (LSASNRef a) const + { return pASNToUInt64 ? pASNToUInt64(a) : 0; }; + inline CFStringRef bundlePathKey() const { return pBundlePathKey ? *pBundlePathKey : NULL;}; + inline Boolean isApplicationRunning(LSSessionID i, LSASNRef a) const {return pIsApplicationRunning ? pIsApplicationRunning(i,a): false;}; + +private: + LaunchServicesProxy(); + + void* handle; + ScheduleNotificationOnQueueWithBlock_t pScheduleNotificationOnQueueWithBlock; + ModifyNotification_t pModifyNotification; + UnscheduleNotificationFunction_t pUnscheduleNotificationFunction; + ASNCreateWithPid_t pASNCreateWithPid; + ASNToUInt64_t pASNToUInt64; + CFStringRef *pBundlePathKey; + IsApplicationRunning_t pIsApplicationRunning; +}; + +/* resolve all the symbols. Throws if something isn't found. */ +LaunchServicesProxy::LaunchServicesProxy() +{ + handle = checkedDlopen(LS_FRAMEWORK_PATH, RTLD_LAZY | RTLD_NOLOAD); + + pScheduleNotificationOnQueueWithBlock = (ScheduleNotificationOnQueueWithBlock_t) checkedDlsym(handle, "_LSScheduleNotificationOnQueueWithBlock"); + pModifyNotification = (ModifyNotification_t) checkedDlsym(handle, "_LSModifyNotification"); + pUnscheduleNotificationFunction = (UnscheduleNotificationFunction_t) checkedDlsym(handle, "_LSUnscheduleNotificationFunction"); + pASNCreateWithPid = (ASNCreateWithPid_t) checkedDlsym(handle, "_LSASNCreateWithPid"); + pASNToUInt64 = (ASNToUInt64_t) checkedDlsym(handle, "_LSASNToUInt64"); + pBundlePathKey = (CFStringRef*) checkedDlsym(handle, "_kLSBundlePathKey"); + pIsApplicationRunning = (IsApplicationRunning_t) checkedDlsym(handle, "_LSIsApplicationRunning"); +} + +/* Singleton getter for the proxy */ +LaunchServicesProxy* LaunchServicesProxy::get() +{ + static dispatch_once_t initialized; + static LaunchServicesProxy* me = NULL; + __block exception_ptr exception(0); + + dispatch_once(&initialized, ^{ + try + { + me = new LaunchServicesProxy(); + } + catch (...) + { + Syslog::critical("SecTranslocate: error while creating LaunchServicesProxy"); + exception = current_exception(); + } + }); + + if (me == NULL) + { + if(exception) + { + rethrow_exception(exception); //already logged in this case + } + else + { + Syslog::critical("SecTranslocate: LaunchServicesProxy initialization has failed"); + UnixError::throwMe(EINVAL); + } + } + + return me; +} + +/* Save the notification queue so we can do things async later */ +LSNotificationMonitor::LSNotificationMonitor(dispatch_queue_t q): notificationQ(q) +{ + if (notificationQ == NULL) + { + Syslog::critical("SecTranslocate::LSNotificationMonitor initialized without a queue."); + UnixError::throwMe(EINVAL); + } + + dispatch_retain(notificationQ); +} + +/* Release the dispatch queue if this ever gets destroyed */ +LSNotificationMonitor::~LSNotificationMonitor() +{ + dispatch_release(notificationQ); +} + +/* Check to see if a path is translocated. If it isn't or no path is provided then return + an empty string. If it is, return the path as a c++ string. */ +string LSNotificationMonitor::stringIfTranslocated(CFStringRef appPath) +{ + if(appPath == NULL) + { + Syslog::error("SecTranslocate: no appPath provided"); + return ""; + } + + CFRef appURL = makeCFURL(appPath); + bool isTranslocated = false; + + string out = cfString(appURL); + + if (!SecTranslocateIsTranslocatedURL(appURL, &isTranslocated, NULL)) + { + Syslog::error("SecTranslocate: path for asn doesn't exist or isn't accessible: %s",out.c_str()); + return ""; + } + + if(!isTranslocated) + { + Syslog::error("SecTranslocate: asn is not translocated: %s",out.c_str()); + return ""; + } + + return out; +} + +/* register for a notification about the death of the requested PID with launch services if the pid is translocated */ +void LSNotificationMonitor::checkIn(pid_t pid) +{ + dispatch_async(notificationQ, ^(){ + try + { + LaunchServicesProxy* lsp = LaunchServicesProxy::get(); + + CFRef asn = lsp->asnCreateWithPid(kCFAllocatorDefault, pid); + + if(lsp->isApplicationRunning(kLSDefaultSessionID, asn)) + { + LSNotificationID nid = lsp->scheduleNotificationOnQueueWithBlock(kLSDefaultSessionID, + cfEmptyArray(), + notificationQ, + ^ (LSNotificationCode notification, + CFAbsoluteTime notificationTime, + CFTypeRef dataRef, + LSASNRef affectedASNRef, + LSSessionID session, + LSNotificationID notificationID){ + if( notification == kLSNotifyApplicationDeath && dataRef) + { + this->asnDied(dataRef); + } + + lsp->unscheduleNotificationFunction(notificationID); + }); + LSNotificationCode notificationCode = kLSNotifyApplicationDeath; + lsp->modifyNotification(nid, 1, ¬ificationCode, 0, NULL, asn, NULL); + } + else + { + Syslog::warning("SecTranslocate: pid %d checked in, but it is not running",pid); + } + } + catch(...) + { + Syslog::error("SecTranslocate: checkin failed for pid %d",pid); + } + }); +} + +/* use the supplied dictionary to perform volume cleanup. If the dictionary contains a bundle path + and that bundle path still exists and is translocated, then unmount it. Otherwise trigger a + unmount of any translocation point that doesn't point to an existant volume. */ +void LSNotificationMonitor::asnDied(CFTypeRef data) const +{ + string path; + try + { + CFDictionaryRef dict = NULL; + if(CFGetTypeID(data) == CFDictionaryGetTypeID()) + { + dict = (CFDictionaryRef)data; + } + else + { + Syslog::error("SecTranslocate: no data dictionary at app death"); + return; + } + + LaunchServicesProxy* lsp = LaunchServicesProxy::get(); + path = stringIfTranslocated((CFStringRef)CFDictionaryGetValue(dict,lsp->bundlePathKey())); + } + catch(...) + { + Syslog::error("SecTranslocate: asn death processing failed"); + return; + } + + /* wait 5 seconds after death */ + dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, 5LL * NSEC_PER_SEC); + + dispatch_after(when, notificationQ, ^() { + try + { + if(path.empty()) + { + /* we got an asn death notification but the path either wasn't translocated or didn't exist + in case it didn't exist try to clean up stale translocation points. + Calling this function with no parameter defaults to a blank volume which causes + only translocation points that point to non-existant volumes to be cleaned up. */ + destroyTranslocatedPathsForUserOnVolume(); + } + else + { + /* remove the translocation point for the app */ + destroyTranslocatedPathForUser(path); + } + } + catch(...) + { + Syslog::error("SecTranslocate: problem deleting translocation after app death: %s", path.c_str()); + } + }); +} + +} //namespace SecTranslocate +} //namespace Security diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.hpp new file mode 100644 index 00000000..c17a3b53 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateLSNotification.hpp @@ -0,0 +1,56 @@ +/* + * 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@ + */ + +/* Purpose: This header defines the Launch Services Notification Monitor for translocation */ + +#ifndef SecTranslocateLSNotification_hpp +#define SecTranslocateLSNotification_hpp + +#include +#include +#include +#include + +namespace Security { +namespace SecTranslocate { + +class LSNotificationMonitor { +public: + LSNotificationMonitor(dispatch_queue_t q); //throws + void checkIn(pid_t pid); + ~LSNotificationMonitor(); +private: + LSNotificationMonitor() = delete; + LSNotificationMonitor(const LSNotificationMonitor& that) = delete; + + void asnDied(CFTypeRef data) const; + static string stringIfTranslocated(CFStringRef appPath); + + dispatch_queue_t notificationQ; + +}; + +} //namespace SecTranslocate +} //namespace Security + +#endif /* SecTranslocateLSNotification_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp new file mode 100644 index 00000000..a515ba69 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateServer.cpp @@ -0,0 +1,167 @@ +/* + * 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 +#include +#include +#include + +#include "SecTranslocateShared.hpp" +#include "SecTranslocateServer.hpp" +#include "SecTranslocateUtilities.hpp" +#include "SecTranslocateDANotification.hpp" +#include "SecTranslocateXPCServer.hpp" +#include "SecTranslocateLSNotification.hpp" +#undef check //The CoreServices code pulls in a check macro that we don't want + +#include +#include + +namespace Security { + +using namespace Security::UnixPlusPlus; + +namespace SecTranslocate { + +using namespace std; + +/* Try to cleanup every 12 hrs */ +#define TRANSLOCATION_CLEANUP_INTERVAL 12ULL * 60ULL * 60ULL * NSEC_PER_SEC +#define TRANSLOCATION_CLEANUP_LEEWAY TRANSLOCATION_CLEANUP_INTERVAL/2ULL + +/* Initialize a dispatch queue to serialize operations */ +TranslocatorServer::TranslocatorServer(dispatch_queue_t q):syncQ(q), da(q), ls(q),xpc(q) +{ + if (!q) + { + Syslog::critical("SecTranslocate: TranslocatorServer failed to create the dispatch queue"); + UnixError::throwMe(ENOMEM); + } + dispatch_retain(syncQ); + + setupPeriodicCleanup(); + + Syslog::warning("SecTranslocate: Server started"); +} + +/* Destroy the dispatch queue and listeners when they are no longer needed */ +TranslocatorServer::~TranslocatorServer() +{ + if( syncQ ) + { + dispatch_release(syncQ); + } + + if(cleanupTimer) + { + dispatch_source_cancel(cleanupTimer); + cleanupTimer = NULL; + } +} + +// This is intended for use by the host process of the server if necessary +// Create a translocation for original path if appropriate +string TranslocatorServer::translocatePathForUser(const TranslocationPath &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) +{ + __block bool result = false; + __block exception_ptr exception(0); + dispatch_sync(syncQ, ^{ + try + { + result = Security::SecTranslocate::destroyTranslocatedPathForUser(translocatedPath); + } + catch (...) + { + exception = current_exception(); + } + }); + if (exception) + { + rethrow_exception(exception); + } + return result; +} + +void TranslocatorServer::appLaunchCheckin(pid_t pid) +{ + //This is thrown on the queue as an async task in the call so don't need to do anything extra. + ls.checkIn(pid); +} + +void TranslocatorServer::setupPeriodicCleanup() +{ + cleanupTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, syncQ); + + dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, TRANSLOCATION_CLEANUP_INTERVAL); + dispatch_source_set_timer(cleanupTimer, when, TRANSLOCATION_CLEANUP_INTERVAL, TRANSLOCATION_CLEANUP_LEEWAY); + + dispatch_source_set_cancel_handler(cleanupTimer, ^{ + dispatch_release(cleanupTimer); + }); + + dispatch_source_set_event_handler(cleanupTimer, ^{ + try + { + Syslog::notice("SecTranslocate: attempting to cleanup unused translocation points"); + tryToDestroyUnusedTranslocationMounts(); + } + catch (Security::UnixError err) + { + int error = err.unixError(); + Syslog::error("SecTranslocate: got unix error[ %d : %s ] while trying to cleanup translocation points.",error, strerror(error)); + } + catch (...) + { + Syslog::error("SecTranslocate: unknown error while trying to cleanup translocation points."); + } + }); + + dispatch_resume(cleanupTimer); +} + +} //namespace SecTranslocate +} //namespace SecTranslocate diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp new file mode 100644 index 00000000..b8cf62ec --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateServer.hpp @@ -0,0 +1,73 @@ +/* + * 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@ + */ + +/* Purpose: This header defines the Translocation "Server" it houses the XPC Listener, Disk Arbitration Monitor, + Launch Services Notification monitor, and interfaces for the process housing the server to request translocation + services. + */ + +#ifndef SecTranslocateServer_hpp +#define SecTranslocateServer_hpp + +#include +#include + +#include "SecTranslocateInterface.hpp" +#include "SecTranslocateUtilities.hpp" +#include "SecTranslocateLSNotification.hpp" +#include "SecTranslocateDANotification.hpp" +#include "SecTranslocateXPCServer.hpp" + + +namespace Security { + +namespace SecTranslocate { + +using namespace std; + +class TranslocatorServer: public Translocator +{ +public: + TranslocatorServer(dispatch_queue_t q); + ~TranslocatorServer(); + + string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) override; + bool destroyTranslocatedPathForUser(const string &translocatedPath) override; + void appLaunchCheckin(pid_t pid) override; + +private: + TranslocatorServer() = delete; + TranslocatorServer(const TranslocatorServer &that) = delete; + dispatch_queue_t syncQ; + DANotificationMonitor da; + LSNotificationMonitor ls; + XPCServer xpc; + dispatch_source_t cleanupTimer; + + void setupPeriodicCleanup(); +}; + +} //namespace SecTranslocate +} //namespace Security + +#endif /* SecTranslocateServer_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp new file mode 100644 index 00000000..f03c070e --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateShared.cpp @@ -0,0 +1,1023 @@ +/* + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define __APPLE_API_PRIVATE +#include +#undef __APPLE_API_PRIVATE + +#include +#include +#include +#include + +#include "SecTranslocateShared.hpp" +#include "SecTranslocateUtilities.hpp" + + +namespace Security { + +namespace SecTranslocate { + +using namespace std; + +/* String Constants for XPC dictionary passing */ +/* XPC Function keys */ +const char* kSecTranslocateXPCFuncCreate = "create"; +const char* kSecTranslocateXPCFuncCheckIn = "check-in"; + +/* XPC message argument keys */ +const char* kSecTranslocateXPCMessageFunction = "function"; +const char* kSecTranslocateXPCMessageOriginalPath = "original"; +const char* kSecTranslocateXPCMessageDestinationPath = "dest"; +const char* kSecTranslocateXPCMessagePid = "pid"; + +/*XPC message reply keys */ +const char* kSecTranslocateXPCReplyError = "error"; +const char* kSecTranslocateXPCReplySecurePath = "result"; + +//Functions used only within this file +static void setMountPointQuarantineIfNecessary(const string &mountPoint, const string &originalPath); +static string getMountpointFromAppPath(const string &appPath, const string &originalPath); + +static vector getMountTableSnapshot(); +static string mountExistsForUser(const string &translationDirForUser, const string &originalPath, const string &destMount); +static void validateMountpoint(const string &mountpoint, bool owned=false); +static string makeNewMountpoint(const string &translationDir); +static string newAppPath (const string &mountPoint, const TranslocationPath &originalPath); +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) +{ + + /* To support testing of translocation the policy is as follows: + 1. When the quarantine translocation sysctl is off, always translocate + if we aren't already on a translocated mount point. + 2. When the quarantine translocation sysctl is on, use the quarantine + bits to decide. + when asking if a path should run translocated need to: + check the current quarantine state of the path asked about + if it is already on a nullfs mount + do not translocate + else if it is unquarantined + do not translocate + else + if not QTN_FLAG_TRANSLOCATE or QTN_FLAG_DO_NOT_TRANSLOCATE + do not translocate + else + find the outermost acceptable code bundle + if not QTN_FLAG_TRANSLOCATE or QTN_FLAG_DO_NOT_TRANSLOCATE + don't translocate + else + translocate + + See findOuterMostCodeBundleForFD for more info about what an acceptable outermost bundle is + in particular it should be noted that the outermost acceptable bundle for a quarantined inner + bundle can not be unquarantined. If the inner bundle is quarantined then any bundle containing it + must also have been quarantined. + */ + + ExtendedAutoFileDesc fd(originalPath); + + should = false; + realOriginalPath = fd.getRealPath(); + + /* don't translocate if it already is */ + /* only consider translocation if the thing being asked about is marked for translocation */ + if(!fd.isFileSystemType(NULLFS_FSTYPE) && fd.isQuarantined() && fd.shouldTranslocate()) + { + ExtendedAutoFileDesc &&outermost = findOuterMostCodeBundleForFD(fd); + + should = outermost.isQuarantined() && outermost.shouldTranslocate(); + pathToTranslocate = outermost.getRealPath(); + + /* Calculate the path that will be needed to give the caller the path they asked for originally but in the translocated place */ + if (should) + { + vector originalComponents = splitPath(realOriginalPath); + vector toTranslocateComponents = splitPath(pathToTranslocate); + + if (toTranslocateComponents.size() == 0 || + toTranslocateComponents.size() > originalComponents.size()) + { + Syslog::error("SecTranslocate, TranslocationPath, path calculation failed:\n\toriginal: %s\n\tcalculated: %s", + realOriginalPath.c_str(), + pathToTranslocate.c_str()); + UnixError::throwMe(EINVAL); + } + + for(size_t cnt = 0; cnt < originalComponents.size(); cnt++) + { + if (cnt < toTranslocateComponents.size()) + { + if (toTranslocateComponents[cnt] != originalComponents[cnt]) + { + Syslog::error("SecTranslocate, TranslocationPath, translocation path calculation failed:\n\toriginal: %s\n\tcalculated: %s", + realOriginalPath.c_str(), + pathToTranslocate.c_str()); + UnixError::throwMe(EINVAL); + } + } + else + { + /* + want pathInsideTranslocationPoint to look like: + a/b/c + i.e. internal / but not at the front or back. + */ + if(pathInsideTranslocationPoint.empty()) + { + pathInsideTranslocationPoint = originalComponents[cnt]; + } + else + { + pathInsideTranslocationPoint += "/" + originalComponents[cnt]; + } + } + } + } + } +} + +/* if we should translocate and a stored path inside the translocation point exists, then add it to the + passed in string. If no path inside is stored, then return the passed in string if translocation + should occur, and the original path for the TranslocationPath if translocation shouldn't occur */ +string TranslocationPath::getTranslocatedPathToOriginalPath(const string &translocationPoint) const +{ + string seperator = translocationPoint.back() != '/' ? "/" : ""; + + if (should) + { + if(!pathInsideTranslocationPoint.empty()) + { + return translocationPoint + seperator + pathInsideTranslocationPoint; + } + else + { + return translocationPoint; + } + } + else + { + //If we weren't supposed to translocate return the original path. + return realOriginalPath; + } +} + +/* Given an fd for a path find the outermost acceptable code bundle and return an fd for that. + an acceptable outermost bundle is quarantined, user approved, and a code bundle. + If nothing is found outside the path to the fd provided, then passed in fd or a copy there of is returned.*/ +ExtendedAutoFileDesc TranslocationPath::findOuterMostCodeBundleForFD(ExtendedAutoFileDesc &fd) +{ + if( fd.isMountPoint() || !fd.isQuarantined()) + { + return fd; + } + vector path = splitPath(fd.getRealPath()); + size_t currentIndex = path.size() - 1; + size_t lastGoodIndex = currentIndex; + + string pathToCheck = joinPathUpTo(path, currentIndex); + /* + Proposed algorithm (pseudo-code): + lastGood := path := canonicalized path to be launched + + while path is not a mount point + if path is quarantined and not user-approved then exit loop # Gatekeeper has not cleared this code + if SecStaticCodeCreateWithPath(path) succeeds # used as an “is a code bundle” oracle + then lastGood := path + path := parent directory of path + return lastGood + */ + while(currentIndex) + { + ExtendedAutoFileDesc currFd(pathToCheck); + + if (currFd.isMountPoint() || !currFd.isQuarantined() || !currFd.isUserApproved()) + { + break; + } + + SecStaticCodeRef staticCodeRef = NULL; + + if( SecStaticCodeCreateWithPath(CFTempURL(currFd.getRealPath()), kSecCSDefaultFlags, &staticCodeRef) == errSecSuccess) + { + lastGoodIndex = currentIndex; + CFRelease(staticCodeRef); + } + + currentIndex--; + pathToCheck = joinPathUpTo(path, currentIndex); + } + + return ExtendedAutoFileDesc(joinPathUpTo(path, lastGoodIndex)); +} + +/* 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. */ +string getOriginalPath(const ExtendedAutoFileDesc& fd, bool* isDir) +{ + if (!fd.isFileSystemType(NULLFS_FSTYPE) || + isDir == NULL || + !fd.isInPrefixDir(fd.getMountPoint())) + { + Syslog::error("SecTranslocate::getOriginalPath called with invalid params: fs_type = %s, isDir = %p, realPath = %s, mountpoint = %s", + fd.getFsType().c_str(), + isDir, + fd.getRealPath().c_str(), + fd.getMountPoint().c_str()); + 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()); + vector mountPointPath = splitPath(fd.getMountPoint()); + vector translocatedRealPath = splitPath(fd.getRealPath()); + + if (mountPointPath.size() > translocatedRealPath.size()) + { + Syslog::warning("SecTranslocate: invalid translocated path %s", fd.getRealPath().c_str()); + UnixError::throwMe(EINVAL); + } + + string originalPath = fd.getMountFromPath(); + + int i; + + for( i = 0; i app = splitPath(appPath); // throws if empty or not absolute + vector original = splitPath(originalPath); //throws if empty or not absolute + + if (original.size() == 0) // had to have at least one directory, can't null mount / + { + Syslog::error("SecTranslocate: invalid original path: %s", originalPath.c_str()); + UnixError::throwMe(EINVAL); + } + + if (app.size() >= 3 && //the app path must have at least 3 directories, can't null mount onto / + app.back() == original.back()) //last directory of both match + { + app.pop_back(); + if(app.back() == "d") //last directory of app path is preceded by /d/ + { + app.pop_back(); + result = joinPath(app); + goto end; + } + } + + Syslog::error("SecTranslocate: invalid app path: %s", appPath.c_str()); + UnixError::throwMe(EINVAL); + +end: + return result; +} + +/* Read the mount table and return it in a vector */ +static vector getMountTableSnapshot() +{ + vector mntInfo; + int fs_cnt_first = 0; + int fs_cnt_second = 0; + int retry = 2; + + /*Strategy here is: + 1. check the current mount table size + 2. allocate double the required space + 3. actually read the mount table + 4. if the read actually filled up that double size try again once otherwise we are done + */ + + while(retry) + { + fs_cnt_first = getfsstat(NULL, 0 , MNT_WAIT); + if(fs_cnt_first <= 0) + { + Syslog::warning("SecTranslocate: error(%d) getting mount table info.", errno); + UnixError::throwMe(); + } + + if( fs_cnt_first == fs_cnt_second) + { + /* this path only applies on a retry. If our second attempt to get the size is + the same as what we already read then break. */ + break; + } + + mntInfo.resize(fs_cnt_first*2); + + fs_cnt_second = getfsstat(mntInfo.data(), (int)(mntInfo.size() * sizeof(struct statfs)), MNT_WAIT); + if (fs_cnt_second <= 0) + { + Syslog::warning("SecTranslocate: error(%d) getting mount table info.", errno); + UnixError::throwMe(); + } + + if( fs_cnt_second == mntInfo.size()) + { + retry--; + } + else + { + mntInfo.resize(fs_cnt_second); // trim the vector to what we actually need + break; + } + } + + if( retry == 0) + { + Syslog::warning("SecTranslocate: mount table is growing very quickly"); + } + + return mntInfo; +} + +/* 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 + exists for this the mountpoint found in the mount table is the same as the one requested */ +static string mountExistsForUser(const string &translationDirForUser, const string &originalPath, const string &destMountPoint) +{ + string result; // start empty + + if(!destMountPoint.empty()) + { + /* Validate that destMountPoint path is well formed and for this user + well formed means it is === translationDirForUser/<1 directory> + */ + vector splitDestMount = splitPath(destMountPoint); + + if(splitDestMount.size() < 2) //translationDirForUser is never / + { + Syslog::warning("SecTranslocate: invalid destination mount point: %s", + destMountPoint.c_str()); + UnixError::throwMe(EINVAL); + } + + splitDestMount.pop_back(); // knock off one directory + + string destBaseDir = joinPath(splitDestMount)+"/"; //translationDirForUser has a / at the end + + if (translationDirForUser != destBaseDir) + { + Syslog::warning("SecTranslocate: invalid destination mount point for user\n\tExpected: %s\n\tRequested: %s", + translationDirForUser.c_str(), + destBaseDir.c_str()); + /* requested destination isn't valid for the user */ + UnixError::throwMe(EINVAL); + } + } + + vector mntbuf = getMountTableSnapshot(); + + for (auto &i : mntbuf) + { + string mountOnName = i.f_mntonname; + size_t lastNonSlashPos = mountOnName.length() - 1; //start at the end of the string + + /* find the last position of the last non slash character */ + for(; lastNonSlashPos != 0 && mountOnName[lastNonSlashPos] == '/' ; lastNonSlashPos--); + + /* we want an exact match for originalPath and a prefix match for translationDirForUser + also make sure that this is a nullfs mount and that the mount point name is longer than the + translation directory with something other than / */ + + if (i.f_mntfromname == originalPath && //mount is for the requested path + strcmp(i.f_fstypename, NULLFS_FSTYPE) == 0 && // mount is a nullfs mount + lastNonSlashPos > translationDirForUser.length()-1 && // no shenanigans, there must be more directory here than just the translation dir + strncmp(i.f_mntonname, translationDirForUser.c_str(), translationDirForUser.length()) == 0) //mount is inside the translocation dir + { + if(!destMountPoint.empty()) + { + if (mountOnName != destMountPoint) + { + /* a mount exists for this path, but its not the one requested */ + Syslog::warning("SecTranslocate: requested destination doesn't match existing\n\tExpected: %s\n\tRequested: %s", + i.f_mntonname, + destMountPoint.c_str()); + UnixError::throwMe(EEXIST); + } + } + result = mountOnName; + break; + } + } + + return result; +} + +/* Given what we think is a valid mountpoint, perform a sanity check, and clean up if we are wrong */ +static void validateMountpoint(const string &mountpoint, bool owned) +{ + /* Requirements: + 1. can be opened + 2. is a directory + 3. is not already a mountpoint + 4. is an absolute path + */ + bool isDir = false; + bool isMount = false; + bool isEmpty = true; + + try { + /* first make sure this is a directory and that it is empty + (it could be dangerous to mount over a directory that contains something, + unfortunately this is still racy, and mount() is path based so we can't lock + down the directory until the mount succeeds (lock down is because of the entitlement + checks in nullfs))*/ + DIR* dir = opendir(mountpoint.c_str()); + int error = 0; + + if (dir == NULL) + { + error = errno; + Syslog::warning("SecTranslocate: mountpoint is not a directory or doesn't exist: %s", + mountpoint.c_str()); + UnixError::throwMe(error); + } + + isDir = true; + + struct dirent *d; + struct dirent dirbuf; + int cnt = 0; + int err = 0; + while(((err = readdir_r(dir, &dirbuf, &d)) == 0) && + d != NULL) + { + /* skip . and .. but break if there is more than that */ + if(++cnt > 2) + { + isEmpty = false; + break; + } + } + + error = errno; + (void)closedir(dir); + + if(err) + { + Syslog::warning("SecTranslocate: error while checking that mountpoint is empty"); + UnixError::throwMe(error); + } + + if(!isEmpty) + { + Syslog::warning("Sectranslocate: mountpoint is not empty: %s", + mountpoint.c_str()); + UnixError::throwMe(EBUSY); + } + + /* now check that the path is not a mountpoint */ + ExtendedAutoFileDesc fd(mountpoint); + + if(!fd.pathIsAbsolute()) + { + Syslog::warning("SecTranslocate: mountpoint isn't fully resolved\n\tExpected: %s\n\tActual: %s", + fd.getRealPath().c_str(), + mountpoint.c_str()); + UnixError::throwMe(EINVAL); + } + + isMount = fd.isMountPoint(); + + if(isMount) + { + Syslog::warning("SecTranslocate:Translocation failed, new mountpoint is already a mountpoint (%s)", + mountpoint.c_str()); + UnixError::throwMe(EINVAL); + } + } + catch(...) + { + if(owned) + { + if (!isMount) + { + if (isDir) + { + if(isEmpty) + { + rmdir(mountpoint.c_str()); + } + /* Already logged the else case above */ + } + else + { + Syslog::warning("SecTranslocate: unexpected file detected at mountpoint location (%s). Deleting.", + mountpoint.c_str()); + unlink(mountpoint.c_str()); + } + } + } + rethrow_exception(current_exception()); + } +} + +/* Create and validate the directory that we should mount at but don't create the mount yet */ +static string makeNewMountpoint(const string &translationDir) +{ + AutoFileDesc fd(getFDForDirectory(translationDir)); + + string uuid = makeUUID(); + + UnixError::check(mkdirat(fd, uuid.c_str(), 0500)); + + string mountpoint = translationDir+uuid; + + validateMountpoint(mountpoint); + + return mountpoint; +} + +/* If the original path has mountpoint quarantine info, apply it to the new mountpoint*/ +static void setMountPointQuarantineIfNecessary(const string &mountPoint, const string &originalPath) +{ + struct statfs sfsbuf; + int error = 0; + + UnixError::check(statfs(originalPath.c_str(), &sfsbuf)); + qtn_file_t original_attr = qtn_file_alloc(); + + if (original_attr != NULL) + { + if (qtn_file_init_with_mount_point(original_attr, sfsbuf.f_mntonname) == 0) + { + error = qtn_file_apply_to_mount_point(original_attr, mountPoint.c_str()); + } + qtn_file_free(original_attr); + } + else + { + error = errno; + } + + if (error) + { + Syslog::warning("SecTranslocate: Failed to apply quarantine information\n\tMountpoint: %s\n\tOriginal Path: %s", + mountPoint.c_str(), + originalPath.c_str()); + UnixError::throwMe(error); + } +} + +/* 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) +{ + vector original = splitPath(originalPath.getPathToTranslocate()); + + if (original.size() == 0) + { + Syslog::error("SecTranslocate: Invalid originalPath: %s", originalPath.getPathToTranslocate().c_str()); + UnixError::throwMe(EINVAL); + } + + string midPath = mountPoint+"/d"; + string outPath = originalPath.getTranslocatedPathToOriginalPath(midPath+"/"+original.back()); + + /* ExtendedAutoFileDesc will throw if one of these doesn't exist or isn't accessible */ + ExtendedAutoFileDesc mountFd(mountPoint); + ExtendedAutoFileDesc midFd(midPath); + ExtendedAutoFileDesc outFd(outPath); + + if(!outFd.isFileSystemType(NULLFS_FSTYPE) || + !mountFd.isFileSystemType(NULLFS_FSTYPE) || + !midFd.isFileSystemType(NULLFS_FSTYPE)) + { + Syslog::warning("SecTranslocate::App exists at expected translocation path (%s) but isn't a nullfs mount (%s)", + outPath.c_str(), + outFd.getFsType().c_str()); + UnixError::throwMe(EINVAL); + } + + if(!outFd.pathIsAbsolute() || + !mountFd.pathIsAbsolute() || + !midFd.pathIsAbsolute() ) + { + Syslog::warning("SecTranslocate::App path isn't resolved\n\tGot: %s\n\tExpected: %s", + outFd.getRealPath().c_str(), + outPath.c_str()); + UnixError::throwMe(EINVAL); + } + + fsid_t outFsid = outFd.getFsid(); + fsid_t midFsid = midFd.getFsid(); + fsid_t mountFsid = mountFd.getFsid(); + + /* different fsids mean that there is more than one volume between the expected mountpoint and the expected app path */ + if (memcmp(&outFsid, &midFsid, sizeof(fsid_t)) != 0 || + memcmp(&outFsid, &mountFsid, sizeof(fsid_t)) != 0) + { + Syslog::warning("SecTranslocate:: the fsid is not consistent between app, /d/ and mountpoint"); + UnixError::throwMe(EINVAL); + } + + return outFd.getRealPath(); +} + +/* 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. */ +string translocatePathForUser(const TranslocationPath &originalPath, const string &destPath) +{ + string newPath; + exception_ptr exception(0); + + string mountpoint; + bool owned = false; + try + { + const string &toTranslocate = originalPath.getPathToTranslocate(); + string baseDirForUser = translocationDirForUser(); //throws + string destMountPoint; + if(!destPath.empty()) + { + destMountPoint = getMountpointFromAppPath(destPath, toTranslocate); //throws or returns a mountpoint + } + + mountpoint = mountExistsForUser(baseDirForUser, toTranslocate, destMountPoint); //throws, detects invalid destMountPoint string + + if (!mountpoint.empty()) + { + /* A mount point exists already so bail*/ + newPath = newAppPath(mountpoint, originalPath); + return newPath; /* exit the block */ + } + if (destMountPoint.empty()) + { + mountpoint = makeNewMountpoint(baseDirForUser); //throws + owned = true; + } + else + { + AutoFileDesc fd(getFDForDirectory(destMountPoint, &owned)); //throws, makes the directory if it doesn't exist + + validateMountpoint(destMountPoint, owned); //throws + mountpoint = destMountPoint; + } + + UnixError::check(mount(NULLFS_FSTYPE, mountpoint.c_str(), MNT_RDONLY, (void*)toTranslocate.c_str())); + + setMountPointQuarantineIfNecessary(mountpoint, toTranslocate); //throws + + newPath = newAppPath(mountpoint, originalPath); //throws + + if (!destPath.empty()) + { + if (newPath != originalPath.getTranslocatedPathToOriginalPath(destPath)) + { + Syslog::warning("SecTranslocate: created app translocation point did not equal requested app translocation point\n\texpected: %s\n\tcreated: %s", + newPath.c_str(), + destPath.c_str()); + /* the app at originalPath didn't match the one at destPath */ + UnixError::throwMe(EINVAL); + } + } + // log that we created a new mountpoint (we don't log when we are re-using) + Syslog::warning("SecTranslocateCreateSecureDirectoryForURL: 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) +{ + DIR* translocationDir = opendir(userDir.c_str()); + + if( translocationDir ) + { + struct dirent de; + struct statfs sfbuf; + struct dirent * result = NULL; + + while (readdir_r(translocationDir, &de, &result) == 0 && result) + { + if(result->d_type == DT_DIR) + { + if (result->d_name[0] == '.') + { + if(result->d_namlen == 1 || + (result->d_namlen == 2 && + result->d_name[1] == '.')) + { + /* skip . and .. */ + continue; + } + } + string nextDir = userDir+string(result->d_name); + if (0 == statfs(nextDir.c_str(), &sfbuf) && + nextDir == sfbuf.f_mntonname) + { + /* its a mount point so continue */ + continue; + } + + /* not a mountpoint so delete it */ + if(unlinkat(dirfd(translocationDir), result->d_name, AT_REMOVEDIR)) + { + Syslog::warning("SecTranslocate: failed to delete directory during cleanup (error %d)\n\tUser Dir: %s\n\tDir to delete: %s", + errno, + userDir.c_str(), + result->d_name); + } + } + } + closedir(translocationDir); + } +} + +/* Unmount and delete a directory */ +static int removeMountPoint(const string &mountpoint, bool force) +{ + int error = 0; + + if (0 == unmount(mountpoint.c_str(), force ? MNT_FORCE : 0) && + 0 == rmdir(mountpoint.c_str())) + { + Syslog::warning("SecTranslocate: removed mountpoint: %s", + mountpoint.c_str()); + } + else + { + error = errno; + Syslog::warning("SecTranslocate: failed to unmount/remove mount point (errno: %d): %s", + error, mountpoint.c_str()); + } + + return error; +} + +/* Destroy the specified translocated path, and clean up the user's translocation directory. + It is the caller's responsibility to synchronize the operation on the dispatch queue. */ +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. + */ + + string baseDirForUser = translocationDirForUser(); // throws + bool shouldUnmount = false; + string translocatedMountpoint; + + { //Use a block to get rid of the file descriptor before we try to unmount. + ExtendedAutoFileDesc fd(translocatedPath); + translocatedMountpoint = fd.getMountPoint(); + /* + 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); + } + + if (shouldUnmount) + { + error = removeMountPoint(translocatedMountpoint); + result = error == 0; + } + + if (!result && !error) + { + Syslog::warning("SecTranslocate: mountpoint does not belong to user(%d): %s", + getuid(), + translocatedPath.c_str()); + error = EPERM; + } + + cleanupTranslocationDirForUser(baseDirForUser); + + if (error) + { + UnixError::throwMe(error); + } + + return result; +} + +/* Cleanup any translocation directories for this user that are either mounted from the + specified volume or from a volume that doesn't exist anymore. If an empty volumePath + is provided this has the effect of only cleaning up translocation points that point + to volumes that don't exist anymore. + + It is the caller's responsibility to synchronize the operation on the dispatch queue. + */ +bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath) +{ + bool cleanupError = false; + string baseDirForUser = translocationDirForUser(); + vector mountTable = getMountTableSnapshot(); + fsid_t unmountingFsid; + + /* passing in an empty volume here will fail to open */ + ExtendedAutoFileDesc volume(volumePath, O_RDONLY, FileDesc::modeMissingOk); + + if(volume.isOpen()) + { + unmountingFsid = volume.getFsid(); + } + + for (auto &mnt : mountTable) + { + /* + we need to look at each translocation mount and check + 1. is it ours + 2. does its mntfromname still exist, if it doesn't unmount it + 3. if it does, is it the same as the volume we are cleaning up?, if so unmount it. + */ + if (strcmp(mnt.f_fstypename, NULLFS_FSTYPE) == 0 && + strncmp(mnt.f_mntonname, baseDirForUser.c_str(), baseDirForUser.length()) == 0) + { + ExtendedAutoFileDesc volumeToCheck(mnt.f_mntfromname, O_RDONLY, FileDesc::modeMissingOk); + + if (!volumeToCheck.isOpen()) + { + // In this case we are trying to unmount a translocation point that points to nothing. Force it. + // Not forcing it currently hangs in UBC cleanup. + (void)removeMountPoint(mnt.f_mntonname , true); + } + else if (volume.isOpen()) + { + fsid_t toCheckFsid = volumeToCheck.getFsid(); + if( memcmp(&unmountingFsid, &toCheckFsid, sizeof(fsid_t)) == 0) + { + if(removeMountPoint(mnt.f_mntonname) != 0) + { + cleanupError = true; + } + } + } + } + } + + return !cleanupError; +} +/* This is intended to be used periodically to clean up translocation points that aren't used anymore */ +void tryToDestroyUnusedTranslocationMounts() +{ + vector mountTable = getMountTableSnapshot(); + string baseDirForUser = translocationDirForUser(); + + for (auto &mnt : mountTable) + { + if (strcmp(mnt.f_fstypename, NULLFS_FSTYPE) == 0 && + strncmp(mnt.f_mntonname, baseDirForUser.c_str(), baseDirForUser.length()) == 0) + { + ExtendedAutoFileDesc volumeToCheck(mnt.f_mntfromname, O_RDONLY, FileDesc::modeMissingOk); + + // Try to destroy the mount point. If the mirroed volume (volumeToCheck) isn't open then force it. + // Not forcing it currently hangs in UBC cleanup. + (void)removeMountPoint(mnt.f_mntonname , !volumeToCheck.isOpen()); + } + } +} + +} //namespace SecTranslocate +}// namespace Security diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp new file mode 100644 index 00000000..0940b3a1 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateShared.hpp @@ -0,0 +1,89 @@ +/* + * 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@ + */ + +/* Purpose: This header exposes shared functions that actually implement mount creation, policy question + answering and mount deletion. + + Important: None of these functions implement synchronization and they all throw exceptions. It is up + to the caller to handle those concerns. + */ + +#include +#include "SecTranslocateUtilities.hpp" + +#ifndef SecTranslocateShared_hpp +#define SecTranslocateShared_hpp + +namespace Security { + +namespace SecTranslocate { + +using namespace std; + +/* XPC Function keys */ +extern const char* kSecTranslocateXPCFuncCreate; +extern const char* kSecTranslocateXPCFuncCheckIn; + +/* XPC message argument keys */ +extern const char* kSecTranslocateXPCMessageFunction; +extern const char* kSecTranslocateXPCMessageOriginalPath; +extern const char* kSecTranslocateXPCMessageDestinationPath; +extern const char* kSecTranslocateXPCMessagePid; + +/*XPC message reply keys */ +extern const char* kSecTranslocateXPCReplyError; +extern const char* kSecTranslocateXPCReplySecurePath; + +class TranslocationPath +{ +public: + TranslocationPath(string originalPath); + 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; } ; + string getTranslocatedPathToOriginalPath(const string &translocationPoint) const; +private: + TranslocationPath() = delete; + + bool should; + string realOriginalPath; + string pathToTranslocate; + string pathInsideTranslocationPoint; + + ExtendedAutoFileDesc findOuterMostCodeBundleForFD(ExtendedAutoFileDesc &fd); +}; + +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 +bool destroyTranslocatedPathForUser(const string &translocatedPath); //throws +bool destroyTranslocatedPathsForUserOnVolume(const string &volumePath = ""); //throws +void tryToDestroyUnusedTranslocationMounts(); + +} //namespace SecTranslocate +}// namespace Security + +#endif /* SecTranslocateShared_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp new file mode 100644 index 00000000..103dd357 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.cpp @@ -0,0 +1,330 @@ +/* + * 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 +#include + +#include +#include +#include +#include + +#define __APPLE_API_PRIVATE +#include +#undef __APPLE_API_PRIVATE + +#include +#include +#include + +#include "SecTranslocateUtilities.hpp" + +#define APP_TRANSLOCATION_DIR "/AppTranslocation/" + +namespace Security { + +using namespace Security::UnixPlusPlus; + +namespace SecTranslocate { + +using namespace std; + +/* store the real path and fstatfs for the file descriptor. This throws if either fail */ +void ExtendedAutoFileDesc::init() +{ + char absPath[MAXPATHLEN]; + if(isOpen()) + { + UnixError::check(fstatfs(fd(), &fsInfo)); + fcntl(F_GETPATH, absPath); + realPath = absPath; + quarantined = false; + qtn_flags = 0; + quarantineFetched = false; //only fetch quarantine info when we need it + } +} + +bool ExtendedAutoFileDesc::isFileSystemType(const string &fsType) const +{ + notOpen(); //Throws if not Open + + return fsType == fsInfo.f_fstypename; +} + +bool ExtendedAutoFileDesc::pathIsAbsolute() const +{ + notOpen(); //Throws if not Open + + return originalPath == realPath; +} + +bool ExtendedAutoFileDesc::isMountPoint() const +{ + notOpen(); //Throws if not Open + return realPath == fsInfo.f_mntonname; +} +bool ExtendedAutoFileDesc::isInPrefixDir(const string &prefixDir) const +{ + notOpen(); //Throws if not Open + + return strncmp(realPath.c_str(), prefixDir.c_str(), prefixDir.length()) == 0; +} + +string ExtendedAutoFileDesc::getFsType() const +{ + notOpen(); //Throws if not Open + + return fsInfo.f_fstypename; +} + +string ExtendedAutoFileDesc::getMountPoint() const +{ + notOpen(); //Throws if not Open + + return fsInfo.f_mntonname; +} + +string ExtendedAutoFileDesc::getMountFromPath() const +{ + notOpen(); //Throws if not Open + + return fsInfo.f_mntfromname; +} + +const string& ExtendedAutoFileDesc::getRealPath() const +{ + notOpen(); //Throws if not Open + + return realPath; +} + +fsid_t const ExtendedAutoFileDesc::getFsid() const +{ + notOpen(); //Throws if not Open + + return fsInfo.f_fsid; +} + +void ExtendedAutoFileDesc::fetchQuarantine() +{ + if(!quarantineFetched) + { + notOpen(); + + qtn_file_t qf = qtn_file_alloc(); + + if(qf) + { + if(0 == qtn_file_init_with_fd(qf, fd())) + { + quarantined = true; + qtn_flags = qtn_file_get_flags(qf); + } + qtn_file_free(qf); + quarantineFetched = true; + } + else + { + Syslog::error("SecTranslocate: failed to allocate memory for quarantine struct"); + UnixError::throwMe(); + } + } +} + +bool ExtendedAutoFileDesc::isQuarantined() +{ + notOpen(); + fetchQuarantine(); + + return quarantined; +} + +bool ExtendedAutoFileDesc::isUserApproved() +{ + notOpen(); + fetchQuarantine(); + + return ((qtn_flags & QTN_FLAG_USER_APPROVED) == QTN_FLAG_USER_APPROVED); +} + +bool ExtendedAutoFileDesc::shouldTranslocate() +{ + notOpen(); + fetchQuarantine(); + + return ((qtn_flags & (QTN_FLAG_TRANSLOCATE | QTN_FLAG_DO_NOT_TRANSLOCATE)) == QTN_FLAG_TRANSLOCATE); +} + +/* Take an absolute path and split it into a vector of path components */ +vector splitPath(const string &path) +{ + vector out; + size_t start = 0; + size_t end = 0; + size_t len = 0; + + if(path.empty() || path.front() != '/') + { + Syslog::error("SecTranslocate::splitPath: asked to split a non-absolute or empty path: %s",path.c_str()); + UnixError::throwMe(EINVAL); + } + + while(end != string::npos) + { + end = path.find('/', start); + len = (end == string::npos) ? end : (end - start); + string temp = path.substr(start,len); + + if(!temp.empty()) + { + out.push_back(temp); + } + start = end + 1; + } + + return out; +} + +/* Take a vector of path components and turn it into an absolute path */ +string joinPath(vector& path) +{ + string out = ""; + for(auto &i : path) + { + out += "/"+i; + } + return out; +} + +string joinPathUpTo(vector &path, size_t index) +{ + if (path.size() == 0 || index > path.size()-1) + { + Syslog::error("SecTranslocate::joinPathUpTo invalid index %lu (size %lu)",index, path.size()-1); + UnixError::throwMe(EINVAL); + } + + string out = ""; + for (size_t i = 0; i <= index; i++) + { + out += "/" + path[i]; + } + + return out; +} + +/* Fully resolve the path provided */ +string getRealPath(const string &path) +{ + char absPath[MAXPATHLEN]; + AutoFileDesc fd(path); + fd.fcntl(F_GETPATH, absPath); + return absPath; +} + +/* Create a UUID string */ +string makeUUID() +{ + CFRef newUUID = CFUUIDCreate(NULL); + if (!newUUID) + { + UnixError::throwMe(ENOMEM); + } + + CFRef str = CFUUIDCreateString(NULL, newUUID.get()); + if (!str) + { + UnixError::throwMe(ENOMEM); + } + + return cfString(str); +} + +void* checkedDlopen(const char* path, int mode) +{ + void* handle = dlopen(path, mode); + + if(handle == NULL) + { + Syslog::critical("SecTranslocate: failed to load library %s: %s", path, dlerror()); + UnixError::throwMe(); + } + + return handle; +} + +void* checkedDlsym(void* handle, const char* symbol) +{ + void* result = dlsym(handle, symbol); + + if(result == NULL) + { + Syslog::critical("SecTranslocate: failed to load symbol %s: %s", symbol, dlerror()); + UnixError::throwMe(); + } + return result; +} + +/* Calculate the app translocation directory for the user inside the user's temp directory */ +string translocationDirForUser() +{ + char userTempPath[MAXPATHLEN]; + + if(confstr(_CS_DARWIN_USER_TEMP_DIR, userTempPath, sizeof(userTempPath)) == 0) + { + Syslog::error("SecTranslocate: Failed to get temp dir for user %d (error:%d)", + getuid(), + errno); + UnixError::throwMe(); + } + + // confstr returns a path with a symlink, we want the resolved path */ + return getRealPath(userTempPath)+APP_TRANSLOCATION_DIR; +} + +/* Get a file descriptor for the provided path. if the last component of the provided path doesn't + exist, create it and then re-attempt to get the file descriptor. + */ +int getFDForDirectory(const string &directoryPath, bool *owned) +{ + FileDesc fd(directoryPath, O_RDONLY, FileDesc::modeMissingOk); + if(!fd) + { + UnixError::check(mkdir(directoryPath.c_str(),0755)); + fd.open(directoryPath); + /* owned means that the library created the directory rather than it being pre-existent. + We just made a directory that didn't exist before, so set owned to true. */ + if(owned) + { + *owned = true; + } + } + else if (owned) + { + *owned = false; + } + + return fd; +} +} +} diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp new file mode 100644 index 00000000..e2503e2d --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateUtilities.hpp @@ -0,0 +1,108 @@ +/* + * 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@ + */ + +/* Purpose: + This header and its corresponding implementation are intended to house functionality that's useful + throughtout SecTranslocate but isn't directly tied to the SPI or things that must be serialized. + */ + +#ifndef SecTranslocateUtilities_hpp +#define SecTranslocateUtilities_hpp + +#include +#include +#include +#include + +#include +#include + +#define NULLFS_FSTYPE "nullfs" + +namespace Security { + +using namespace Security::UnixPlusPlus; + +namespace SecTranslocate { + +using namespace std; + +class ExtendedAutoFileDesc : public AutoFileDesc { +public: + ExtendedAutoFileDesc() = delete; //Always want these initialized with a path + + ExtendedAutoFileDesc(const char *path, int flag = O_RDONLY, mode_t mode = 0666) + : AutoFileDesc(path, flag, mode), originalPath(path) { init(); } + ExtendedAutoFileDesc(const std::string &path, int flag = O_RDONLY, mode_t mode = 0666) + : AutoFileDesc(path, flag, mode),originalPath(path) { init(); } + + bool isFileSystemType(const string &fsType) const; + bool pathIsAbsolute() const; + bool isMountPoint() const; + bool isInPrefixDir(const string &prefixDir) const; + string getFsType() const; + string getMountPoint() const; + string getMountFromPath() const; + const string& getRealPath() const; + fsid_t const getFsid() const; + bool isQuarantined(); + bool isUserApproved(); + bool shouldTranslocate(); + + // implicit destructor should call AutoFileDesc destructor. Nothing else to clean up. +private: + void init(); + inline void notOpen() const { if(!isOpen()) UnixError::throwMe(EINVAL); }; + + struct statfs fsInfo; + string realPath; + string originalPath; + bool quarantineFetched; + bool quarantined; + uint32_t qtn_flags; + void fetchQuarantine(); +}; + +//General utilities +string makeUUID(); +void* checkedDlopen(const char* path, int mode); +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); + +//File system utlities +string getRealPath(const string &path); +int getFDForDirectory(const string &directoryPath, bool *owned = NULL); //creates the directory if it can + + +//Translocation specific utilities +string translocationDirForUser(); + +} // namespace SecTranslocate +} // namespace Security + + +#endif /* SecTranslocateUtilities_hpp */ diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp new file mode 100644 index 00000000..769f72ac --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.cpp @@ -0,0 +1,155 @@ +/* + * 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 +#include + +#include +#include + +#include +#include + +#include "SecTranslocateInterface.hpp" +#include "SecTranslocateXPCServer.hpp" +#include "SecTranslocateUtilities.hpp" +#include "SecTranslocateShared.hpp" + +namespace Security { +namespace SecTranslocate { + +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); + + string originalPath = original ? original : ""; + string destPath = dest ? dest: ""; + + if( originalPath.empty()) + { + Syslog::error("SecTranslocate: XPCServer, doCreate no path to translocate"); + UnixError::throwMe(EINVAL); + } + + TranslocationPath tPath(originalPath); + + string result = tPath.getOriginalRealPath(); + + if(tPath.shouldTranslocate()) + { + result = Security::SecTranslocate::translocatePathForUser(tPath, destPath); + } + xpc_dictionary_set_string(reply, kSecTranslocateXPCReplySecurePath, result.c_str()); +} + +static void doCheckIn(xpc_object_t msg) +{ + if (xpc_dictionary_get_value(msg, kSecTranslocateXPCMessagePid) == NULL) + { + Syslog::error("SecTranslocate, XpcServer, doCheckin, no pid provided"); + UnixError::throwMe(EINVAL); + } + int64_t pid = xpc_dictionary_get_int64(msg, kSecTranslocateXPCMessagePid); + Translocator * t = getTranslocator(); + if(t) + { + t->appLaunchCheckin((pid_t)pid); + } + else + { + Syslog::critical("SecTranslocate, XpcServer, doCheckin, No top level translocator"); + UnixError::throwMe(EINVAL); + } +} + +XPCServer::XPCServer(dispatch_queue_t q):notificationQ(q) +{ + if(q == NULL) + { + Syslog::critical("SecTranslocate: XPCServer, no dispatch queue provided"); + UnixError::throwMe(EINVAL); + } + //notificationQ is assumed to be serial + service = xpc_connection_create_mach_service(SECTRANSLOCATE_XPC_SERVICE_NAME, + notificationQ, + XPC_CONNECTION_MACH_SERVICE_LISTENER); + if (service == NULL) + { + Syslog::critical("SecTranslocate: XPCServer, failed to create xpc mach service"); + UnixError::throwMe(ENOMEM); + } + + dispatch_retain(notificationQ); + xpc_connection_set_event_handler(service, ^(xpc_object_t cmsg) { + if (xpc_get_type(cmsg) == XPC_TYPE_CONNECTION) { + xpc_connection_t connection = xpc_connection_t(cmsg); + Syslog::debug("SecTranslocate: XPCServer, Connection from pid %d", xpc_connection_get_pid(connection)); + xpc_connection_set_event_handler(connection, ^(xpc_object_t msg) { + if (xpc_get_type(msg) == XPC_TYPE_DICTIONARY) { + xpc_retain(msg); + dispatch_async(notificationQ, ^{ // async from here + const char *function = xpc_dictionary_get_string(msg, kSecTranslocateXPCMessageFunction); + Syslog::debug("SecTranslocate: XPCServer, pid %d requested %s", xpc_connection_get_pid(connection), function); + xpc_object_t reply = xpc_dictionary_create_reply(msg); + try { + if (function == NULL) { + xpc_dictionary_set_int64(reply, kSecTranslocateXPCReplyError, EINVAL); + } else if (!strcmp(function, kSecTranslocateXPCFuncCreate)) { + doCreate(msg, reply); + } else if (!strcmp(function, kSecTranslocateXPCFuncCheckIn)) { + doCheckIn(msg); + } else { + xpc_dictionary_set_int64(reply, kSecTranslocateXPCReplyError, EINVAL); + } + } catch (Security::UnixError err) { + xpc_dictionary_set_int64(reply, kSecTranslocateXPCReplyError, err.unixError()); + } catch (...) { + xpc_dictionary_set_int64(reply, kSecTranslocateXPCReplyError, EINVAL); + } + xpc_release(msg); + if (reply) { + xpc_connection_send_message(connection, reply); + xpc_release(reply); + } + }); + } + }); + xpc_connection_resume(connection); + } else { + const char *s = xpc_copy_description(cmsg); + Syslog::error("SecTranslocate: XPCServer, unepxected incoming message - %s", s); + free((char*)s); + } + }); + xpc_connection_resume(service); +} + +XPCServer::~XPCServer() +{ + xpc_connection_cancel(service); + dispatch_release(notificationQ); +} + +} //namespace Security +} //namespace SecTranslocate diff --git a/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.hpp b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.hpp new file mode 100644 index 00000000..2b14381b --- /dev/null +++ b/OSX/libsecurity_translocate/lib/SecTranslocateXPCServer.hpp @@ -0,0 +1,51 @@ +/* + * 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@ + */ + +/* Purpose: This defines the xpc server for translocation */ + +#ifndef SecTranslocateXPCServer_hpp +#define SecTranslocateXPCServer_hpp + +#include +#include + +namespace Security { +namespace SecTranslocate { + +class XPCServer +{ +public: + XPCServer(dispatch_queue_t q); + ~XPCServer(); +private: + XPCServer() = delete; + XPCServer(const XPCServer& that) = delete; + + dispatch_queue_t notificationQ; + xpc_connection_t service; +}; + +} //namespace SecTranslocate +} //namespace Security + +#endif /* SecTranslocateXPCServer_hpp */ diff --git a/OSX/libsecurity_translocate/lib/security_translocate.exp b/OSX/libsecurity_translocate/lib/security_translocate.exp new file mode 100644 index 00000000..d18a7c00 --- /dev/null +++ b/OSX/libsecurity_translocate/lib/security_translocate.exp @@ -0,0 +1,25 @@ +# +# 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@ +# + +_SecTranslocateCreateSecureDirectoryForURL +_SecTranslocateDeleteSecureDirectory diff --git a/OSX/libsecurity_translocate/libsecurity_translocate.xcodeproj/project.pbxproj b/OSX/libsecurity_translocate/libsecurity_translocate.xcodeproj/project.pbxproj new file mode 100644 index 00000000..19323604 --- /dev/null +++ b/OSX/libsecurity_translocate/libsecurity_translocate.xcodeproj/project.pbxproj @@ -0,0 +1,383 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1F2D0DD71CBC7294007390C6 /* SecTranslocateXPCServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F2D0DD51CBC7294007390C6 /* SecTranslocateXPCServer.cpp */; }; + 1F2D0DD81CBC7294007390C6 /* SecTranslocateXPCServer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1F2D0DD61CBC7294007390C6 /* SecTranslocateXPCServer.hpp */; }; + 1F50781B1CB47EA500A017CD /* SecTranslocateUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F5078191CB47EA500A017CD /* SecTranslocateUtilities.cpp */; }; + 1F50781C1CB47EA500A017CD /* SecTranslocateUtilities.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1F50781A1CB47EA500A017CD /* SecTranslocateUtilities.hpp */; }; + 1F5078221CB5769200A017CD /* SecTranslocateServer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1F50781E1CB5747100A017CD /* SecTranslocateServer.hpp */; }; + 1F5A5D481CB5D8CF009BDA30 /* SecTranslocateLSNotification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F5A5D461CB5D8CF009BDA30 /* SecTranslocateLSNotification.cpp */; }; + 1F5A5D491CB5D8CF009BDA30 /* SecTranslocateLSNotification.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1F5A5D471CB5D8CF009BDA30 /* SecTranslocateLSNotification.hpp */; }; + 1F77EB011CBB15B7006E0E7E /* SecTranslocateDANotification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FB9D34D1CBB0E7C00374EF3 /* SecTranslocateDANotification.cpp */; }; + 1F975A3E1CBD5613003EF8F6 /* SecTranslocateClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F975A3C1CBD5613003EF8F6 /* SecTranslocateClient.cpp */; }; + 1F975A3F1CBD5613003EF8F6 /* SecTranslocateClient.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1F975A3D1CBD5613003EF8F6 /* SecTranslocateClient.hpp */; }; + 1FB9D3501CBB0E7C00374EF3 /* SecTranslocateDANotification.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1FB9D34E1CBB0E7C00374EF3 /* SecTranslocateDANotification.hpp */; }; + 1FC462B81C498980001E4B1F /* SecTranslocate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FC462B71C49897F001E4B1F /* SecTranslocate.cpp */; }; + 1FC462BA1C498991001E4B1F /* SecTranslocate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC462B91C498991001E4B1F /* SecTranslocate.h */; }; + 1FC4A6151CBDA7B900390630 /* SecTranslocateInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1FC4A6141CBDA7B900390630 /* SecTranslocateInterface.cpp */; }; + 1FC4A6161CBDC5C300390630 /* SecTranslocateServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F50781D1CB5747100A017CD /* SecTranslocateServer.cpp */; }; + 1FD0FA551CBC4A8C0037CB0E /* SecTranslocateInterface.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1FD0FA541CBC4A8C0037CB0E /* SecTranslocateInterface.hpp */; }; + 1FEFBDB01CB6D2AD00FAC2A1 /* SecTranslocateShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1F5A5D431CB58E97009BDA30 /* SecTranslocateShared.cpp */; }; + 1FEFBDB11CB6D2BC00FAC2A1 /* SecTranslocateShared.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 1F5A5D421CB58E97009BDA30 /* SecTranslocateShared.hpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1F2D0DD51CBC7294007390C6 /* SecTranslocateXPCServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateXPCServer.cpp; path = lib/SecTranslocateXPCServer.cpp; sourceTree = SOURCE_ROOT; }; + 1F2D0DD61CBC7294007390C6 /* SecTranslocateXPCServer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateXPCServer.hpp; path = lib/SecTranslocateXPCServer.hpp; sourceTree = SOURCE_ROOT; }; + 1F5078191CB47EA500A017CD /* SecTranslocateUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateUtilities.cpp; path = lib/SecTranslocateUtilities.cpp; sourceTree = SOURCE_ROOT; }; + 1F50781A1CB47EA500A017CD /* SecTranslocateUtilities.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateUtilities.hpp; path = lib/SecTranslocateUtilities.hpp; sourceTree = SOURCE_ROOT; }; + 1F50781D1CB5747100A017CD /* SecTranslocateServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateServer.cpp; path = lib/SecTranslocateServer.cpp; sourceTree = SOURCE_ROOT; }; + 1F50781E1CB5747100A017CD /* SecTranslocateServer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateServer.hpp; path = lib/SecTranslocateServer.hpp; sourceTree = SOURCE_ROOT; }; + 1F5A5D421CB58E97009BDA30 /* SecTranslocateShared.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateShared.hpp; path = lib/SecTranslocateShared.hpp; sourceTree = SOURCE_ROOT; }; + 1F5A5D431CB58E97009BDA30 /* SecTranslocateShared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateShared.cpp; path = lib/SecTranslocateShared.cpp; sourceTree = SOURCE_ROOT; }; + 1F5A5D461CB5D8CF009BDA30 /* SecTranslocateLSNotification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateLSNotification.cpp; path = lib/SecTranslocateLSNotification.cpp; sourceTree = SOURCE_ROOT; }; + 1F5A5D471CB5D8CF009BDA30 /* SecTranslocateLSNotification.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateLSNotification.hpp; path = lib/SecTranslocateLSNotification.hpp; sourceTree = SOURCE_ROOT; }; + 1F975A3C1CBD5613003EF8F6 /* SecTranslocateClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateClient.cpp; path = lib/SecTranslocateClient.cpp; sourceTree = SOURCE_ROOT; }; + 1F975A3D1CBD5613003EF8F6 /* SecTranslocateClient.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateClient.hpp; path = lib/SecTranslocateClient.hpp; sourceTree = SOURCE_ROOT; }; + 1FAA71431C10D8E000EAAE3E /* libsecurity_translocate.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsecurity_translocate.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 1FB9D34D1CBB0E7C00374EF3 /* SecTranslocateDANotification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateDANotification.cpp; path = lib/SecTranslocateDANotification.cpp; sourceTree = SOURCE_ROOT; }; + 1FB9D34E1CBB0E7C00374EF3 /* SecTranslocateDANotification.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateDANotification.hpp; path = lib/SecTranslocateDANotification.hpp; sourceTree = SOURCE_ROOT; }; + 1FC462B71C49897F001E4B1F /* SecTranslocate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocate.cpp; path = lib/SecTranslocate.cpp; sourceTree = SOURCE_ROOT; }; + 1FC462B91C498991001E4B1F /* SecTranslocate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecTranslocate.h; path = lib/SecTranslocate.h; sourceTree = SOURCE_ROOT; }; + 1FC4A6141CBDA7B900390630 /* SecTranslocateInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SecTranslocateInterface.cpp; path = lib/SecTranslocateInterface.cpp; sourceTree = SOURCE_ROOT; }; + 1FD0FA541CBC4A8C0037CB0E /* SecTranslocateInterface.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SecTranslocateInterface.hpp; path = lib/SecTranslocateInterface.hpp; sourceTree = SOURCE_ROOT; }; + 1FDA9ABE1C449C880083929D /* security_translocate.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; name = security_translocate.exp; path = lib/security_translocate.exp; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1FAA71401C10D8E000EAAE3E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1FAA713A1C10D8E000EAAE3E = { + isa = PBXGroup; + children = ( + 1FAA71451C10D8E000EAAE3E /* lib */, + 1FAA71441C10D8E000EAAE3E /* Products */, + ); + sourceTree = ""; + }; + 1FAA71441C10D8E000EAAE3E /* Products */ = { + isa = PBXGroup; + children = ( + 1FAA71431C10D8E000EAAE3E /* libsecurity_translocate.a */, + ); + name = Products; + sourceTree = ""; + }; + 1FAA71451C10D8E000EAAE3E /* lib */ = { + isa = PBXGroup; + children = ( + 1F975A3C1CBD5613003EF8F6 /* SecTranslocateClient.cpp */, + 1F975A3D1CBD5613003EF8F6 /* SecTranslocateClient.hpp */, + 1F2D0DD51CBC7294007390C6 /* SecTranslocateXPCServer.cpp */, + 1F2D0DD61CBC7294007390C6 /* SecTranslocateXPCServer.hpp */, + 1FD0FA541CBC4A8C0037CB0E /* SecTranslocateInterface.hpp */, + 1FB9D34D1CBB0E7C00374EF3 /* SecTranslocateDANotification.cpp */, + 1FB9D34E1CBB0E7C00374EF3 /* SecTranslocateDANotification.hpp */, + 1F5A5D461CB5D8CF009BDA30 /* SecTranslocateLSNotification.cpp */, + 1F5A5D471CB5D8CF009BDA30 /* SecTranslocateLSNotification.hpp */, + 1F5A5D421CB58E97009BDA30 /* SecTranslocateShared.hpp */, + 1F5A5D431CB58E97009BDA30 /* SecTranslocateShared.cpp */, + 1F50781D1CB5747100A017CD /* SecTranslocateServer.cpp */, + 1F50781E1CB5747100A017CD /* SecTranslocateServer.hpp */, + 1FC462B91C498991001E4B1F /* SecTranslocate.h */, + 1FC462B71C49897F001E4B1F /* SecTranslocate.cpp */, + 1FDA9ABE1C449C880083929D /* security_translocate.exp */, + 1F5078191CB47EA500A017CD /* SecTranslocateUtilities.cpp */, + 1F50781A1CB47EA500A017CD /* SecTranslocateUtilities.hpp */, + 1FC4A6141CBDA7B900390630 /* SecTranslocateInterface.cpp */, + ); + name = lib; + path = libsecurity_translocate; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1FAA71411C10D8E000EAAE3E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1FC462BA1C498991001E4B1F /* SecTranslocate.h in Headers */, + 1FD0FA551CBC4A8C0037CB0E /* SecTranslocateInterface.hpp in Headers */, + 1F975A3F1CBD5613003EF8F6 /* SecTranslocateClient.hpp in Headers */, + 1F5078221CB5769200A017CD /* SecTranslocateServer.hpp in Headers */, + 1FB9D3501CBB0E7C00374EF3 /* SecTranslocateDANotification.hpp in Headers */, + 1F5A5D491CB5D8CF009BDA30 /* SecTranslocateLSNotification.hpp in Headers */, + 1FEFBDB11CB6D2BC00FAC2A1 /* SecTranslocateShared.hpp in Headers */, + 1F2D0DD81CBC7294007390C6 /* SecTranslocateXPCServer.hpp in Headers */, + 1F50781C1CB47EA500A017CD /* SecTranslocateUtilities.hpp in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 1FAA71421C10D8E000EAAE3E /* libsecurity_translocate */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1FAA714C1C10D8E000EAAE3E /* Build configuration list for PBXNativeTarget "libsecurity_translocate" */; + buildPhases = ( + 1FAA713F1C10D8E000EAAE3E /* Sources */, + 1FAA71401C10D8E000EAAE3E /* Frameworks */, + 1FAA71411C10D8E000EAAE3E /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_translocate; + productName = libsecurity_translocate; + productReference = 1FAA71431C10D8E000EAAE3E /* libsecurity_translocate.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1FAA713B1C10D8E000EAAE3E /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0800; + ORGANIZATIONNAME = Apple; + TargetAttributes = { + 1FAA71421C10D8E000EAAE3E = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = 1FAA713E1C10D8E000EAAE3E /* Build configuration list for PBXProject "libsecurity_translocate" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1FAA713A1C10D8E000EAAE3E; + productRefGroup = 1FAA71441C10D8E000EAAE3E /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1FAA71421C10D8E000EAAE3E /* libsecurity_translocate */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 1FAA713F1C10D8E000EAAE3E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1FC4A6161CBDC5C300390630 /* SecTranslocateServer.cpp in Sources */, + 1F2D0DD71CBC7294007390C6 /* SecTranslocateXPCServer.cpp in Sources */, + 1FC462B81C498980001E4B1F /* SecTranslocate.cpp in Sources */, + 1F77EB011CBB15B7006E0E7E /* SecTranslocateDANotification.cpp in Sources */, + 1F975A3E1CBD5613003EF8F6 /* SecTranslocateClient.cpp in Sources */, + 1F5A5D481CB5D8CF009BDA30 /* SecTranslocateLSNotification.cpp in Sources */, + 1FEFBDB01CB6D2AD00FAC2A1 /* SecTranslocateShared.cpp in Sources */, + 1FC4A6151CBDA7B900390630 /* SecTranslocateInterface.cpp in Sources */, + 1F50781B1CB47EA500A017CD /* SecTranslocateUtilities.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1FAA714A1C10D8E000EAAE3E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + 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_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + 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_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx.internal; + }; + name = Debug; + }; + 1FAA714B1C10D8E000EAAE3E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + 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_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + 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_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx.internal; + }; + name = Release; + }; + 1FAA714D1C10D8E000EAAE3E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BOOL_CONVERSION = NO; + CODE_SIGN_IDENTITY = ""; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + EXECUTABLE_PREFIX = ""; + FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders", + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(PROJECT_DIR)/../utilities/", + ); + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_translocate; + SDKROOT = macosx.internal; + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "$(inherited)", + "-Wall", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Debug; + }; + 1FAA714E1C10D8E000EAAE3E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = YES; + "ARCHS[sdk=macosx*]" = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_ENABLE_MODULES = NO; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BOOL_CONVERSION = NO; + CODE_SIGN_IDENTITY = ""; + COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = YES; + ENABLE_STRICT_OBJC_MSGSEND = NO; + EXECUTABLE_PREFIX = ""; + FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; + GCC_PREPROCESSOR_DEFINITIONS = "NDEBUG=1"; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders", + "$(PROJECT_DIR)/../include", + "$(BUILT_PRODUCTS_DIR)/derived_src", + "$(PROJECT_DIR)/../utilities/", + ); + ONLY_ACTIVE_ARCH = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = /usr/local/include/security_translocate; + SDKROOT = macosx.internal; + VERSIONING_SYSTEM = "apple-generic"; + WARNING_CFLAGS = ( + "$(inherited)", + "-Wall", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1FAA713E1C10D8E000EAAE3E /* Build configuration list for PBXProject "libsecurity_translocate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1FAA714A1C10D8E000EAAE3E /* Debug */, + 1FAA714B1C10D8E000EAAE3E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1FAA714C1C10D8E000EAAE3E /* Build configuration list for PBXNativeTarget "libsecurity_translocate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1FAA714D1C10D8E000EAAE3E /* Debug */, + 1FAA714E1C10D8E000EAAE3E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1FAA713B1C10D8E000EAAE3E /* Project object */; +} diff --git a/OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp b/OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp index 1cbe0d02..5b8769ec 100644 --- a/OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp +++ b/OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp @@ -45,8 +45,29 @@ DLTransaction::~DLTransaction() { finalize(); } -void DLTransaction::success() { +void DLTransaction::commit() { + // Commit the transaction, and throw if it fails + + // If autocommit wasn't on on the database when we started, don't + // actually commit. There might be something else going on... + if(mAutoCommit) { + Security::CssmClient::ObjectImpl::check(CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_COMMIT, NULL, NULL)); + CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, reinterpret_cast(mAutoCommit), NULL); + } + + // Throwing above means this wasn't a success and we're not finalized. On exit, we'll roll back the transaction. mSuccess = true; + mFinalized = true; +} + +void DLTransaction::rollback() { + // If autocommit wasn't on on the database when we started, don't + // actually roll back. There might be something else going on... + if(mAutoCommit) { + CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); + CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(mAutoCommit), NULL); + } } void DLTransaction::finalize() { @@ -54,31 +75,18 @@ void DLTransaction::finalize() { return; } - // If autocommit wasn't on on the database when we started, don't - // actually commit. There might be something else going on... - if(mAutoCommit) { - // if this transaction was a success, commit. Otherwise, roll back. - if(mSuccess) { - Security::CssmClient::ObjectImpl::check(CSSM_DL_PassThrough(mDldbh, - CSSM_APPLEFILEDL_COMMIT, NULL, NULL)); - CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - reinterpret_cast(mAutoCommit), NULL); - } else { - // This is a failed transaction. Roll back, and turn autoCommit back on. - // - // Note that we're likely (but not necessarily) unwinding the stack for an exception right now. - // (If this transaction succeeded, we wouldn't be here. So, it failed, and this code likes to fail with exceptions.) - // If this throws an exception, we might crash the whole process. - // Swallow exceptions whole, but log them aggressively. - try { - CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); - CSSM_DL_PassThrough(mDldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - reinterpret_cast(mAutoCommit), NULL); - } catch(CssmError cssme) { - const char* errStr = cssmErrorString(cssme.error); - secdebugfunc("integrity", "caught CssmError during transaction rollback: %d %s", (int) cssme.error, errStr); - syslog(LOG_ERR, "ERROR: failed to rollback keychain transaction: %d %s", (int) cssme.error, errStr); - } + // if this transaction was not a success, roll back. + if(!mSuccess) { + // Note that we're likely (but not necessarily) unwinding the stack for an exception right now. + // (If this transaction succeeded, we wouldn't be here. So, it failed, and this code likes to fail with exceptions.) + // If this throws an exception, we might crash the whole process. + // Swallow exceptions whole, but log them aggressively. + try { + rollback(); + } catch(CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secnotice("integrity", "caught CssmError during transaction rollback: %d %s", (int) cssme.error, errStr); + syslog(LOG_ERR, "ERROR: failed to rollback keychain transaction: %d %s", (int) cssme.error, errStr); } } mFinalized = true; @@ -95,6 +103,5 @@ CSPDLTransaction::CSPDLTransaction(Security::CssmClient::Db& db) } CSPDLTransaction::~CSPDLTransaction() { - finalize(); } diff --git a/OSX/libsecurity_utilities/lib/CSPDLTransaction.h b/OSX/libsecurity_utilities/lib/CSPDLTransaction.h index 2a5adce3..078d9aca 100644 --- a/OSX/libsecurity_utilities/lib/CSPDLTransaction.h +++ b/OSX/libsecurity_utilities/lib/CSPDLTransaction.h @@ -29,14 +29,9 @@ // // This class performs a transaction on a CSPDL database. // -// It will commit when: +// If commit() has not yet been called when the object goes out of scope, the transaction will roll back instead (exceptions will be swallowed). // -// 1) success() has been called -// 2) the object goes out of scope OR finalize() is called -// -// if success() has not been called, the transaction will roll back instead. -// -// You can nest transaction objects, but I don't really suggest it... +// Nesting transactions will likely work, but isn't recommended. // class DLTransaction { public: @@ -45,18 +40,22 @@ public: ~DLTransaction(); // Everything has gone right; this transaction will commit. - // If you don't call this, the transaction will roll back. - void success(); - - // Commit or rollback as appropriate - void finalize(); + // If you don't call this, the transaction will roll back when the object goes out of scope. + // Might throw on error. + void commit(); protected: DLTransaction(); - // Actually toggle autocommit using the dldbh + // Note: disables autocommit using the dldbh void initialize(); + // Call rollback if necessary. Never throws. + void finalize(); + + // Rolls back database transactions. Might throw. + void rollback(); + CSSM_DL_DB_HANDLE mDldbh; bool mSuccess; diff --git a/OSX/libsecurity_utilities/lib/FileLockTransaction.cpp b/OSX/libsecurity_utilities/lib/FileLockTransaction.cpp new file mode 100644 index 00000000..1af4828a --- /dev/null +++ b/OSX/libsecurity_utilities/lib/FileLockTransaction.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 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 "FileLockTransaction.h" +#include +#include + +FileLockTransaction::FileLockTransaction(Security::CssmClient::Db& db) + : mDb(db), mSuccess(false), mFinalized(false), mDeleteOnFailure(false) { + initialize(); +} + +void FileLockTransaction::initialize() { + mDb->takeFileLock(); +} + +FileLockTransaction::~FileLockTransaction() { + finalize(); +} + +void FileLockTransaction::success() { + mSuccess = true; +} + +void FileLockTransaction::setDeleteOnFailure() { + mDeleteOnFailure = true; +} + +void FileLockTransaction::finalize() { + if(mFinalized) { + return; + } + + // if this transaction was a success, commit. Otherwise, roll back. + if(mSuccess) { + mDb->releaseFileLock(true); + } else { + // This is a failure. + + // Note that we're likely (but not necessarily) unwinding the stack for an exception right now. + // (If this transaction succeeded, we wouldn't be here. So, it failed, and this code likes to fail with exceptions.) + // If this throws an exception, we might crash the whole process. + // Swallow exceptions whole, but log them aggressively. + try { + if(mDeleteOnFailure) { + mDb->deleteFile(); + } + mDb->releaseFileLock(false); + } catch(CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secnotice("integrity", "caught CssmError during transaction rollback: %d %s", (int) cssme.error, errStr); + syslog(LOG_ERR, "ERROR: failed to rollback keychain transaction: %d %s", (int) cssme.error, errStr); + } + } + mFinalized = true; +} diff --git a/OSX/libsecurity_utilities/lib/FileLockTransaction.h b/OSX/libsecurity_utilities/lib/FileLockTransaction.h new file mode 100644 index 00000000..ad9c2432 --- /dev/null +++ b/OSX/libsecurity_utilities/lib/FileLockTransaction.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 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 FileLockTransaction_h +#define FileLockTransaction_h + +#include +// +// This class performs a file lock transaction on a Cssm Db object. +// +// It will attempt to take the file lock upon creation. +// +// It will release the file lock upon destruction OR calling finalize(). +// +// If you have called success(), it will tell the file lock transaction to commit +// otherwise, it will tell the file lock transaction to roll back. +// +// If you call setDeleteOnFailure(), and the transaction would normally roll +// back, this transaction will instead delete the Db's underlying file. +// +class FileLockTransaction { +public: + FileLockTransaction(Security::CssmClient::Db& db); + + ~FileLockTransaction(); + + // Everything has gone right; this transaction will commit. + // If you don't call this, the transaction will roll back. + void success(); + + // Commit or rollback as appropriate + void finalize(); + + // After calling this method, if this class attempts to roll back the + // transaction, it will also attempt to delete the database file. + void setDeleteOnFailure(); + +protected: + // Actually toggle autocommit using the dldbh + void initialize(); + + Security::CssmClient::Db mDb; + + bool mSuccess; + bool mFinalized; + bool mDeleteOnFailure; +}; + +#endif diff --git a/OSX/libsecurity_utilities/lib/alloc.h b/OSX/libsecurity_utilities/lib/alloc.h index 83403e01..411b58cb 100644 --- a/OSX/libsecurity_utilities/lib/alloc.h +++ b/OSX/libsecurity_utilities/lib/alloc.h @@ -74,8 +74,13 @@ public: // All right, if you *really* have to have calloc... void *calloc(size_t size, size_t count) throw(std::bad_alloc) { - void *addr = malloc(size * count); - memset(addr, 0, size * count); + size_t bytes = 0; + if(__builtin_mul_overflow(size, count, &bytes)) { + // Multiplication overflowed. + throw std::bad_alloc(); + } + void *addr = malloc(bytes); + memset(addr, 0, bytes); return addr; } diff --git a/OSX/libsecurity_ssl/lib/appleSession.h b/OSX/libsecurity_utilities/lib/casts.h similarity index 55% rename from OSX/libsecurity_ssl/lib/appleSession.h rename to OSX/libsecurity_utilities/lib/casts.h index fd87cd62..da638502 100644 --- a/OSX/libsecurity_ssl/lib/appleSession.h +++ b/OSX/libsecurity_utilities/lib/casts.h @@ -1,15 +1,15 @@ /* - * Copyright (c) 1999-2001,2005-2007,2010-2012,2014 Apple Inc. All Rights Reserved. + * 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, @@ -17,39 +17,30 @@ * 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@ */ -/* - * appleSession.h - Session storage module, Apple CDSA version. - */ +#ifndef casts_h +#define casts_h -#ifndef _APPLE_SESSION_H_ -#define _APPLE_SESSION_H_ +#include +#include +#include -#include "ssl.h" +template +static inline TResult int_cast(TSource value) { + // TODO: if we're using C++11, we should do some static_asserts on the signedness of these types + TResult result = static_cast(value); -#ifdef __cplusplus -extern "C" { + if (static_cast(result) != value) { +#ifndef NDEBUG + syslog(LOG_ERR, "%s: casted value out of range", __PRETTY_FUNCTION__); #endif - -extern OSStatus sslAddSession ( - const SSLBuffer sessionKey, - const SSLBuffer sessionData, - uint32_t timeToLive); /* optional time-to-live in seconds; 0 ==> default */ - -extern OSStatus sslCopySession ( - const SSLBuffer sessionKey, - SSLBuffer *sessionData); - -extern OSStatus sslDeleteSession ( - const SSLBuffer sessionKey); - -extern OSStatus sslCleanupSession(void); - -#ifdef __cplusplus + secnotice("int_cast", "casted value out of range"); + throw std::out_of_range("int_cast: casted value out of range"); + } + return result; } -#endif -#endif /* _APPLE_SESSION_H_ */ +#endif /* casts_h */ diff --git a/OSX/libsecurity_utilities/lib/ccaudit.cpp b/OSX/libsecurity_utilities/lib/ccaudit.cpp index ecde313a..5a543cad 100644 --- a/OSX/libsecurity_utilities/lib/ccaudit.cpp +++ b/OSX/libsecurity_utilities/lib/ccaudit.cpp @@ -116,7 +116,7 @@ void AuditRecord::submit(const short event_code, const int returnCode, if (!(au_get_state() == AUC_AUDITING)) return; - secdebug("ccaudit", "Submitting authorization audit record"); + secinfo("ccaudit", "Submitting authorization audit record"); int ret = kAUNoErr; diff --git a/OSX/libsecurity_utilities/lib/cfclass.cpp b/OSX/libsecurity_utilities/lib/cfclass.cpp index 75244e0c..530edb4b 100644 --- a/OSX/libsecurity_utilities/lib/cfclass.cpp +++ b/OSX/libsecurity_utilities/lib/cfclass.cpp @@ -26,8 +26,6 @@ #include #include #include -#include -#include // // CFClass @@ -60,42 +58,11 @@ CFClass::cleanupObject(intptr_t op, CFTypeRef cf, bool &zap) // the default is to not throw away the object zap = false; - bool isGC = CF_IS_COLLECTABLE(cf); - uint32_t currentCount; SecCFObject *obj = SecCFObject::optional(cf); uint32_t oldCount; currentCount = obj->updateRetainCount(op, &oldCount); - - if (isGC) - { - auto_zone_t* zone = objc_collectableZone(); - - if (op == -1 && oldCount == 0) - { - auto_zone_release(zone, (void*) cf); - } - else if (op == 1 && oldCount == 0 && currentCount == 1) - { - auto_zone_retain(zone, (void*) cf); - } - else if (op == -1 && oldCount == 1 && currentCount == 0) - { - /* - To prevent accidental resurrection, just pull it out of the - cache. - */ - obj->aboutToDestruct(); - auto_zone_release(zone, (void*) cf); - } - else if (op == 0) - { - return currentCount; - } - - return 0; - } if (op == 0) { @@ -163,23 +130,14 @@ void CFClass::finalizeType(CFTypeRef cf) throw() { /* - Why are we asserting the mutex here as well as in refCountForType? - Because the way we control the objects and the queues are different - under GC than they are under non-GC operations. - - In non-GC, we need to control the lifetime of the object. This means + We need to control the lifetime of the object. This means that the cache lock has to be asserted while we are determining if the object should live or die. The mutex is recursive, which means that we won't end up with mutex inversion. - - In GC, GC figures out the lifetime of the object. We probably don't need - to assert the mutex here, but it doesn't hurt. */ SecCFObject *obj = SecCFObject::optional(cf); - bool isCollectable = CF_IS_COLLECTABLE(cf); - try { Mutex* mutex = obj->getMutexForObject(); @@ -207,11 +165,6 @@ CFClass::finalizeType(CFTypeRef cf) throw() catch(...) { } - - if (isCollectable) - { - delete obj; - } } Boolean diff --git a/OSX/libsecurity_utilities/lib/cfmach++.cpp b/OSX/libsecurity_utilities/lib/cfmach++.cpp index f04828bd..8e02670d 100644 --- a/OSX/libsecurity_utilities/lib/cfmach++.cpp +++ b/OSX/libsecurity_utilities/lib/cfmach++.cpp @@ -86,7 +86,7 @@ void CFAutoPort::enable() } CFRunLoopAddSource(CFRunLoopGetCurrent(), mSource, kCFRunLoopCommonModes); mEnabled = true; - secdebug("autoport", "%p enabled", this); + secinfo("autoport", "%p enabled", this); } } @@ -100,7 +100,7 @@ void CFAutoPort::disable() if (mEnabled) { CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mSource, kCFRunLoopCommonModes); mEnabled = false; - secdebug("autoport", "%p disabled", this); + secinfo("autoport", "%p disabled", this); } } @@ -114,13 +114,13 @@ static int gNumTimesCalled = 0; void CFAutoPort::cfCallback(CFMachPortRef cfPort, void *msg, CFIndex size, void *context) { ++gNumTimesCalled; - secdebug("adhoc", "Callback was called %d times.", gNumTimesCalled); + secinfo("adhoc", "Callback was called %d times.", gNumTimesCalled); Message message(msg, (mach_msg_size_t)size); try { reinterpret_cast(context)->receive(message); } catch (...) { - secdebug("autoport", "%p receive handler failed with exception", context); + secinfo("autoport", "%p receive handler failed with exception", context); } } diff --git a/OSX/libsecurity_utilities/lib/cfutilities.cpp b/OSX/libsecurity_utilities/lib/cfutilities.cpp index 8f147467..c2f199bc 100644 --- a/OSX/libsecurity_utilities/lib/cfutilities.cpp +++ b/OSX/libsecurity_utilities/lib/cfutilities.cpp @@ -261,7 +261,7 @@ CFDataRef cfLoadFile(CFURLRef url) &data, NULL, NULL, &error)) { return data; } else { - secdebug("cfloadfile", "failed to fetch %s error=%d", cfString(url).c_str(), int(error)); + secinfo("cfloadfile", "failed to fetch %s error=%d", cfString(url).c_str(), int(error)); return NULL; } } diff --git a/OSX/libsecurity_utilities/lib/cfutilities.h b/OSX/libsecurity_utilities/lib/cfutilities.h index b8a38d3a..a29174d0 100644 --- a/OSX/libsecurity_utilities/lib/cfutilities.h +++ b/OSX/libsecurity_utilities/lib/cfutilities.h @@ -412,12 +412,12 @@ inline CFDataRef makeCFData(const void *data, size_t size) inline CFDataRef makeCFData(CFDictionaryRef dictionary) { - return CFPropertyListCreateXMLData(NULL, dictionary); + return CFPropertyListCreateData(NULL, dictionary, kCFPropertyListXMLFormat_v1_0, 0, NULL); } inline CFDataRef makeCFData(CFArrayRef array) { - return CFPropertyListCreateXMLData(NULL, array); + return CFPropertyListCreateData(NULL, array, kCFPropertyListXMLFormat_v1_0, 0, NULL); } template diff --git a/OSX/libsecurity_utilities/lib/coderepository.cpp b/OSX/libsecurity_utilities/lib/coderepository.cpp index bc18eec4..0c97973a 100644 --- a/OSX/libsecurity_utilities/lib/coderepository.cpp +++ b/OSX/libsecurity_utilities/lib/coderepository.cpp @@ -49,14 +49,14 @@ PathList::PathList(const string &subPath, if (envPath[0] == '!') { // envar="!path" -> single-item override (debugging only) mDebugOverride = envPath + 1; - secdebug("pathlist", "%p env(\"%s\") overrides to \"%s\"", + secinfo("pathlist", "%p env(\"%s\") overrides to \"%s\"", this, envar, mDebugOverride.c_str()); return; } #endif //NDEBUG // treat envPath as a classic colon-separated list of directories - secdebug("pathlist", "%p configuring from env(\"%s\")", this, envar); + secinfo("pathlist", "%p configuring from env(\"%s\")", this, envar); while (const char *p = strchr(envPath, ':')) { addDirectory(string(envPath, p - envPath)); envPath = p + 1; @@ -66,9 +66,9 @@ PathList::PathList(const string &subPath, } // no joy from environment variables - secdebug("pathlist", "%p configuring from default path set \"%s\"", this, subPath.c_str()); + secinfo("pathlist", "%p configuring from default path set \"%s\"", this, subPath.c_str()); if (forUser) - secdebug("pathlist", "user search list not yet implemented"); + secinfo("pathlist", "user search list not yet implemented"); addDirectory("/Library/" + subPath); addDirectory("/System/Library/" + subPath); } diff --git a/OSX/libsecurity_utilities/lib/coderepository.h b/OSX/libsecurity_utilities/lib/coderepository.h index 400dcf73..fb405324 100644 --- a/OSX/libsecurity_utilities/lib/coderepository.h +++ b/OSX/libsecurity_utilities/lib/coderepository.h @@ -89,18 +89,18 @@ void CodeRepository::update() if (CFRef bundles = CFBundleCreateBundlesFromDirectory(NULL, CFTempURL(*it, true), mSuffix.empty() ? NULL : CFStringRef(CFTempString(mSuffix)))) { CFIndex count = CFArrayGetCount(bundles); - secdebug("coderep", "%p directory %s has %ld entries", this, it->c_str(), count); + secinfo("coderep", "%p directory %s has %ld entries", this, it->c_str(), count); for (CFIndex n = 0; n < count; n++) try { result.push_back(new Code((CFBundleRef)CFArrayGetValueAtIndex(bundles, n))); } catch (...) { - secdebug("coderep", "%p exception creating %s (skipped)", + secinfo("coderep", "%p exception creating %s (skipped)", this, cfString(CFBundleRef(CFArrayGetValueAtIndex(bundles, n))).c_str()); } } else - secdebug("coderep", "directory %s bundle read failed", it->c_str()); + secinfo("coderep", "directory %s bundle read failed", it->c_str()); } - secdebug("coderep", "%p total of %ld items in list", this, result.size()); + secinfo("coderep", "%p total of %ld items in list", this, result.size()); this->swap(result); } diff --git a/OSX/libsecurity_utilities/lib/daemon.cpp b/OSX/libsecurity_utilities/lib/daemon.cpp index fc8c15e4..f06ced98 100644 --- a/OSX/libsecurity_utilities/lib/daemon.cpp +++ b/OSX/libsecurity_utilities/lib/daemon.cpp @@ -94,12 +94,12 @@ bool executeSelf(char **argv) { static const char reExecEnv[] = "_RE_EXECUTE"; if (getenv(reExecEnv)) { // was re-executed - secdebug("daemon", "self-execution complete"); + secinfo("daemon", "self-execution complete"); unsetenv(reExecEnv); return true; } else { setenv(reExecEnv, "go", 1); - secdebug("daemon", "self-executing (ouch!)"); + secinfo("daemon", "self-executing (ouch!)"); execv(argv[0], argv); perror("re-execution"); Syslog::error("Re-execution attempt failed"); diff --git a/OSX/libsecurity_utilities/lib/debugging.cpp b/OSX/libsecurity_utilities/lib/debugging.cpp deleted file mode 100644 index 5f5fa108..00000000 --- a/OSX/libsecurity_utilities/lib/debugging.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (c) 2000-2004,2011-2012,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@ - */ - - -// -// debugging - non-trivial debugging support -// -#include -#include -#include -#include - -#define SYSLOG_NAMES // compile syslog name tables -#include - -#include // for name demangling -#include // for _NSGetExecutablePath -#include - -// enable kernel tracing -#define ENABLE_SECTRACE 1 - - -namespace Security { -namespace Debug { - - -// -// Dump facility -// -bool dumping(const char *scope) -{ -#if defined(NDEBUG_STUBS) - return false; -#else - return Target::get().dump(scope); -#endif -} - -void dump(const char *format, ...) -{ -#if !defined(NDEBUG_CODE) - va_list args; - va_start(args, format); - Target::get().dump(format, args); - va_end(args); -#endif -} - -void dumpData(const void *ptr, size_t size) -{ -#if !defined(NDEBUG_CODE) - const char *addr = reinterpret_cast(ptr); - const char *end = addr + size; - bool isText = true; - for (const char *p = addr; p < end; p++) - if (!isprint(*p)) { isText = false; break; } - - if (isText) { - dump("\""); - for (const char *p = addr; p < end; p++) - dump("%c", *p); - dump("\""); - } else { - dump("0x"); - for (const char *p = addr; p < end; p++) - dump("%2.2x", static_cast(*p)); - } -#endif //NDEBUG_STUBS -} - -void dumpData(const char *title, const void *ptr, size_t size) -{ -#if !defined(NDEBUG_CODE) - dump("%s: ", title); - dumpData(ptr, size); - dump("\n"); -#endif //NDEBUG_STUBS -} - - -// -// Turn a C++ typeid into a nice type name. -// This uses the C++ ABI where available. -// We're stripping out a few C++ prefixes; they're pretty redundant (and obvious). -// -string makeTypeName(const type_info &type) -{ - int status; - char *cname = abi::__cxa_demangle(type.name(), NULL, NULL, &status); - string name = !strncmp(cname, "Security::", 10) ? (cname + 10) : - !strncmp(cname, "std::", 5) ? (cname + 5) : - cname; - ::free(cname); // yes, really (ABI rules) - return name; -} - - -// -// Target initialization. -// This where we should do all "first time" initializations. -// -#if !defined(NDEBUG_CODE) - -char Target::progName[maxProgNameLength + 1]; -unsigned int Target::PerThread::lastUsed; - -Target::Target() - : showScope(false), showThread(false), showProc(false), showDate(false), - sink(NULL) -{ - // put into singleton slot if first - if (singleton == NULL) - singleton = this; - - // insert terminate handler - if (!previousTerminator) // first time we do this - previousTerminator = set_terminate(terminator); - - // get program name - char execPath[PATH_MAX]; - uint32_t length = sizeof(execPath); - if (_NSGetExecutablePath(execPath, &length)) { - strcpy(progName, "unknown"); - } else { - const char *p = strrchr(execPath, '/'); - if (p) - p++; - else - p = execPath; - size_t plen = strlen(p); - if (plen > maxProgNameLength) // too long - p += plen - maxProgNameLength; // take rear - strcpy(progName, p); - } -} - -Target::~Target() -{ -} - - -static void addScope(char *&bufp, const char *scope) -{ - if (const char *sep = strchr(scope, ',')) { - bufp += sprintf(bufp, "%-*s", Name::maxLength, (const char *)Name(scope, sep)); - } else { // single scope - bufp += sprintf(bufp, "%-*s", Name::maxLength, scope); - } -} - - -// -// The core logging function of a Target -// -void Target::message(const char *scope, const char *format, va_list args) -{ - if (logSelector(scope)) { - // note: messageConstructionSize is big enough for all prefixes constructed - char buffer[messageConstructionSize]; // building the message here - char *bufp = buffer; - - // date option - if (showDate && sink->needsDate) { - time_t now = time(NULL); - char *date = ctime(&now); - date[19] = '\0'; - bufp += sprintf(bufp, "%s ", date + 4); // Nov 24 18:22:48 - } - - // leading scope - if (showScope && scope) - addScope(bufp, scope); - - if (showProc || showThread) { - char sub[maxProgNameLength + 20]; - unsigned plen = 0; - if (showProc && showThread) - plen = sprintf(sub, "%s[%d]", progName, getpid()); - else if (showProc) - plen = sprintf(sub, "%s", progName); - else - plen = sprintf(sub, "[%d]", getpid()); - unsigned int id = perThread().id; - if (id > 1) - plen += sprintf(sub + plen, ":%d", id); - if (plen <= procLength) - bufp += sprintf(bufp, "%-*s ", int(procLength), sub); - else - bufp += sprintf(bufp, "%s ", sub + plen - procLength); - } - - // scope after proc/thread/pid - if (showScopeRight && scope) - addScope(bufp, scope); - - // 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)) - *p = '?'; - if (written >= left) { // snprintf overflowed - bufp += left; - strcpy(bufp - 3, "..."); - } else - bufp += written; - - // now append a newline and a null - bufp[0] = '\n'; - bufp[1] = '\0'; - - // submit to sink (do not count newline and null in count) - sink->put(buffer, (unsigned int)(bufp - buffer)); - } -} - -bool Target::debugging(const char *scope) -{ - return logSelector(scope); -} - - -// -// The core debug-dump function of a target -// -void Target::dump(const char *format, va_list args) -{ - char buffer[messageConstructionSize]; // building the message here - vsnprintf(buffer, sizeof(buffer), format, args); - for (char *p = buffer; *p; p++) - if ((!isprint(*p) && !isspace(*p)) || *p == '\r') - *p = '?'; - sink->dump(buffer); -} - -bool Target::dump(const char *scope) -{ - return dumpSelector(scope); -} - - -// -// Selector objects. -// -Target::Selector::Selector() : useSet(false), negate(false) -{ } - -void Target::Selector::operator = (const char *scope) -{ - if (scope) { - // initial values - if (!strcmp(scope, "all")) { - useSet = false; - negate = true; - } else if (!strcmp(scope, "none")) { - useSet = negate = false; - } else { - useSet = true; - enableSet.erase(enableSet.begin(), enableSet.end()); - if (scope[0] == '-') { - negate = true; - scope++; - } else - negate = false; - while (const char *sep = strchr(scope, ',')) { - enableSet.insert(Name(scope, sep)); - scope = sep + 1; - } - enableSet.insert(scope); - } - } else { - useSet = negate = false; - } -} - -bool Target::Selector::operator () (const char *scope) const -{ - // a scope of NULL is a special override; it always qualifies - if (scope == NULL) - return true; - - if (useSet) { - while (const char *sep = strchr(scope, ',')) { - if (enableSet.find(Name(scope, sep)) != enableSet.end()) - return !negate; - scope = sep + 1; - } - return (enableSet.find(scope) != enableSet.end()) != negate; - } else { - return negate; - } -} - - -// -// Establish Target state from the environment -// -void Target::setFromEnvironment() -{ - // set scopes - logSelector = getenv("DEBUGSCOPE"); - dumpSelector = getenv("DEBUGDUMP"); - - // - // Set and configure destination. Currently available: - // /some/where -> that file - // LOG_SOMETHING -> syslog facility - // >&number -> that (already) open (for write or append) file descriptor - // anything else -> try as a filename sight unseen [may change] - // DEBUGDEST not set -> stderr - // anything in error -> stderr (with an error message on it) - // - if (const char *dest = getenv("DEBUGDEST")) { - if (dest[0] == '/') { // full pathname, write to file - to(dest); - } else if (!strncmp(dest, "LOG_", 4)) { // syslog - int facility = LOG_DAEMON; - for (CODE *cp = facilitynames; cp->c_name; cp++) - if (!strcmp(dest, cp->c_name)) - facility = cp->c_val; - to(facility | LOG_DEBUG); - } else if (!strncmp(dest, ">&", 2)) { // to file descriptor - int fd = atoi(dest+2); - if (FILE *f = fdopen(fd, "a")) { - to(f); - } else { - to(stderr); - secdebug("", "cannot log to fd[%d]: %s", fd, strerror(errno)); - } - } else { // if everything else fails, write a file - to(dest); - } - } else { // default destination is stderr - to(stderr); - } - configure(); -} - - -void Target::configure() -{ - configure(getenv("DEBUGOPTIONS")); -} - -void Target::configure(const char *config) -{ - // configure global options - showScopeRight = config && strstr(config, "rscope"); - showScope = !showScopeRight && config && strstr(config, "scope"); - showThread = config && (strstr(config, "thread") || strstr(config, "pid")); // (legacy) - showProc = config && strstr(config, "proc"); - showDate = config && strstr(config, "date"); - - // configure sink - if (sink) - sink->configure(config); -} - - -// -// Explicit destination assignments -// -void Target::to(Sink *s) -{ - delete sink; - sink = s; -} - -void Target::to(FILE *file) -{ - to(new FileSink(file)); -} - -void Target::to(const char *filename) -{ - if (FILE *f = fopen(filename, "a")) { - to(new FileSink(f)); - } else { - to(stderr); - secdebug("", "cannot debug to \"%s\": %s", filename, strerror(errno)); - } -} - -void Target::to(int syslogPriority) -{ - to(new SyslogSink(syslogPriority)); -} - - -// -// Making and retrieving the default singleton -// -Target *Target::singleton; - -Target &Target::get() -{ - if (singleton == NULL) { - Target *t = new Target; - t->setFromEnvironment(); - } - return *singleton; -} - - -// -// Standard sink implementations -// -Target::Sink::~Sink() -{ } - -void Target::Sink::dump(const char *) -{ } - -void Target::Sink::configure(const char *) -{ } - - -// -// The terminate handler installed when a Target is created -// -terminate_handler Target::previousTerminator; - -void Target::terminator() -{ - secdebug("exception", "uncaught exception terminates program"); - previousTerminator(); - secdebug("exception", "prior termination handler failed to abort; forcing abort"); - abort(); -} - - -// -// File sinks (write to file via stdio) -// -void FileSink::put(const char *inbuf, unsigned int length) -{ - fwrite(inbuf, 1, length + 1, file); // do pick up the trailing newline -} - -void FileSink::dump(const char *text) -{ - fputs(text, file); -} - -void FileSink::configure(const char *options) -{ - if (options == NULL || !strstr(options, "noflush")) { - // we mean "if the file isn't unbuffered", but what's the portable way to say that? - if (file != stderr) - setlinebuf(file); - } -} - - -// -// Syslog sinks (write to syslog) -// -void SyslogSink::put(const char *buffer, unsigned int length) -{ - syslog(priority, "%1.*s", length, buffer); // don't pick up trailing newline -} - -void SyslogSink::dump(const char *text) -{ - // add to dump buffer - snprintf(dumpPtr, dumpBuffer + dumpBufferSize - dumpPtr, "%s", text); - - // take off full lines and submit - char *p = dumpBase; - while (char *q = strchr(p, '\n')) { - *q++ = '\0'; // terminate/break - syslog(priority, " @@ %s", p); - p = q; - } - - if (*p) { // left-over unterminated line segment in buffer - dumpPtr = p + strlen(p); - if ((dumpBase = p) > dumpBuffer + dumpBufferSize / 2) { - // shift buffer down to make room - memmove(dumpBuffer, dumpBase, dumpPtr - dumpBase); - dumpPtr -= (dumpBase - dumpBuffer); - dumpBase = dumpBuffer; - } - } else { // buffer is empty; reset to start - dumpBase = dumpPtr = dumpBuffer; - } -} - -void SyslogSink::configure(const char *options) -{ -} - -#endif //NDEBUG_CODE - - -} // end namespace Debug -} // end namespace Security diff --git a/OSX/libsecurity_utilities/lib/debugging.h b/OSX/libsecurity_utilities/lib/debugging.h deleted file mode 100644 index 36b25377..00000000 --- a/OSX/libsecurity_utilities/lib/debugging.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2000-2004,2011-2012,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@ - */ - - -// -// debugging - non-trivial debug support -// -#ifndef _H_DEBUGGING -#define _H_DEBUGGING - - -#include - -#ifdef __cplusplus - -#include -#include -#include - -namespace Security { -namespace Debug { - - -// -// Debug-dumping functions always exist. They may be stubs depending on build options. -// -bool dumping(const char *scope); -void dump(const char *format, ...) __attribute((format(printf,1,2))); -void dumpData(const void *data, size_t length); -void dumpData(const char *title, const void *data, size_t length); -template inline void dumpData(const Data &obj) -{ dumpData(obj.data(), obj.length()); } -template inline void dumpData(const char *title, const Data &obj) -{ dumpData(title, obj.data(), obj.length()); } - - -// -// The following functions perform runtime recovery of type names. -// This is meant for debugging ONLY. Don't even THINK of depending -// on this for program correctness. For all you know, we may replace -// all those names with "XXX" tomorrow. -// -string makeTypeName(const type_info &info); - -template -string typeName(const Object &obj) -{ - return makeTypeName(typeid(obj)); -} - -template -string typeName() -{ - return makeTypeName(typeid(Object)); -} - - -// -// We are still conditionally emitting debug-dumping code -// -#undef DEBUGGING -#if !defined(NDEBUG) -# define DEBUGGING 1 -# define DEBUGDUMP 1 -#else //NDEBUG -# define DEBUGGING 0 -#endif //NDEBUG - -#if defined(DEBUGDUMP) -# define IFDUMP(code) code -# define IFDUMPING(scope,code) if (Debug::dumping(scope)) code; else /* no */ -#else -# define IFDUMP(code) /* no-op */ -# define IFDUMPING(scope,code) /* no-op */ -#endif - - -// -// We have some very, very old customers who call old debug facilities. -// Dummy them out for now. -// -inline bool debugging(const char *scope) DEPRECATED_ATTRIBUTE; -inline void debug(const char *scope, const char *format, ...) DEPRECATED_ATTRIBUTE; -inline void vdebug(const char *scope, const char *format, va_list args) DEPRECATED_ATTRIBUTE; - -inline bool debugging(const char *scope) { return false; } -inline void debug(const char *scope, const char *format, ...) { } -inline void vdebug(const char *scope, const char *format, va_list args) { } - - - - - -} // end namespace Debug -} // end namespace Security - -// leak debug() into the global namespace because URLAccess et al rely on that -using Security::Debug::debug; - -#else //__cplusplus - -#include - -#endif //__cplusplus - -#include - - -#endif //_H_DEBUGGING diff --git a/OSX/libsecurity_utilities/lib/debugging.h b/OSX/libsecurity_utilities/lib/debugging.h new file mode 120000 index 00000000..ac6a54fc --- /dev/null +++ b/OSX/libsecurity_utilities/lib/debugging.h @@ -0,0 +1 @@ +./../utilities/src/debugging.h \ No newline at end of file diff --git a/OSX/libsecurity_utilities/lib/debugging_internal.cpp b/OSX/libsecurity_utilities/lib/debugging_internal.cpp index 53aeecd7..d3dcac17 100644 --- a/OSX/libsecurity_utilities/lib/debugging_internal.cpp +++ b/OSX/libsecurity_utilities/lib/debugging_internal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,46 +22,506 @@ */ -#include "debugging_internal.h" -#include -#include - -void secdebug_internal(const char* scope, const char* format, ...) -{ - if (__builtin_expect(SECURITY_DEBUG_LOG_ENABLED(), 0)) - { - va_list list; - va_start(list, format); - - CFStringRef formatString = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, formatString, list); - CFRelease(formatString); - CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(message), kCFStringEncodingUTF8) + 1; - char buffer[maxLength]; - CFStringGetCString(message, buffer, sizeof(buffer), kCFStringEncodingUTF8); - CFRelease(message); - SECURITY_DEBUG_LOG((char *)(scope), (buffer)); - - va_end(list); - } -} - -void secdebugfunc_internal(const char* scope, const char* functionname, const char* format, ...) -{ - if (__builtin_expect(SECURITY_DEBUG_LOG_ENABLED(), 0)) - { - va_list list; - va_start(list, format); - - CFStringRef formatString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s: %s"), functionname, format); - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, formatString, list); - CFRelease(formatString); - CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(message), kCFStringEncodingUTF8) + 1; - char buffer[maxLength]; - CFStringGetCString(message, buffer, sizeof(buffer), kCFStringEncodingUTF8); - CFRelease(message); - SECURITY_DEBUG_LOG((char *)(scope), (buffer)); - - va_end(list); - } +// +// debugging - non-trivial debugging support +// +#include +#include +#include +#include +#include + +#define SYSLOG_NAMES // compile syslog name tables +#include + +#include // for name demangling +#include // for _NSGetExecutablePath +#include + +// enable kernel tracing +#define ENABLE_SECTRACE 1 + + +namespace Security { +namespace Debug { + + +// +// Dump facility +// +bool dumping(const char *scope) +{ +#if defined(NDEBUG_STUBS) + return false; +#else + return Target::get().dump(scope); +#endif +} + +void dump(const char *format, ...) +{ +#if !defined(NDEBUG_CODE) + va_list args; + va_start(args, format); + Target::get().dump(format, args); + va_end(args); +#endif +} + +void dumpData(const void *ptr, size_t size) +{ +#if !defined(NDEBUG_CODE) + const char *addr = reinterpret_cast(ptr); + const char *end = addr + size; + bool isText = true; + for (const char *p = addr; p < end; p++) + if (!isprint(*p)) { isText = false; break; } + + if (isText) { + dump("\""); + for (const char *p = addr; p < end; p++) + dump("%c", *p); + dump("\""); + } else { + dump("0x"); + for (const char *p = addr; p < end; p++) + dump("%2.2x", static_cast(*p)); + } +#endif //NDEBUG_STUBS +} + +void dumpData(const char *title, const void *ptr, size_t size) +{ +#if !defined(NDEBUG_CODE) + dump("%s: ", title); + dumpData(ptr, size); + dump("\n"); +#endif //NDEBUG_STUBS +} + + +// +// Turn a C++ typeid into a nice type name. +// This uses the C++ ABI where available. +// We're stripping out a few C++ prefixes; they're pretty redundant (and obvious). +// +string makeTypeName(const type_info &type) +{ + int status; + char *cname = abi::__cxa_demangle(type.name(), NULL, NULL, &status); + string name = !strncmp(cname, "Security::", 10) ? (cname + 10) : + !strncmp(cname, "std::", 5) ? (cname + 5) : + cname; + ::free(cname); // yes, really (ABI rules) + return name; +} + + +// +// Target initialization. +// This where we should do all "first time" initializations. +// +#if !defined(NDEBUG_CODE) + +char Target::progName[maxProgNameLength + 1]; +unsigned int Target::PerThread::lastUsed; + +Target::Target() + : showScope(false), showThread(false), showProc(false), showDate(false), + sink(NULL) +{ + // put into singleton slot if first + if (singleton == NULL) + singleton = this; + + // insert terminate handler + if (!previousTerminator) // first time we do this + previousTerminator = set_terminate(terminator); + + // get program name + char execPath[PATH_MAX]; + uint32_t length = sizeof(execPath); + if (_NSGetExecutablePath(execPath, &length)) { + strcpy(progName, "unknown"); + } else { + const char *p = strrchr(execPath, '/'); + if (p) + p++; + else + p = execPath; + size_t plen = strlen(p); + if (plen > maxProgNameLength) // too long + p += plen - maxProgNameLength; // take rear + strcpy(progName, p); + } +} + +Target::~Target() +{ +} + + +static void addScope(char *&bufp, const char *scope) +{ + if (const char *sep = strchr(scope, ',')) { + bufp += sprintf(bufp, "%-*s", Name::maxLength, (const char *)Name(scope, sep)); + } else { // single scope + bufp += sprintf(bufp, "%-*s", Name::maxLength, scope); + } +} + + +// +// The core logging function of a Target +// +void Target::message(const char *scope, const char *format, va_list args) +{ + if (logSelector(scope)) { + // note: messageConstructionSize is big enough for all prefixes constructed + char buffer[messageConstructionSize]; // building the message here + char *bufp = buffer; + + // date option + if (showDate && sink->needsDate) { + time_t now = time(NULL); + char *date = ctime(&now); + date[19] = '\0'; + bufp += sprintf(bufp, "%s ", date + 4); // Nov 24 18:22:48 + } + + // leading scope + if (showScope && scope) + addScope(bufp, scope); + + if (showProc || showThread) { + char sub[maxProgNameLength + 20]; + unsigned plen = 0; + if (showProc && showThread) + plen = sprintf(sub, "%s[%d]", progName, getpid()); + else if (showProc) + plen = sprintf(sub, "%s", progName); + else + plen = sprintf(sub, "[%d]", getpid()); + unsigned int id = perThread().id; + if (id > 1) + plen += sprintf(sub + plen, ":%d", id); + if (plen <= procLength) + bufp += sprintf(bufp, "%-*s ", int(procLength), sub); + else + bufp += sprintf(bufp, "%s ", sub + plen - procLength); + } + + // scope after proc/thread/pid + if (showScopeRight && scope) + addScope(bufp, scope); + + // 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)) + *p = '?'; + if (written >= left) { // snprintf overflowed + bufp += left; + strcpy(bufp - 3, "..."); + } else + bufp += written; + + // now append a newline and a null + bufp[0] = '\n'; + bufp[1] = '\0'; + + // submit to sink (do not count newline and null in count) + sink->put(buffer, (unsigned int)(bufp - buffer)); + } +} + +bool Target::debugging(const char *scope) +{ + return logSelector(scope); +} + + +// +// The core debug-dump function of a target +// +void Target::dump(const char *format, va_list args) +{ + char buffer[messageConstructionSize]; // building the message here + vsnprintf(buffer, sizeof(buffer), format, args); + for (char *p = buffer; *p; p++) + if ((!isprint(*p) && !isspace(*p)) || *p == '\r') + *p = '?'; + sink->dump(buffer); +} + +bool Target::dump(const char *scope) +{ + return dumpSelector(scope); +} + + +// +// Selector objects. +// +Target::Selector::Selector() : useSet(false), negate(false) +{ } + +void Target::Selector::operator = (const char *scope) +{ + if (scope) { + // initial values + if (!strcmp(scope, "all")) { + useSet = false; + negate = true; + } else if (!strcmp(scope, "none")) { + useSet = negate = false; + } else { + useSet = true; + enableSet.erase(enableSet.begin(), enableSet.end()); + if (scope[0] == '-') { + negate = true; + scope++; + } else + negate = false; + while (const char *sep = strchr(scope, ',')) { + enableSet.insert(Name(scope, sep)); + scope = sep + 1; + } + enableSet.insert(scope); + } + } else { + useSet = negate = false; + } +} + +bool Target::Selector::operator () (const char *scope) const +{ + // a scope of NULL is a special override; it always qualifies + if (scope == NULL) + return true; + + if (useSet) { + while (const char *sep = strchr(scope, ',')) { + if (enableSet.find(Name(scope, sep)) != enableSet.end()) + return !negate; + scope = sep + 1; + } + return (enableSet.find(scope) != enableSet.end()) != negate; + } else { + return negate; + } +} + + +// +// Establish Target state from the environment +// +void Target::setFromEnvironment() +{ + // set scopes + logSelector = getenv("DEBUGSCOPE"); + dumpSelector = getenv("DEBUGDUMP"); + + // + // Set and configure destination. Currently available: + // /some/where -> that file + // LOG_SOMETHING -> syslog facility + // >&number -> that (already) open (for write or append) file descriptor + // anything else -> try as a filename sight unseen [may change] + // DEBUGDEST not set -> stderr + // anything in error -> stderr (with an error message on it) + // + if (const char *dest = getenv("DEBUGDEST")) { + if (dest[0] == '/') { // full pathname, write to file + to(dest); + } else if (!strncmp(dest, "LOG_", 4)) { // syslog + int facility = LOG_DAEMON; + for (CODE *cp = facilitynames; cp->c_name; cp++) + if (!strcmp(dest, cp->c_name)) + facility = cp->c_val; + to(facility | LOG_DEBUG); + } else if (!strncmp(dest, ">&", 2)) { // to file descriptor + int fd = atoi(dest+2); + if (FILE *f = fdopen(fd, "a")) { + to(f); + } else { + to(stderr); + secinfo("", "cannot log to fd[%d]: %s", fd, strerror(errno)); + } + } else { // if everything else fails, write a file + to(dest); + } + } else { // default destination is stderr + to(stderr); + } + configure(); +} + + +void Target::configure() +{ + configure(getenv("DEBUGOPTIONS")); +} + +void Target::configure(const char *config) +{ + // configure global options + showScopeRight = config && strstr(config, "rscope"); + showScope = !showScopeRight && config && strstr(config, "scope"); + showThread = config && (strstr(config, "thread") || strstr(config, "pid")); // (legacy) + showProc = config && strstr(config, "proc"); + showDate = config && strstr(config, "date"); + + // configure sink + if (sink) + sink->configure(config); +} + + +// +// Explicit destination assignments +// +void Target::to(Sink *s) +{ + delete sink; + sink = s; +} + +void Target::to(FILE *file) +{ + to(new FileSink(file)); +} + +void Target::to(const char *filename) +{ + if (FILE *f = fopen(filename, "a")) { + to(new FileSink(f)); + } else { + to(stderr); + secinfo("", "cannot debug to \"%s\": %s", filename, strerror(errno)); + } +} + +void Target::to(int syslogPriority) +{ + to(new SyslogSink(syslogPriority)); +} + + +// +// Making and retrieving the default singleton +// +Target *Target::singleton; + +Target &Target::get() +{ + if (singleton == NULL) { + Target *t = new Target; + t->setFromEnvironment(); + } + return *singleton; +} + + +// +// Standard sink implementations +// +Target::Sink::~Sink() +{ } + +void Target::Sink::dump(const char *) +{ } + +void Target::Sink::configure(const char *) +{ } + + +// +// The terminate handler installed when a Target is created +// +terminate_handler Target::previousTerminator; + +void Target::terminator() +{ + secinfo("exception", "uncaught exception terminates program"); + previousTerminator(); + secinfo("exception", "prior termination handler failed to abort; forcing abort"); + abort(); +} + + +// +// File sinks (write to file via stdio) +// +void FileSink::put(const char *inbuf, unsigned int length) +{ + fwrite(inbuf, 1, length + 1, file); // do pick up the trailing newline +} + +void FileSink::dump(const char *text) +{ + fputs(text, file); +} + +void FileSink::configure(const char *options) +{ + if (options == NULL || !strstr(options, "noflush")) { + // we mean "if the file isn't unbuffered", but what's the portable way to say that? + if (file != stderr) + setlinebuf(file); + } +} + + +// +// Syslog sinks (write to syslog) +// +void SyslogSink::put(const char *buffer, unsigned int length) +{ + syslog(priority, "%1.*s", length, buffer); // don't pick up trailing newline +} + +void SyslogSink::dump(const char *text) +{ + // add to dump buffer + snprintf(dumpPtr, dumpBuffer + dumpBufferSize - dumpPtr, "%s", text); + + // take off full lines and submit + char *p = dumpBase; + while (char *q = strchr(p, '\n')) { + *q++ = '\0'; // terminate/break + syslog(priority, " @@ %s", p); + p = q; + } + + if (*p) { // left-over unterminated line segment in buffer + dumpPtr = p + strlen(p); + if ((dumpBase = p) > dumpBuffer + dumpBufferSize / 2) { + // shift buffer down to make room + memmove(dumpBuffer, dumpBase, dumpPtr - dumpBase); + dumpPtr -= (dumpBase - dumpBuffer); + dumpBase = dumpBuffer; + } + } else { // buffer is empty; reset to start + dumpBase = dumpPtr = dumpBuffer; + } +} + +void SyslogSink::configure(const char *options) +{ +} + +#endif //NDEBUG_CODE + + +} // end namespace Debug +} // end namespace Security + + +void secdebug_internal(const char* scope, const char* format, ...) { + // no-op. +} +void secdebugfunc_internal(const char* scope, const char* functionname, const char* format, ...) { + // no-op. } diff --git a/OSX/libsecurity_utilities/lib/debugging_internal.h b/OSX/libsecurity_utilities/lib/debugging_internal.h index 6f990296..a33ee7c2 100644 --- a/OSX/libsecurity_utilities/lib/debugging_internal.h +++ b/OSX/libsecurity_utilities/lib/debugging_internal.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved. - * + * Copyright (c) 2000-2004,2011-2012,2014 Apple Inc. All Rights Reserved. + * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code @@ -22,42 +22,121 @@ */ -#ifndef libsecurity_utilities_debugging_internal_h -#define libsecurity_utilities_debugging_internal_h - +// +// debugging_internal - non-trivial debug support +// +// everything in this file is deprecated. Try not to use it. +// +#ifndef _H_DEBUGGING +#define _H_DEBUGGING #ifdef __cplusplus -extern "C" + +#include +#include +#include + +namespace Security { +namespace Debug { + + +// +// Debug-dumping functions always exist. They may be stubs depending on build options. +// +bool dumping(const char *scope); +void dump(const char *format, ...) __attribute((format(printf,1,2))); +void dumpData(const void *data, size_t length); +void dumpData(const char *title, const void *data, size_t length); +template inline void dumpData(const Data &obj) +{ dumpData(obj.data(), obj.length()); } +template inline void dumpData(const char *title, const Data &obj) +{ dumpData(title, obj.data(), obj.length()); } + + +// +// The following functions perform runtime recovery of type names. +// This is meant for debugging ONLY. Don't even THINK of depending +// on this for program correctness. For all you know, we may replace +// all those names with "XXX" tomorrow. +// +string makeTypeName(const type_info &info); + +template +string typeName(const Object &obj) { -#endif // __cplusplus + return makeTypeName(typeid(obj)); +} + +template +string typeName() +{ + return makeTypeName(typeid(Object)); +} + // -// Include DTrace static probe definitions +// We are still conditionally emitting debug-dumping code // -typedef const void *DTException; +#undef DEBUGGING +#if !defined(NDEBUG) +# define DEBUGGING 1 +# define DEBUGDUMP 1 +#else //NDEBUG +# define DEBUGGING 0 +#endif //NDEBUG + +#if defined(DEBUGDUMP) +# define IFDUMP(code) code +# define IFDUMPING(scope,code) if (Debug::dumping(scope)) code; else /* no */ +#else +# define IFDUMP(code) /* no-op */ +# define IFDUMPING(scope,code) /* no-op */ +#endif -#include // -// The debug-log macro is now unconditionally emitted as a DTrace static probe point. +// We have some very, very old customers who call old debug facilities. +// Dummy them out for now. // +inline bool debugging(const char *scope) DEPRECATED_ATTRIBUTE; +inline void debug(const char *scope, const char *format, ...) DEPRECATED_ATTRIBUTE; +inline void vdebug(const char *scope, const char *format, va_list args) DEPRECATED_ATTRIBUTE; + +inline bool debugging(const char *scope) { return false; } +inline void debug(const char *scope, const char *format, ...) { } +inline void vdebug(const char *scope, const char *format, va_list args) { } + -void secdebug_internal(const char* scope, const char* format, ...); -void secdebugfunc_internal(const char* scope, const char* functionname, const char* format, ...); -#define secdebug(scope, format...) secdebug_internal(scope, format) -#define secdebugfunc(scope, format...) secdebugfunc_internal(scope, __PRETTY_FUNCTION__, format) -#define secdebugf(scope, __msg) SECURITY_DEBUG_LOG((char *)(scope), (__msg)) + + +} // end namespace Debug +} // end namespace Security + +// leak debug() into the global namespace because URLAccess et al rely on that +using Security::Debug::debug; + +__BEGIN_DECLS // -// The old secdelay() macro is also emitted as a DTrace probe (use destructive actions to handle this). -// Secdelay() should be considered a legacy feature; just put a secdebug at the intended delay point. +// Include DTrace static probe definitions // -#define secdelay(file) SECURITY_DEBUG_DELAY((char *)(file)) +typedef const void *DTException; +#include +// The following are deprecated functions. Don't use them (but they need to be here for symbol reasons). +void secdebug_internal(const char* scope, const char* format, ...); +void secdebugfunc_internal(const char* scope, const char* functionname, const char* format, ...); -#ifdef __cplusplus -}; -#endif // __cplusplus +__END_DECLS -#endif +#else //__cplusplus + +#include + +#endif //__cplusplus + +#include + + +#endif //_H_DEBUGGING diff --git a/OSX/libsecurity_utilities/lib/errors.cpp b/OSX/libsecurity_utilities/lib/errors.cpp index eab27f83..7384c990 100644 --- a/OSX/libsecurity_utilities/lib/errors.cpp +++ b/OSX/libsecurity_utilities/lib/errors.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include //@@@ // From cssmapple.h - layering break @@ -40,13 +42,8 @@ // // The base of the exception hierarchy. -// Note that the debug output here depends on a particular -// implementation feature of gcc; to wit, that the exception object -// is created and then copied (at least once) via its copy constructor. -// If your compiler does not invoke the copy constructor, you won't get -// debug output, but nothing worse should happen. // -CommonError::CommonError() +CommonError::CommonError() : whatBuffer("CommonError") { } @@ -54,34 +51,89 @@ CommonError::CommonError() // // We strongly encourage catching all exceptions by const reference, so the copy // constructor of our exceptions should never be called. -// We trace a copy to help catch violations of this rule. // CommonError::CommonError(const CommonError &source) { - SECURITY_EXCEPTION_COPY(this, &source); + strlcpy(whatBuffer, source.whatBuffer, whatBufferSize); } CommonError::~CommonError() throw () { - SECURITY_EXCEPTION_HANDLED(this); +} + +void CommonError::LogBacktrace() { + // Only do this work if we're actually going to log things + if(secinfoenabled("security_exception")) { + const size_t maxsize = 32; + void* callstack[maxsize]; + + int size = backtrace(callstack, maxsize); + char** names = backtrace_symbols(callstack, size); + + // C++ symbolicate the callstack + + const char* delim = " "; + string build; + char * token = NULL; + char * line = NULL; + + for(int i = 0; i < size; i++) { + build = ""; + + line = names[i]; + + while((token = strsep(&line, delim))) { + if(*token == '\0') { + build += " "; + } else { + int status = 0; + char * demangled = abi::__cxa_demangle(token, NULL, NULL, &status); + if(status == 0) { + build += demangled; + } else { + build += token; + } + build += " "; + + if(demangled) { + free(demangled); + } + } + } + + secinfo("security_exception", "%s", build.c_str()); + } + free(names); + } } + // // UnixError exceptions // UnixError::UnixError() : error(errno) { - SECURITY_EXCEPTION_THROW_UNIX(this, errno); + SECURITY_EXCEPTION_THROW_UNIX(this, errno); + + snprintf(whatBuffer, whatBufferSize, "UNIX errno exception: %d", this->error); + secnotice("security_exception", "%s", what()); + LogBacktrace(); } UnixError::UnixError(int err) : error(err) { - SECURITY_EXCEPTION_THROW_UNIX(this, err); + SECURITY_EXCEPTION_THROW_UNIX(this, err); + + snprintf(whatBuffer, whatBufferSize, "UNIX error exception: %d", this->error); + secnotice("security_exception", "%s", what()); + LogBacktrace(); } const char *UnixError::what() const throw () -{ return "UNIX error exception"; } +{ + return whatBuffer; +} OSStatus UnixError::osStatus() const @@ -103,11 +155,17 @@ UnixError UnixError::make(int err) { return UnixError(err); } // MacOSError::MacOSError(int err) : error(err) { - SECURITY_EXCEPTION_THROW_OSSTATUS(this, err); + SECURITY_EXCEPTION_THROW_OSSTATUS(this, err); + + snprintf(whatBuffer, whatBufferSize, "MacOS error: %d", this->error); + secnotice("security_exception", "%s", what()); + LogBacktrace(); } const char *MacOSError::what() const throw () -{ return "MacOS error"; } +{ + return whatBuffer; +} OSStatus MacOSError::osStatus() const { return error; } @@ -137,7 +195,9 @@ MacOSError MacOSError::make(int error) // CFError::CFError() { - SECURITY_EXCEPTION_THROW_CF(this); + SECURITY_EXCEPTION_THROW_CF(this); + secnotice("security_exception", "CFError"); + LogBacktrace(); } const char *CFError::what() const throw () diff --git a/OSX/libsecurity_utilities/lib/errors.h b/OSX/libsecurity_utilities/lib/errors.h index cbc2bd62..4725bee5 100644 --- a/OSX/libsecurity_utilities/lib/errors.h +++ b/OSX/libsecurity_utilities/lib/errors.h @@ -54,6 +54,11 @@ public: virtual OSStatus osStatus() const = 0; virtual int unixError() const = 0; + + char whatBuffer[128]; + const size_t whatBufferSize = sizeof(whatBuffer); + + static void LogBacktrace(); }; diff --git a/OSX/libsecurity_utilities/lib/exports b/OSX/libsecurity_utilities/lib/exports index d9e60230..f262b943 100644 --- a/OSX/libsecurity_utilities/lib/exports +++ b/OSX/libsecurity_utilities/lib/exports @@ -1,2 +1,8 @@ _secdebug_internal _secdebugfunc_internal +#ifdef TARGET_OS_OSX +_weak_os_log_impl +_weak_os_log_create +_weak_os_log_type_enabled +_logObjForScope +#endif diff --git a/OSX/libsecurity_utilities/lib/globalizer.h b/OSX/libsecurity_utilities/lib/globalizer.h index 66480469..aa733560 100644 --- a/OSX/libsecurity_utilities/lib/globalizer.h +++ b/OSX/libsecurity_utilities/lib/globalizer.h @@ -127,7 +127,7 @@ class CleanModuleNexus : public ModuleNexus { public: ~CleanModuleNexus() { - secdebug("nexus", "ModuleNexus %p destroyed object 0x%x", + secinfo("nexus", "ModuleNexus %p destroyed object 0x%x", this, ModuleNexus::pointer); delete reinterpret_cast(ModuleNexus::pointer); } diff --git a/OSX/libsecurity_utilities/lib/hosts.cpp b/OSX/libsecurity_utilities/lib/hosts.cpp index 2d15a909..689d46fc 100644 --- a/OSX/libsecurity_utilities/lib/hosts.cpp +++ b/OSX/libsecurity_utilities/lib/hosts.cpp @@ -130,7 +130,7 @@ NamedHost::NamedHost(const char *name) : mName(name) if (hostent *he = gethostbyname(name)) { for (char **p = he->h_addr_list; *p; p++) mAddrs.insert(*reinterpret_cast(*p)); - secdebug("ipname", "host %s resolves to %ld address(es)", mName.c_str(), mAddrs.size()); + secinfo("ipname", "host %s resolves to %ld address(es)", mName.c_str(), mAddrs.size()); return; } UnixError::throwMe(ENOENT); //@@@ h_errno translation or other source diff --git a/OSX/libsecurity_utilities/lib/iodevices.cpp b/OSX/libsecurity_utilities/lib/iodevices.cpp index 28633d3e..42874c4d 100644 --- a/OSX/libsecurity_utilities/lib/iodevices.cpp +++ b/OSX/libsecurity_utilities/lib/iodevices.cpp @@ -190,7 +190,7 @@ void NotificationPort::add(const DeviceMatch &match, Receiver &receiver, const c &iterator)); // run initial iterator to process existing devices - secdebug("iokit", "dispatching initial device match iterator %d", iterator); + secinfo("iokit", "dispatching initial device match iterator %d", iterator); DeviceIterator it(iterator); receiver.ioChange(it); } @@ -199,10 +199,9 @@ void NotificationPort::addInterestNotification(Receiver &receiver, io_service_t const io_name_t interestType) { io_iterator_t iterator; - mach_port_t pp = NotificationPort::port(); - secdebug("iokit", "NotificationPort::addInterest - type: %s [port: %p (0x%08X), service: 0x%08X]", - interestType, mPortRef, pp, service); + secinfo("iokit", "NotificationPort::addInterest - type: %s [port: %p (0x%08X), service: 0x%08X]", + interestType, mPortRef, NotificationPort::port(), service); // We cannot throw if we get an error here since we will receive notifications // from each plane, and not all planes have the necessary information to be @@ -212,30 +211,30 @@ void NotificationPort::addInterestNotification(Receiver &receiver, io_service_t const char *msgstr = mach_error_string(kr); const char *msgtyp = mach_error_type(kr); if (msgstr && msgtyp) - secdebug("iokit", " msg: %s, typ: %s", msgstr, msgtyp); + secinfo("iokit", " msg: %s, typ: %s", msgstr, msgtyp); } void NotificationPort::ioNotify(void *refCon, io_iterator_t iterator) { - secdebug("iokit", "dispatching new device match iterator %d", iterator); + secinfo("iokit", "dispatching new device match iterator %d", iterator); DeviceIterator it(iterator); try { reinterpret_cast(refCon)->ioChange(it); } catch (...) { - secdebug("iokit", "ioChange callback threw an exception (ignored)"); + secinfo("iokit", "ioChange callback threw an exception (ignored)"); } } void NotificationPort::ioDeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { - secdebug("iokit", "dispatching NEW device notification iterator, service 0x%08X, msg: 0x%04X, arg: %p", + secinfo("iokit", "dispatching NEW device notification iterator, service 0x%08X, msg: 0x%04X, arg: %p", service, messageType, messageArgument); const char *msgstr = mach_error_string(messageType); const char *msgtyp = mach_error_type(messageType); if (msgstr && msgtyp) - secdebug("iokit", " msg: %s, typ: %s", msgstr, msgtyp); + secinfo("iokit", " msg: %s, typ: %s", msgstr, msgtyp); if (service!=io_service_t(-1)) reinterpret_cast(refCon)->ioServiceChange(refCon, service, messageType, messageArgument); diff --git a/OSX/libsecurity_utilities/lib/ip++.cpp b/OSX/libsecurity_utilities/lib/ip++.cpp index b589c11f..030b678f 100644 --- a/OSX/libsecurity_utilities/lib/ip++.cpp +++ b/OSX/libsecurity_utilities/lib/ip++.cpp @@ -159,7 +159,7 @@ void Socket::open(int domain, int type, int protocol) { checkSetFd(::socket(domain, type, protocol)); mAtEnd = false; - secdebug("sockio", "socket(%d,%d) -> %d", type, protocol, fd()); + secinfo("sockio", "socket(%d,%d) -> %d", type, protocol, fd()); } void Socket::prepare(int fdFlags, int domain, int type, int protocol) @@ -182,13 +182,13 @@ void Socket::bind(const IPAddress &addr, IPPort port) void Socket::bind(const IPSockAddress &local) { checkError(::bind(fd(), local, sizeof(local))); - secdebug("sockio", "%d bind to %s", fd(), string(local).c_str()); + secinfo("sockio", "%d bind to %s", fd(), string(local).c_str()); } void Socket::bind(const UNSockAddress &local) { checkError(::bind(fd(), local, sizeof(local))); - secdebug("sockio", "%d bind to %s", fd(), string(local).c_str()); + secinfo("sockio", "%d bind to %s", fd(), string(local).c_str()); } @@ -224,17 +224,17 @@ bool Socket::connect(const IPSockAddress &peer) if (::connect(fd(), peer, sizeof(peer))) { switch (errno) { case EINPROGRESS: - secdebug("sockio", "%d connecting to %s", fd(), string(peer).c_str()); + secinfo("sockio", "%d connecting to %s", fd(), string(peer).c_str()); return false; case EALREADY: if (int err = error()) // connect failed UnixError::throwMe(err); // just keep trying - secdebug("sockio", "%d still trying to connect", fd()); + secinfo("sockio", "%d still trying to connect", fd()); return false; case EISCONN: if (flags() & O_NONBLOCK) { - secdebug("sockio", "%d now connected", fd()); + secinfo("sockio", "%d now connected", fd()); return true; } else { UnixError::throwMe(); @@ -243,7 +243,7 @@ bool Socket::connect(const IPSockAddress &peer) UnixError::throwMe(); } } else { - secdebug("sockio", "%d connect to %s", fd(), string(peer).c_str()); + secinfo("sockio", "%d connect to %s", fd(), string(peer).c_str()); return true; } } @@ -257,7 +257,7 @@ bool Socket::connect(const UNSockAddress &peer) { // no nice async support here: local operation (but keep the niceties) checkError(::connect(fd(), peer, sizeof(peer))); - secdebug("sockio", "%d connect to %s", fd(), string(peer).c_str()); + secinfo("sockio", "%d connect to %s", fd(), string(peer).c_str()); return true; } @@ -314,7 +314,7 @@ void Socket::connect(const Host &host, IPPort port) for (set::const_iterator it = addrs.begin(); it != addrs.end(); it++) { const IPSockAddress address(*it, port); if (::connect(fd(), address, sizeof(IPSockAddress)) == 0) { - secdebug("sockio", "%d connect to %s", fd(), string(address).c_str()); + secinfo("sockio", "%d connect to %s", fd(), string(address).c_str()); return; } } diff --git a/OSX/libsecurity_utilities/lib/mach++.cpp b/OSX/libsecurity_utilities/lib/mach++.cpp index f0ba24b7..616dcdf7 100644 --- a/OSX/libsecurity_utilities/lib/mach++.cpp +++ b/OSX/libsecurity_utilities/lib/mach++.cpp @@ -41,7 +41,8 @@ namespace MachPlusPlus { // Error::Error(kern_return_t err) : error(err) { - SECURITY_EXCEPTION_THROW_MACH(this, err); + SECURITY_EXCEPTION_THROW_MACH(this, err); + secnotice("security_exception", "mach error: %d", err); } Error::~Error() throw() @@ -127,9 +128,9 @@ mach_port_t Port::requestNotify(mach_port_t notify, mach_msg_id_t type, mach_por default: typeName = "???"; break; } if (notify == MACH_PORT_NULL) - secdebug("port", "%d cancel notify %s", port(), typeName); + secinfo("port", "%d cancel notify %s", port(), typeName); else - secdebug("port", "%d request notify %s to %d (sync %d)", port(), typeName, notify, sync); + secinfo("port", "%d request notify %s to %d (sync %d)", port(), typeName, notify, sync); #endif //!NDEBUG return previous; @@ -232,7 +233,7 @@ mach_port_t Bootstrap::checkInOptional(const char *name) const void Bootstrap::registerAs(mach_port_t port, const char *name) const { - secdebug("bootstrap", "creating service port %d in %d:%s", port, this->port(), name); + secinfo("bootstrap", "creating service port %d in %d:%s", port, this->port(), name); check(::bootstrap_register(mPort, makeName(name), port)); } @@ -298,13 +299,13 @@ StBootstrap::StBootstrap(const Bootstrap &newBoot, const TaskPort &task) { mOldBoot = Bootstrap(); mTask.bootstrap(newBoot); - secdebug("StBoot", "bootstrap for %d switched to %d", mTask.port(), newBoot.port()); + secinfo("StBoot", "bootstrap for %d switched to %d", mTask.port(), newBoot.port()); } StBootstrap::~StBootstrap() { mTask.bootstrap(mOldBoot); - secdebug("StBoot", "bootstrap for %d returned to %d", mTask.port(), mOldBoot.port()); + secinfo("StBoot", "bootstrap for %d returned to %d", mTask.port(), mOldBoot.port()); } diff --git a/OSX/libsecurity_utilities/lib/mach++.h b/OSX/libsecurity_utilities/lib/mach++.h index f87b4a3c..84236769 100644 --- a/OSX/libsecurity_utilities/lib/mach++.h +++ b/OSX/libsecurity_utilities/lib/mach++.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/OSX/libsecurity_utilities/lib/macho++.cpp b/OSX/libsecurity_utilities/lib/macho++.cpp index ed3a2fea..9587e253 100644 --- a/OSX/libsecurity_utilities/lib/macho++.cpp +++ b/OSX/libsecurity_utilities/lib/macho++.cpp @@ -140,7 +140,7 @@ void MachOBase::initHeader(const mach_header *header) m64 = true; break; default: - secdebug("macho", "%p: unrecognized header magic (%x)", this, mHeader->magic); + secinfo("macho", "%p: unrecognized header magic (%x)", this, mHeader->magic); UnixError::throwMe(ENOEXEC); } } @@ -505,7 +505,7 @@ Universal::Universal(FileDesc fd, size_t offset /* = 0 */, size_t length /* = 0 if (last_arch->cputype == (CPU_ARCH_ABI64 | CPU_TYPE_ARM)) { mArchCount++; } - secdebug("macho", "%p is a fat file with %d architectures", + secinfo("macho", "%p is a fat file with %d architectures", this, mArchCount); /* A Mach-O universal file has padding of no more than "page size" @@ -579,14 +579,14 @@ Universal::Universal(FileDesc fd, size_t offset /* = 0 */, size_t length /* = 0 mArchList = NULL; mArchCount = 0; mThinArch = Architecture(mheader.cputype, mheader.cpusubtype); - secdebug("macho", "%p is a thin file (%s)", this, mThinArch.name()); + secinfo("macho", "%p is a thin file (%s)", this, mThinArch.name()); break; case MH_CIGAM: case MH_CIGAM_64: mArchList = NULL; mArchCount = 0; mThinArch = Architecture(flip(mheader.cputype), flip(mheader.cpusubtype)); - secdebug("macho", "%p is a thin file (%s)", this, mThinArch.name()); + secinfo("macho", "%p is a thin file (%s)", this, mThinArch.name()); break; default: UnixError::throwMe(ENOEXEC); diff --git a/OSX/libsecurity_utilities/lib/machrunloopserver.cpp b/OSX/libsecurity_utilities/lib/machrunloopserver.cpp index 38021594..f6ef5ac5 100644 --- a/OSX/libsecurity_utilities/lib/machrunloopserver.cpp +++ b/OSX/libsecurity_utilities/lib/machrunloopserver.cpp @@ -97,7 +97,7 @@ void MachRunLoopServer::receive(const Message &request) void MachRunLoopServer::oneRequest(const Message &request) { if (!handle(request, mReplyMessage)) { // MIG dispatch failed - secdebug("machrls", "MachRunLoopServer dispatch failed"); + secinfo("machrls", "MachRunLoopServer dispatch failed"); } else { // MIG dispatch handled the call. Send reply back to caller. mReplyMessage.send((MACH_MSGH_BITS_REMOTE(mReplyMessage.bits()) == MACH_MSG_TYPE_MOVE_SEND_ONCE) ? diff --git a/OSX/libsecurity_utilities/lib/machserver.cpp b/OSX/libsecurity_utilities/lib/machserver.cpp index 82434ef2..b2f2b775 100644 --- a/OSX/libsecurity_utilities/lib/machserver.cpp +++ b/OSX/libsecurity_utilities/lib/machserver.cpp @@ -89,13 +89,13 @@ MachServer::~MachServer() // void MachServer::add(Port receiver) { - SECURITY_MACHSERVER_PORT_ADD(receiver); + secinfo("machserver", "port add: %d", receiver.port()); mPortSet += receiver; } void MachServer::remove(Port receiver) { - SECURITY_MACHSERVER_PORT_REMOVE(receiver); + secinfo("machserver", "port remove: %d", receiver.port()); mPortSet -= receiver; } @@ -143,9 +143,9 @@ void MachServer::run(mach_msg_size_t maxSize, mach_msg_options_t options) highestWorkerCount = 1; // run server loop in initial (immortal) thread - SECURITY_MACHSERVER_START_THREAD(false); + secinfo("machserver", "start thread"); runServerThread(false); - SECURITY_MACHSERVER_END_THREAD(false); + secinfo("machserver", "end thread"); // primary server thread exited somehow (not currently possible) assert(false); @@ -192,7 +192,7 @@ void MachServer::runServerThread(bool doTimeout) Time::Absolute rightNow = Time::now(); if (rightNow >= nextCheckTime) { // reaping period complete; process UInt32 idlers = leastIdleWorkers; - SECURITY_MACHSERVER_REAP(workerCount, idlers); + secinfo("machserver", "reaping workers: %d %d", (uint32_t) workerCount, (uint32_t) idlers); nextCheckTime = rightNow + workerTimeout; leastIdleWorkers = INT_MAX; if (idlers > 1) // multiple idle threads throughout measuring interval... @@ -213,9 +213,7 @@ void MachServer::runServerThread(bool doTimeout) timeout = workerTimeout; } } - if (SECURITY_MACHSERVER_RECEIVE_ENABLED()) - SECURITY_MACHSERVER_RECEIVE(indefinite ? 0 : timeout.seconds()); - + // receive next IPC request (or wait for timeout) mach_msg_return_t mr = indefinite ? mach_msg_overwrite(bufRequest, @@ -235,7 +233,7 @@ void MachServer::runServerThread(bool doTimeout) // process received request message below break; default: - SECURITY_MACHSERVER_RECEIVE_ERROR(mr); + secinfo("machserver", "received error: %d", mr); continue; } @@ -248,7 +246,7 @@ void MachServer::runServerThread(bool doTimeout) } else { // normal request message StLock _(*this); - SECURITY_MACHSERVER_BEGIN(bufRequest.localPort(), bufRequest.msgId()); + secinfo("machserver", "begin request: %d, %d", bufRequest.localPort().port(), bufRequest.msgId()); // try subsidiary handlers first bool handled = false; @@ -263,7 +261,7 @@ void MachServer::runServerThread(bool doTimeout) handle(bufRequest, bufReply); } - SECURITY_MACHSERVER_END(); + secinfo("machserver", "end request"); } // process reply generated by handler @@ -303,7 +301,7 @@ void MachServer::runServerThread(bool doTimeout) case MACH_MSG_SUCCESS: break; default: - SECURITY_MACHSERVER_SEND_ERROR(mr, bufReply.remotePort()); + secinfo("machserver", "send error: %d %d", mr, bufReply.remotePort().port()); bufReply.destroy(); break; } @@ -371,7 +369,7 @@ void MachServer::releaseWhenDone(Allocator &alloc, void *memory) if (memory) { set &releaseSet = perThread().deferredAllocations; assert(releaseSet.find(Allocation(memory, alloc)) == releaseSet.end()); - SECURITY_MACHSERVER_ALLOC_REGISTER(memory, &alloc); + secinfo("machserver", "allocing register %p with alloc %p", memory, &alloc); releaseSet.insert(Allocation(memory, alloc)); } } @@ -388,8 +386,8 @@ void MachServer::releaseDeferredAllocations() { set &releaseSet = perThread().deferredAllocations; for (set::iterator it = releaseSet.begin(); it != releaseSet.end(); it++) { - SECURITY_MACHSERVER_ALLOC_RELEASE(it->addr, it->allocator); - + secinfo("machserver", "releasing alloc at %p with %p", it->addr, it->allocator); + // before we release the deferred allocation, zap it so that secrets aren't left in memory size_t memSize = malloc_size(it->addr); bzero(it->addr, memSize); @@ -464,12 +462,12 @@ void MachServer::LoadThread::action() // register the worker thread and go server.addThread(this); try { - SECURITY_MACHSERVER_START_THREAD(true); + secinfo("machserver", "start thread"); server.runServerThread(true); - SECURITY_MACHSERVER_END_THREAD(false); + secinfo("machserver", "end thread"); } catch (...) { // fell out of server loop by error. Let the thread go quietly - SECURITY_MACHSERVER_END_THREAD(true); + secinfo("machserver", "end thread (due to error)"); } server.removeThread(this); } @@ -515,7 +513,7 @@ bool MachServer::processTimer() return false; // nothing (more) to be done now } // drop lock; work has been retrieved try { - SECURITY_MACHSERVER_TIMER_START(top, top->longTerm(), Time::now().internalForm()); + secinfo("machserver", "timer start: %p, %d, %f", top, top->longTerm(), Time::now().internalForm()); StLock _t(*top); if (top->longTerm()) { @@ -524,9 +522,9 @@ bool MachServer::processTimer() } else { top->action(); } - SECURITY_MACHSERVER_TIMER_END(false); + secinfo("machserver", "timer end (false)"); } catch (...) { - SECURITY_MACHSERVER_TIMER_END(true); + secinfo("machserver", "timer end (true)"); } return true; } diff --git a/OSX/libsecurity_utilities/lib/memutils.h b/OSX/libsecurity_utilities/lib/memutils.h index 035aee1c..20333873 100644 --- a/OSX/libsecurity_utilities/lib/memutils.h +++ b/OSX/libsecurity_utilities/lib/memutils.h @@ -51,7 +51,7 @@ static const size_t systemAlignment = 4; // Get the local alignment for a type, as used by the acting compiler. // template -inline size_t alignof() { struct { char c; T t; } s; return sizeof(s) - sizeof(T); } +inline int alignof() { struct { char c; T t; } s; return sizeof(s) - sizeof(T); } // diff --git a/OSX/libsecurity_utilities/lib/muscle++.cpp b/OSX/libsecurity_utilities/lib/muscle++.cpp index d1841472..575edce6 100644 --- a/OSX/libsecurity_utilities/lib/muscle++.cpp +++ b/OSX/libsecurity_utilities/lib/muscle++.cpp @@ -39,7 +39,8 @@ namespace Muscle { // Error::Error(MSC_RV err) : error(err) { - SECURITY_EXCEPTION_THROW_OTHER(this, err, (char *)"muscle"); + SECURITY_EXCEPTION_THROW_OTHER(this, err, (char *)"muscle"); + secnotice("security_exception", "muscle: %d", err); } @@ -97,7 +98,7 @@ void Connection::open(const PCSC::ReaderState &reader, unsigned share) // establish Muscle-level connection to card Error::check(::MSCEstablishConnection(&info, share, NULL, 0, this)); mIsOpen = true; - secdebug("muscle", "%p opened %s", this, info.slotName); + secinfo("muscle", "%p opened %s", this, info.slotName); // pull initial status updateStatus(); @@ -106,7 +107,7 @@ void Connection::open(const PCSC::ReaderState &reader, unsigned share) void Connection::close() { if (mIsOpen) { - secdebug("muscle", "%p closing", this); + secinfo("muscle", "%p closing", this); Error::check(::MSCReleaseConnection(this, SCARD_LEAVE_CARD)); mIsOpen = false; } @@ -117,14 +118,14 @@ void Connection::begin(Transaction *trans) { assert(!mCurrentTransaction); Error::check(::MSCBeginTransaction(this)); - secdebug("muscle", "%p start transaction %p", this, trans); + secinfo("muscle", "%p start transaction %p", this, trans); mCurrentTransaction = trans; } void Connection::end(Transaction *trans) { assert(trans == mCurrentTransaction); - secdebug("muscle", "%p end transaction %p", this, trans); + secinfo("muscle", "%p end transaction %p", this, trans); Error::check(::MSCEndTransaction(this, SCARD_LEAVE_CARD)); mCurrentTransaction = NULL; } diff --git a/OSX/libsecurity_utilities/lib/osxcode.cpp b/OSX/libsecurity_utilities/lib/osxcode.cpp index 51c01007..7b464a01 100644 --- a/OSX/libsecurity_utilities/lib/osxcode.cpp +++ b/OSX/libsecurity_utilities/lib/osxcode.cpp @@ -59,7 +59,7 @@ RefPointer OSXCode::main() if (const char *contents = strstr(cpath, "/Contents/MacOS/")) if (contents + 15 == slash) return new Bundle(path.substr(0, contents-cpath).c_str()); - secdebug("bundle", "OSXCode::main(%s) not recognized as bundle (treating as tool)", cpath); + secinfo("bundle", "OSXCode::main(%s) not recognized as bundle (treating as tool)", cpath); } return new ExecutableTool(path.c_str()); } @@ -124,7 +124,7 @@ Bundle::Bundle(const char *path, const char *execPath /* = NULL */) { if (execPath) // caller knows that one; set it mExecutablePath = execPath; - secdebug("bundle", "%p Bundle from path %s(%s)", this, path, executablePath().c_str()); + secinfo("bundle", "%p Bundle from path %s(%s)", this, path, executablePath().c_str()); } Bundle::Bundle(CFBundleRef bundle, const char *root /* = NULL */) @@ -133,7 +133,7 @@ Bundle::Bundle(CFBundleRef bundle, const char *root /* = NULL */) assert(bundle); CFRetain(bundle); mPath = root ? root : cfStringRelease(CFBundleCopyBundleURL(mBundle)); - secdebug("bundle", "%p Bundle from bundle %p(%s)", this, bundle, mPath.c_str()); + secinfo("bundle", "%p Bundle from bundle %p(%s)", this, bundle, mPath.c_str()); } @@ -156,7 +156,7 @@ string Bundle::executablePath() const CFBundleRef Bundle::cfBundle() const { if (!mBundle) { - secdebug("bundle", "instantiating CFBundle for %s", mPath.c_str()); + secinfo("bundle", "instantiating CFBundle for %s", mPath.c_str()); CFRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)mPath.c_str(), mPath.length(), true); if (!url || !(mBundle = CFBundleCreate(NULL, url))) @@ -214,12 +214,12 @@ void LoadableBundle::load() { if (!CFBundleLoadExecutable(cfBundle())) CFError::throwMe(); - secdebug("bundle", "%p (%s) loaded", this, path().c_str()); + secinfo("bundle", "%p (%s) loaded", this, path().c_str()); } void LoadableBundle::unload() { - secdebug("bundle", "%p (%s) unloaded", this, path().c_str()); + secinfo("bundle", "%p (%s) unloaded", this, path().c_str()); CFBundleUnloadExecutable(cfBundle()); } diff --git a/OSX/libsecurity_utilities/lib/pcsc++.cpp b/OSX/libsecurity_utilities/lib/pcsc++.cpp index 0a79de0e..8c5e409d 100644 --- a/OSX/libsecurity_utilities/lib/pcsc++.cpp +++ b/OSX/libsecurity_utilities/lib/pcsc++.cpp @@ -59,7 +59,8 @@ inline void decode(vector &names, const vector &buffer, size_t siz // Error::Error(unsigned long err) : error(err) { - SECURITY_EXCEPTION_THROW_PCSC(this, (unsigned int)err); + SECURITY_EXCEPTION_THROW_PCSC(this, (unsigned int)err); + secnotice("security_exception", "pcsc: %d", (unsigned int) err); } @@ -158,11 +159,11 @@ void Session::open() try { Error::check(::SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &mContext)); mIsOpen = true; - secdebug("pcsc", "context opened"); + secinfo("pcsc", "context opened"); } catch (const Error &err) { if (err.error == SCARD_F_INTERNAL_ERROR) { - secdebug("pcsc", "got internal error; assuming pcscd absent; context not ready"); + secinfo("pcsc", "got internal error; assuming pcscd absent; context not ready"); return; } } @@ -176,11 +177,11 @@ void Session::close() try { if (mContext) Error::check(SCardReleaseContext(mContext)); - secdebug("pcsc", "context closed"); + secinfo("pcsc", "context closed"); } catch (const Error &err) { if (err.error == SCARD_F_INTERNAL_ERROR) { - secdebug("pcsc", "got internal error; assuming pcscd absent; context not ready"); + secinfo("pcsc", "got internal error; assuming pcscd absent; context not ready"); return; } } @@ -203,18 +204,23 @@ bool Session::check(long rc) void Session::listReaders(vector &readers, const char *groups) { - uint32_t size = 0; - if (check(::SCardListReaders(mContext, groups, NULL, &size))) + uint32_t size = uint32_t(mReaderBuffer.size()); + for (;;) { - mReaderBuffer.resize(size); - if (check(::SCardListReaders(mContext, groups, &mReaderBuffer[0], &size))) - { - decode(readers, mReaderBuffer, size); - return; + int32_t rc = ::SCardListReaders(mContext, groups, &mReaderBuffer[0], &size); + switch (rc) { + case SCARD_S_SUCCESS: + if (size <= mReaderBuffer.size()) { + decode(readers, mReaderBuffer, size); + return; + } + case SCARD_E_INSUFFICIENT_BUFFER: + mReaderBuffer.resize(size); + break; + default: + Error::throwMe(rc); } } - - readers.clear(); // treat as success (returning zero readers) } @@ -282,7 +288,7 @@ void Card::disconnect(unsigned long disposition) { if (mTransactionNestLevel > 0) { - secdebug("pcsc", "%p: disconnect, dropping: %d transactions", this, mTransactionNestLevel); + secinfo("pcsc", "%p: disconnect, dropping: %d transactions", this, mTransactionNestLevel); mTransactionNestLevel = 0; } @@ -297,7 +303,7 @@ Card::checkReset(unsigned int rv) { if (rv == SCARD_W_RESET_CARD) { - secdebug("pcsc", "%p: card reset during pcsc call, we're disconnected", this); + secinfo("pcsc", "%p: card reset during pcsc call, we're disconnected", this); didDisconnect(); } Error::check(rv); @@ -321,7 +327,7 @@ Card::transmit(const unsigned char *pbSendBuffer, size_t cbSendLength, { if (mConnectedState == kDisconnected) { - secdebug("pcsc", "%p: transmit after disconnect, reconnecting", this); + secinfo("pcsc", "%p: transmit after disconnect, reconnecting", this); reconnect(); } @@ -342,25 +348,25 @@ void Card::begin() { if (mConnectedState == kDisconnected) { - secdebug("pcsc", "%p: begin transaction after disconnect, reconnecting", this); + secinfo("pcsc", "%p: begin transaction after disconnect, reconnecting", this); reconnect(); } checkReset(::SCardBeginTransaction(mHandle)); } mTransactionNestLevel++; - secdebug("pcsc", "%p begin transaction: %d", this, mTransactionNestLevel); + secinfo("pcsc", "%p begin transaction: %d", this, mTransactionNestLevel); } void Card::end(unsigned long disposition) { // Only the last transaction ended is sent to PCSC - secdebug("pcsc", "%p end transaction: %d", this, mTransactionNestLevel); + secinfo("pcsc", "%p end transaction: %d", this, mTransactionNestLevel); if (disposition == SCARD_RESET_CARD) { if (mConnectedState == kDisconnected) { - secdebug("pcsc", "%p: end transaction after disconnect, reconnecting to reset card", this); + secinfo("pcsc", "%p: end transaction after disconnect, reconnecting to reset card", this); reconnect(); } @@ -373,7 +379,7 @@ void Card::end(unsigned long disposition) if (mTransactionNestLevel == 0) { if (mConnectedState == kDisconnected) - secdebug("pcsc", "%p: end transaction while disconnected ignored", this); + secinfo("pcsc", "%p: end transaction while disconnected ignored", this); else { checkReset(::SCardEndTransaction(mHandle, (uint32_t)disposition)); diff --git a/OSX/libsecurity_utilities/lib/powerwatch.cpp b/OSX/libsecurity_utilities/lib/powerwatch.cpp index 1e3037b9..239f1acb 100644 --- a/OSX/libsecurity_utilities/lib/powerwatch.cpp +++ b/OSX/libsecurity_utilities/lib/powerwatch.cpp @@ -69,24 +69,22 @@ IOPowerWatcher::iopmcallback(void * param, { IOPowerWatcher *me = (IOPowerWatcher *)param; - if (SECURITY_DEBUG_LOG_ENABLED()) { - secdebug("powerwatch", "powerstates"); + secnotice("powerwatch", "powerstates"); if (capabilities & kIOPMSystemPowerStateCapabilityDisk) - secdebug("powerwatch", "disk"); + secnotice("powerwatch", "disk"); if (capabilities & kIOPMSystemPowerStateCapabilityNetwork) - secdebug("powerwatch", "net"); + secnotice("powerwatch", "net"); if (capabilities & kIOPMSystemPowerStateCapabilityAudio) - secdebug("powerwatch", "audio"); + secnotice("powerwatch", "audio"); if (capabilities & kIOPMSystemPowerStateCapabilityVideo) - secdebug("powerwatch", "video"); - } + secnotice("powerwatch", "video"); /* if cpu and no display -> in DarkWake */ if ((capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)) == kIOPMSystemPowerStateCapabilityCPU) { - secdebug("powerwatch", "enter DarkWake"); + secnotice("powerwatch", "enter DarkWake"); me->mInDarkWake = true; } else if (me->mInDarkWake) { - secdebug("powerwatch", "exit DarkWake"); + secnotice("powerwatch", "exit DarkWake"); me->mInDarkWake = false; } @@ -177,43 +175,43 @@ void IOPowerWatcher::ioCallback(void *refCon, io_service_t service, enum { allow, refuse, ignore } reaction; switch (messageType) { case kIOMessageSystemWillSleep: - secdebug("powerwatch", "system will sleep"); + secnotice("powerwatch", "system will sleep"); me->systemWillSleep(); reaction = allow; break; case kIOMessageSystemHasPoweredOn: - secdebug("powerwatch", "system has powered on"); + secnotice("powerwatch", "system has powered on"); me->systemIsWaking(); reaction = ignore; break; case kIOMessageSystemWillPowerOff: - secdebug("powerwatch", "system will power off"); + secnotice("powerwatch", "system will power off"); me->systemWillPowerDown(); reaction = allow; break; case kIOMessageSystemWillNotPowerOff: - secdebug("powerwatch", "system will not power off"); + secnotice("powerwatch", "system will not power off"); reaction = ignore; break; case kIOMessageCanSystemSleep: - secdebug("powerwatch", "can system sleep"); + secnotice("powerwatch", "can system sleep"); reaction = allow; break; case kIOMessageSystemWillNotSleep: - secdebug("powerwatch", "system will not sleep"); + secnotice("powerwatch", "system will not sleep"); reaction = ignore; break; case kIOMessageCanSystemPowerOff: - secdebug("powerwatch", "can system power off"); + secnotice("powerwatch", "can system power off"); reaction = allow; break; case kIOMessageSystemWillPowerOn: - secdebug("powerwatch", "system will power on"); + secnotice("powerwatch", "system will power on"); me->systemWillPowerOn(); reaction = ignore; break; default: - secdebug("powerwatch", + secnotice("powerwatch", "type 0x%x message received (ignored)", messageType); reaction = ignore; break; @@ -222,15 +220,15 @@ void IOPowerWatcher::ioCallback(void *refCon, io_service_t service, // handle acknowledgments switch (reaction) { case allow: - secdebug("powerwatch", "calling IOAllowPowerChange"); + secnotice("powerwatch", "calling IOAllowPowerChange"); IOAllowPowerChange(me->mKernelPort, long(argument)); break; case refuse: - secdebug("powerwatch", "calling IOCancelPowerChange"); + secnotice("powerwatch", "calling IOCancelPowerChange"); IOCancelPowerChange(me->mKernelPort, long(argument)); break; case ignore: - secdebug("powerwatch", "sending no response"); + secnotice("powerwatch", "sending no response"); break; } } diff --git a/OSX/libsecurity_utilities/lib/refcount.h b/OSX/libsecurity_utilities/lib/refcount.h index 677376c5..945488f1 100644 --- a/OSX/libsecurity_utilities/lib/refcount.h +++ b/OSX/libsecurity_utilities/lib/refcount.h @@ -49,14 +49,15 @@ namespace Security { // way to "demand copy" a RefCount subclass. Trust me; it's been tried. Don't. // -#if !defined(DEBUG_REFCOUNTS) -# define DEBUG_REFCOUNTS 1 -#endif +// Uncomment to debug refcounts +//# define DEBUG_REFCOUNTS 1 #if DEBUG_REFCOUNTS -# define RCDEBUG(_kind, _args...) SECURITY_DEBUG_REFCOUNT_##_kind((void *)this, ##_args) +# define RCDEBUG_CREATE() secinfo("refcount", "%p: CREATE", this) +# define RCDEBUG(_kind, n) secinfo("refcount", "%p: %s: %d", this, #_kind, n) #else -# define RCDEBUG(kind) /* nothing */ +# define RCDEBUG_CREATE() /* nothing */ +# define RCDEBUG(kind, _args...) /* nothing */ #endif @@ -65,7 +66,7 @@ namespace Security { // class RefCount { public: - RefCount() : mRefCount(0) { RCDEBUG(CREATE); } + RefCount() : mRefCount(0) { RCDEBUG_CREATE(); } protected: template friend class RefPointer; diff --git a/OSX/libsecurity_utilities/lib/seccfobject.cpp b/OSX/libsecurity_utilities/lib/seccfobject.cpp index 142a2730..11220f45 100644 --- a/OSX/libsecurity_utilities/lib/seccfobject.cpp +++ b/OSX/libsecurity_utilities/lib/seccfobject.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include SecPointerBase::SecPointerBase(const SecPointerBase& p) { @@ -40,20 +40,6 @@ SecPointerBase::SecPointerBase(const SecPointerBase& p) } - - -static void CheckForRelease(SecCFObject* ptr) -{ - CFTypeRef tr = ptr->operator CFTypeRef(); - CFIndex retainCount = CFGetRetainCount(tr); - if (retainCount == 1 || retainCount == -1) - { - ptr->aboutToDestruct(); - } -} - - - SecPointerBase::SecPointerBase(SecCFObject *p) { if (p && !p->isNew()) @@ -69,7 +55,6 @@ SecPointerBase::~SecPointerBase() { if (ptr) { - CheckForRelease(ptr); CFRelease(ptr->operator CFTypeRef()); } } @@ -85,7 +70,6 @@ SecPointerBase& SecPointerBase::operator = (const SecPointerBase& p) } if (ptr) { - CheckForRelease(ptr); CFRelease(ptr->operator CFTypeRef()); } ptr = p.ptr; @@ -102,7 +86,6 @@ void SecPointerBase::assign(SecCFObject * p) } if (ptr) { - CheckForRelease(ptr); CFRelease(ptr->operator CFTypeRef()); } ptr = p; @@ -114,7 +97,6 @@ void SecPointerBase::copy(SecCFObject * p) { if (ptr) { - CheckForRelease(ptr); CFRelease(ptr->operator CFTypeRef()); } @@ -153,14 +135,10 @@ SecCFObject::allocate(size_t size, const CFClass &cfclass) throw(std::bad_alloc) if (p == NULL) throw std::bad_alloc(); - ((SecRuntimeBase*) p)->isNew = true; + atomic_flag_clear(&((SecRuntimeBase*) p)->isOld); void *q = ((u_int8_t*) p) + kAlignedRuntimeSize; - if (SECURITY_DEBUG_SEC_CREATE_ENABLED()) { - const CFRuntimeClass *rtc = _CFRuntimeGetClassWithTypeID(cfclass.typeID); - SECURITY_DEBUG_SEC_CREATE(q, rtc ? (char *)rtc->className : NULL, (unsigned int)cfclass.typeID); - } return q; } @@ -212,7 +190,7 @@ uint32_t SecCFObject::updateRetainCount(intptr_t direction, uint32_t *oldCount) SecCFObject::~SecCFObject() { - SECURITY_DEBUG_SEC_DESTROY(this); + //SECURITY_DEBUG_SEC_DESTROY(this); } bool @@ -257,7 +235,7 @@ SecCFObject::aboutToDestruct() Mutex* -SecCFObject::getMutexForObject() +SecCFObject::getMutexForObject() const { return NULL; // we only worry about descendants of KeychainImpl and ItemImpl } diff --git a/OSX/libsecurity_utilities/lib/seccfobject.h b/OSX/libsecurity_utilities/lib/seccfobject.h index 2717d755..26c39288 100644 --- a/OSX/libsecurity_utilities/lib/seccfobject.h +++ b/OSX/libsecurity_utilities/lib/seccfobject.h @@ -29,15 +29,13 @@ #include #include #include "threading.h" +#include namespace Security { class CFClass; -#define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ -\ -void *operator new(size_t size) throw(std::bad_alloc) \ -{ return SecCFObject::allocate(size, CFCLASS); } \ +#define SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR) \ \ operator APIPTR() const \ { return (APIPTR)(this->operator CFTypeRef()); } \ @@ -45,7 +43,16 @@ operator APIPTR() const \ OBJTYPE *retain() \ { SecCFObject::handle(true); return this; } \ APIPTR handle(bool retain = true) \ -{ return (APIPTR)SecCFObject::handle(retain); } \ +{ return (APIPTR)SecCFObject::handle(retain); } + +#define SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \ +SECCFFUNCTIONS_BASE(OBJTYPE, APIPTR)\ +\ +void *operator new(size_t size) throw(std::bad_alloc) \ +{ return SecCFObject::allocate(size, CFCLASS); } + +#define SECCFFUNCTIONS(OBJTYPE, APIPTR, ERRCODE, CFCLASS) \ +SECCFFUNCTIONS_CREATABLE(OBJTYPE, APIPTR, CFCLASS) \ \ static OBJTYPE *required(APIPTR ptr) \ { if (OBJTYPE *p = dynamic_cast(SecCFObject::required(ptr, ERRCODE))) \ @@ -60,7 +67,7 @@ static OBJTYPE *optional(APIPTR ptr) \ struct SecRuntimeBase: CFRuntimeBase { - bool isNew; + atomic_flag isOld; }; class SecCFObject @@ -79,9 +86,9 @@ public: bool isNew() { SecRuntimeBase *base = reinterpret_cast(reinterpret_cast(this) - kAlignedRuntimeSize); - bool isNew = base->isNew; - base->isNew = false; - return isNew; + + // atomic flags start clear, and like to go high. + return !atomic_flag_test_and_set(&(base->isOld)); } static SecCFObject *optional(CFTypeRef) throw(); @@ -94,7 +101,7 @@ public: uint32_t getRetainCount() {return updateRetainCount(0, NULL);} static void operator delete(void *object) throw(); - operator CFTypeRef() const throw() + virtual operator CFTypeRef() const throw() { return reinterpret_cast(reinterpret_cast(this) - kAlignedRuntimeSize); } @@ -107,7 +114,7 @@ public: virtual CFStringRef copyFormattingDesc(CFDictionaryRef dict); virtual CFStringRef copyDebugDesc(); virtual void aboutToDestruct(); - virtual Mutex* getMutexForObject(); + virtual Mutex* getMutexForObject() const; virtual bool mayDelete(); }; diff --git a/OSX/libsecurity_utilities/lib/selector.cpp b/OSX/libsecurity_utilities/lib/selector.cpp index e3f115a7..599e4b64 100644 --- a/OSX/libsecurity_utilities/lib/selector.cpp +++ b/OSX/libsecurity_utilities/lib/selector.cpp @@ -60,7 +60,7 @@ void Selector::add(int fd, Client &client, Type type) assert(!client.isActive()); // one Selector per client, and no re-adding assert(fd >= 0); - secdebug("selector", "add client %p fd %d type=%d", &client, fd, type); + secinfo("selector", "add client %p fd %d type=%d", &client, fd, type); // grow FDSets if needed unsigned int pos = fd / NFDBITS; @@ -99,7 +99,7 @@ void Selector::remove(int fd) assert(it != clientMap.end()); assert(it->second->mSelector == this); - secdebug("selector", "remove client %p fd %d", it->second, fd); + secinfo("selector", "remove client %p fd %d", it->second, fd); // remove from FDSets set(fd, none); @@ -129,7 +129,7 @@ void Selector::set(int fd, Type type) inSet.set(fd, type & input); outSet.set(fd, type & output); errSet.set(fd, type & critical); - secdebug("selector", "fd %d notifications 0x%x", fd, type); + secinfo("selector", "fd %d notifications 0x%x", fd, type); } @@ -156,7 +156,7 @@ void Selector::operator () (Time::Absolute stopTime) void Selector::singleStep(Time::Interval maxWait) { assert(!clientMap.empty()); - secdebug("selector", "select(%d) [%d-%d] for %ld clients", + secinfo("selector", "select(%d) [%d-%d] for %ld clients", fdMax + 1, fdMin, fdMax, clientMap.size()); for (;;) { // pseudo-loop - only retries struct timeval duration = maxWait.timevalInterval(); @@ -172,13 +172,13 @@ void Selector::singleStep(Time::Interval maxWait) case -1: // error if (errno == EINTR) continue; - secdebug("selector", "select failed: errno=%d", errno); + secinfo("selector", "select failed: errno=%d", errno); UnixError::throwMe(); case 0: // no events - secdebug("selector", "select returned nothing"); + secinfo("selector", "select returned nothing"); return; default: // some events - secdebug("selector", "%d pending descriptors", hits); + secinfo("selector", "%d pending descriptors", hits); //@@@ This could be optimized as a word-merge scan. //@@@ The typical case doesn't benefit from this though, though browsers might //@@@ and integrated servers definitely would. @@ -188,7 +188,7 @@ void Selector::singleStep(Time::Interval maxWait) if (outSet[fd]) types |= output; if (errSet[fd]) types |= critical; if (types) { - secdebug("selector", "notify fd %d client %p type %d", + secinfo("selector", "notify fd %d client %p type %d", fd, clientMap[fd], types); clientMap[fd]->notify(fd, types); hits--; diff --git a/OSX/libsecurity_utilities/lib/simpleprefs.cpp b/OSX/libsecurity_utilities/lib/simpleprefs.cpp index 105f20b7..c4d09774 100644 --- a/OSX/libsecurity_utilities/lib/simpleprefs.cpp +++ b/OSX/libsecurity_utilities/lib/simpleprefs.cpp @@ -39,7 +39,7 @@ #include #include -#define prefsDebug(args...) secdebug("simpleprefs", ## args) +#define prefsDebug(args...) secinfo("simpleprefs", ## args) #define kSecUserPrefsDir "Library/Preferences" /* relative to $HOME */ #define kSecSystemPrefsDir "/Library/Preferences" diff --git a/OSX/libsecurity_utilities/lib/socks++4.cpp b/OSX/libsecurity_utilities/lib/socks++4.cpp index 1f6908b0..20e2e9bb 100644 --- a/OSX/libsecurity_utilities/lib/socks++4.cpp +++ b/OSX/libsecurity_utilities/lib/socks++4.cpp @@ -47,7 +47,7 @@ void Server::connect(SocksClientSocket &me, const IPSockAddress &peer) request.send(me, "nobody"); (Message(me)); // read and check reply message me.mPeerAddress = peer; // best guess, Mr. Sulu - secdebug("socks", "%d socks4 connected to %s", me.fd(), string(peer).c_str()); + secinfo("socks", "%d socks4 connected to %s", me.fd(), string(peer).c_str()); } void Server::connect(SocksClientSocket &me, const Host &host, IPPort port) @@ -77,7 +77,7 @@ void Server::bind(SocksServerSocket &me, const IPAddress &peer, IPPort port) request.send(me, "nobody"); Message reply(me); me.mLocalAddress = reply.address().defaults(mServerAddress.address()); - secdebug("socks", "%d socks4 bound to %s", me.fd(), string(me.mLocalAddress).c_str()); + secinfo("socks", "%d socks4 bound to %s", me.fd(), string(me.mLocalAddress).c_str()); } void Server::receive(SocksServerSocket &me, SocksClientSocket &receiver) @@ -85,7 +85,7 @@ void Server::receive(SocksServerSocket &me, SocksClientSocket &receiver) Message reply(me); receiver.setFd(me.fd(), me.mLocalAddress, reply.address()); me.clear(); // clear our own (don't close on destruction) - secdebug("socks", "%d socks4 inbound connect", receiver.fd()); + secinfo("socks", "%d socks4 inbound connect", receiver.fd()); } diff --git a/OSX/libsecurity_utilities/lib/socks++5.cpp b/OSX/libsecurity_utilities/lib/socks++5.cpp index 0aa6cc31..0f6856b0 100644 --- a/OSX/libsecurity_utilities/lib/socks++5.cpp +++ b/OSX/libsecurity_utilities/lib/socks++5.cpp @@ -41,13 +41,13 @@ void Server::open(Socket &s, Support &my) { s.open(SOCK_STREAM); s.connect(my.mServer->address()); - secdebug("socks", "%d connected to server %s", s.fd(), string(my.mServer->address()).c_str()); + secinfo("socks", "%d connected to server %s", s.fd(), string(my.mServer->address()).c_str()); Byte request[] = { 5, 1, socksAuthPublic }; s.write(request, sizeof(request)); Byte reply[2]; s.read(reply, sizeof(reply)); if (reply[0] != 5 || reply[1] != socksAuthPublic) { - secdebug("socks", "%d server failed (v%d auth=%d)", s.fd(), reply[0], reply[1]); + secinfo("socks", "%d server failed (v%d auth=%d)", s.fd(), reply[0], reply[1]); s.close(); UnixError::throwMe(EPROTONOSUPPORT); } @@ -61,7 +61,7 @@ void Server::connect(SocksClientSocket &me, const IPSockAddress &peer) Message reply(me); me.mLocalAddress = reply.address(); me.mPeerAddress = peer; - secdebug("socks", "%d socks connected to %s", me.fd(), string(peer).c_str()); + secinfo("socks", "%d socks connected to %s", me.fd(), string(peer).c_str()); } void Server::connect(SocksClientSocket &me, const Host &host, IPPort port) @@ -88,7 +88,7 @@ void Server::connect(SocksClientSocket &me, const Host &host, IPPort port) Message reply(me); me.mLocalAddress = reply.address(); //me.mPeerAddress = not provided by Socks5 protocol; - secdebug("socks", "%d socks connected to %s", me.fd(), host.name().c_str()); + secinfo("socks", "%d socks connected to %s", me.fd(), host.name().c_str()); #endif } @@ -101,7 +101,7 @@ void Server::bind(SocksServerSocket &me, const IPAddress &peer, IPPort port) Message reply(me); me.mLocalAddress = reply.address(); //me.mPeerAddress not available yet; - secdebug("socks", "%d socks bound to %s", me.fd(), string(me.mLocalAddress).c_str()); + secinfo("socks", "%d socks bound to %s", me.fd(), string(me.mLocalAddress).c_str()); } void Server::receive(SocksServerSocket &me, SocksClientSocket &receiver) @@ -109,7 +109,7 @@ void Server::receive(SocksServerSocket &me, SocksClientSocket &receiver) Message reply(me); receiver.setFd(me.fd(), me.mLocalAddress, reply.address()); me.clear(); // clear our own (don't close on destruction) - secdebug("socks", "%d socks received from %s", receiver.fd(), string(reply.address()).c_str()); + secinfo("socks", "%d socks received from %s", receiver.fd(), string(reply.address()).c_str()); } diff --git a/OSX/libsecurity_utilities/lib/sqlite++.cpp b/OSX/libsecurity_utilities/lib/sqlite++.cpp index 5eaf3a36..4a5e05e8 100644 --- a/OSX/libsecurity_utilities/lib/sqlite++.cpp +++ b/OSX/libsecurity_utilities/lib/sqlite++.cpp @@ -52,9 +52,10 @@ void Error::check(int err) Error::Error(Database &db) : error(db.errcode()), message(db.errmsg()) { - SECURITY_EXCEPTION_THROW_SQLITE(this, error, (char*)message.c_str()); + SECURITY_EXCEPTION_THROW_SQLITE(this, error, (char*)message.c_str()); + secnotice("security_exception", "sqlite: %d %s",error, (char*)message.c_str()); } - + void Error::throwMe(int err) { throw Error(err); diff --git a/OSX/libsecurity_utilities/lib/superblob.h b/OSX/libsecurity_utilities/lib/superblob.h index e6b8edc8..ba7a5811 100644 --- a/OSX/libsecurity_utilities/lib/superblob.h +++ b/OSX/libsecurity_utilities/lib/superblob.h @@ -40,6 +40,7 @@ public: }; bool validateBlob(size_t maxSize = 0) const; + bool strictValidateBlob(size_t maxSize = 0) const; unsigned count() const { return mCount; } @@ -80,6 +81,34 @@ inline bool SuperBlobCore<_BlobType, _magic, _Type>::validateBlob(size_t maxSize return true; } +struct _SBRange { + size_t base; + size_t end; + _SBRange(size_t b, size_t len) : base(b), end(b+len) { } + bool operator < (const _SBRange& other) const { return this->base < other.base; } +}; + +template +inline bool SuperBlobCore<_BlobType, _magic, _Type>::strictValidateBlob(size_t size /* = 0 */) const +{ + if (!validateBlob(size)) // verifies in-bound sub-blobs + return false; + unsigned count = mCount; + if (count == 0) + return this->length() == sizeof(SuperBlobCore); // nothing in here + + std::vector<_SBRange> ranges; + for (unsigned ix = 0; ix < count; ++ix) + ranges.push_back(_SBRange(mIndex[ix].offset, this->blob(ix)->length())); + sort(ranges.begin(), ranges.end()); + if (ranges[0].base != sizeof(SuperBlobCore) + count * sizeof(Index)) + return false; // start anchor + for (unsigned ix = 1; ix < count; ++ix) + if (ranges[ix].base != ranges[ix-1].end) // nothing in between + return false; + return ranges[count-1].end == this->length(); // end anchor +} + // // A generic SuperBlob ready for use. You still need to specify a magic number. @@ -157,7 +186,7 @@ void SuperBlobCore<_BlobType, _magic, _Type>::Maker::add(Type type, BlobCore *bl { pair r = mPieces.insert(make_pair(type, blob)); if (!r.second) { // already there - secdebug("superblob", "Maker %p replaces type=%d", this, type); + secinfo("superblob", "Maker %p replaces type=%d", this, type); ::free(r.first->second); r.first->second = blob; } @@ -233,7 +262,7 @@ _BlobType *SuperBlobCore<_BlobType, _magic, _Type>::Maker::make() const pc += it->second->length(); n++; } - secdebug("superblob", "Maker %p assembles %ld blob(s) into %p (size=%d)", + secinfo("superblob", "Maker %p assembles %ld blob(s) into %p (size=%d)", this, mPieces.size(), result, total); return result; } diff --git a/OSX/libsecurity_utilities/lib/threading.cpp b/OSX/libsecurity_utilities/lib/threading.cpp index bfe6427c..4146c3f4 100644 --- a/OSX/libsecurity_utilities/lib/threading.cpp +++ b/OSX/libsecurity_utilities/lib/threading.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include // WWDC 2007 thread-crash workaround #include // WWDC 2007 thread-crash workaround @@ -91,6 +92,9 @@ Mutex::Mutex(Type type) Mutex::~Mutex() { int result = pthread_mutex_destroy(&me); + if(result) { + secerror("Probable bug: error destroying Mutex: %d", result); + } check(result); } @@ -156,7 +160,6 @@ void CountingMutex::enter() { lock(); mCount++; - secdebug("cmutex", "%p up to %d", this, mCount); unlock(); } @@ -165,7 +168,6 @@ bool CountingMutex::tryEnter() if (!tryLock()) return false; mCount++; - secdebug("cmutex", "%p up to %d (was try)", this, mCount); unlock(); return true; } @@ -175,14 +177,12 @@ void CountingMutex::exit() lock(); assert(mCount > 0); mCount--; - secdebug("cmutex", "%p down to %d", this, mCount); unlock(); } void CountingMutex::finishEnter() { mCount++; - secdebug("cmutex", "%p finish up to %d", this, mCount); unlock(); } @@ -190,7 +190,6 @@ void CountingMutex::finishExit() { assert(mCount > 0); mCount--; - secdebug("cmutex", "%p finish down to %d", this, mCount); unlock(); } @@ -275,7 +274,7 @@ void Thread::run() syslog(LOG_ERR, "too many failed pthread_create() attempts"); } else - secdebug("thread", "%p created", self.mIdent); + secinfo("thread", "%p created", self.mIdent); } void *Thread::runner(void *arg) @@ -284,9 +283,9 @@ void *Thread::runner(void *arg) // otherwise it will crash if something underneath throws. { Thread *me = static_cast(arg); - secdebug("thread", "%p starting", me->self.mIdent); + secinfo("thread", "%p starting", me->self.mIdent); me->action(); - secdebug("thread", "%p terminating", me->self.mIdent); + secinfo("thread", "%p terminating", me->self.mIdent); delete me; return NULL; } diff --git a/OSX/libsecurity_utilities/lib/threading.h b/OSX/libsecurity_utilities/lib/threading.h index 60168536..34a47636 100644 --- a/OSX/libsecurity_utilities/lib/threading.h +++ b/OSX/libsecurity_utilities/lib/threading.h @@ -248,6 +248,33 @@ protected: bool mActive; }; +// +// This class behaves exactly as StLock above, but accepts a pointer to a mutex instead of a reference. +// If the pointer is NULL, this class does nothing. Otherwise, it behaves as StLock. +// Try not to use this. +// +template +class StMaybeLock { +public: + StMaybeLock(Lock *lck) : me(lck), mActive(false) + { if(me) { (me->*_lock)(); mActive = true; } } + StMaybeLock(Lock *lck, bool option) : me(lck), mActive(option) { } + ~StMaybeLock() { if (me) { if(mActive) (me->*_unlock)(); } else {mActive = false;} } + + bool isActive() const { return mActive; } + void lock() { if(me) { if(!mActive) { (me->*_lock)(); mActive = true; }}} + void unlock() { if(me) { if(mActive) { (me->*_unlock)(); mActive = false; }}} + void release() { if(me) { assert(mActive); mActive = false; } } + + operator const Lock &() const { return me; } + +protected: + Lock *me; + bool mActive; +}; + // Note: if you use the TryRead or TryWrite modes, you must check if you // actually have the lock before proceeding class StReadWriteLock { diff --git a/OSX/libsecurity_utilities/lib/tqueue.h b/OSX/libsecurity_utilities/lib/tqueue.h index 571061c8..f40c2736 100644 --- a/OSX/libsecurity_utilities/lib/tqueue.h +++ b/OSX/libsecurity_utilities/lib/tqueue.h @@ -91,7 +91,7 @@ void ScheduleQueue