From e3d460c9de4426da6c630c3ae3f46173a99f82d8 Mon Sep 17 00:00:00 2001 From: Apple Date: Wed, 13 Jul 2016 22:37:23 +0000 Subject: [PATCH] Security-57337.40.85.tar.gz --- CircleJoinRequested/CircleJoinRequested.m | 2 + ...ple.security.idskeychainsyncingproxy.plist | 2 + ...idskeychainsyncingproxy.entitlements.plist | 4 + ...ple.security.idskeychainsyncingproxy.plist | 2 + ...idskeychainsyncingproxy.entitlements.plist | 4 + .../KNAppDelegate.m | 4 +- OSX/OSX.xcodeproj/project.pbxproj | 69 + .../xcshareddata/xcschemes/World.xcscheme | 14 +- .../xcshareddata/xcschemes/secdtests.xcscheme | 18 +- OSX/authd/authorization.plist | 7 + OSX/authd/engine.c | 9 +- OSX/authd/server.c | 7 +- OSX/codesign_tests/CaspianTests/CaspianTests | 12 +- OSX/lib/security.exp-in | 21 + .../lib/RSA_DSA_utils.cpp | 10 +- .../lib/SSCSPDLSession.cpp | 6 +- .../lib/SSDLSession.cpp | 25 + .../lib/SSDatabase.cpp | 249 +- OSX/libsecurity_apple_cspdl/lib/SSDatabase.h | 32 +- OSX/libsecurity_apple_cspdl/lib/SSKey.cpp | 2 + .../lib/TPCertInfo.cpp | 3 +- .../lib/TPDatabase.cpp | 68 +- OSX/libsecurity_asn1/lib/secasn1d.c | 47 +- OSX/libsecurity_asn1/lib/secasn1e.c | 39 +- OSX/libsecurity_cdsa_client/lib/aclclient.h | 1 + OSX/libsecurity_cdsa_client/lib/dlclient.cpp | 64 + OSX/libsecurity_cdsa_client/lib/dlclient.h | 25 + .../lib/keychainacl.cpp | 18 - OSX/libsecurity_cdsa_client/lib/keychainacl.h | 7 - .../lib/securestorage.cpp | 56 +- .../lib/CSPsession.cpp | 4 + OSX/libsecurity_cdsa_utilities/lib/Schema.h | 1 + OSX/libsecurity_cdsa_utilities/lib/Schema.m4 | 75 + .../lib/acl_any.cpp | 2 +- OSX/libsecurity_cdsa_utilities/lib/acl_any.h | 2 +- .../lib/acl_codesigning.cpp | 2 +- .../lib/acl_codesigning.h | 2 +- .../lib/acl_comment.cpp | 2 +- .../lib/acl_comment.h | 2 +- .../lib/acl_preauth.cpp | 6 +- .../lib/acl_preauth.h | 4 +- .../lib/acl_process.cpp | 2 +- .../lib/acl_process.h | 2 +- .../lib/acl_protectedpw.cpp | 2 +- .../lib/acl_protectedpw.h | 2 +- .../lib/acl_secret.cpp | 2 +- .../lib/acl_secret.h | 2 +- .../lib/acl_threshold.cpp | 4 +- .../lib/acl_threshold.h | 2 +- .../lib/aclsubject.cpp | 4 +- .../lib/aclsubject.h | 28 +- .../lib/cssmaclpod.cpp | 7 +- .../lib/cssmaclpod.h | 1 + .../lib/cssmcred.cpp | 29 + OSX/libsecurity_cdsa_utilities/lib/cssmcred.h | 5 +- OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp | 18 + OSX/libsecurity_cdsa_utilities/lib/cssmdb.h | 10 +- .../lib/objectacl.cpp | 92 +- .../lib/objectacl.h | 14 +- OSX/libsecurity_cdsa_utilities/lib/walkers.h | 1 + OSX/libsecurity_cms/lib/CMSDecoder.cpp | 44 + OSX/libsecurity_cms/lib/CMSEncoder.cpp | 29 +- OSX/libsecurity_cms/lib/CMSEncoder.h | 6 +- OSX/libsecurity_cms/lib/CMSPrivate.h | 24 + OSX/libsecurity_cms/lib/security_cms.exp | 2 + .../libsecurity_cms.xcodeproj/project.pbxproj | 140 + .../regressions/cms-hashagility-test.c | 231 ++ .../regressions/cms-hashagility-test.h | 839 ++++++ .../regressions/cms_regressions.h | 28 + OSX/libsecurity_codesigning/lib/CSCommon.h | 24 + .../lib/CSCommonPriv.h | 22 - OSX/libsecurity_codesigning/lib/Code.cpp | 4 +- .../lib/CodeSigner.cpp | 33 +- OSX/libsecurity_codesigning/lib/CodeSigner.h | 13 +- OSX/libsecurity_codesigning/lib/SecCode.cpp | 4 + OSX/libsecurity_codesigning/lib/SecCode.h | 7 +- .../lib/SecCodeSigner.cpp | 7 - .../lib/SecCodeSigner.h | 3 +- .../lib/SecStaticCode.cpp | 1 + .../lib/SecStaticCode.h | 1 + .../lib/StaticCode.cpp | 200 +- OSX/libsecurity_codesigning/lib/StaticCode.h | 25 +- .../lib/bundlediskrep.cpp | 35 +- .../lib/bundlediskrep.h | 4 +- OSX/libsecurity_codesigning/lib/cdbuilder.cpp | 37 +- OSX/libsecurity_codesigning/lib/cdbuilder.h | 5 +- .../lib/codedirectory.cpp | 89 +- .../lib/codedirectory.h | 27 +- OSX/libsecurity_codesigning/lib/csutilities.h | 30 +- .../lib/diskimagerep.cpp | 255 ++ .../lib/diskimagerep.h | 96 + OSX/libsecurity_codesigning/lib/diskrep.cpp | 14 +- OSX/libsecurity_codesigning/lib/diskrep.h | 21 +- OSX/libsecurity_codesigning/lib/machorep.cpp | 50 +- OSX/libsecurity_codesigning/lib/machorep.h | 3 +- .../lib/opaquewhitelist.cpp | 26 +- OSX/libsecurity_codesigning/lib/policydb.h | 1 + .../lib/policyengine.cpp | 39 +- OSX/libsecurity_codesigning/lib/reqinterp.cpp | 83 +- OSX/libsecurity_codesigning/lib/reqinterp.h | 3 + OSX/libsecurity_codesigning/lib/resources.cpp | 91 +- OSX/libsecurity_codesigning/lib/resources.h | 18 +- .../lib/security_codesigning.exp | 2 + OSX/libsecurity_codesigning/lib/signer.cpp | 220 +- OSX/libsecurity_codesigning/lib/signer.h | 26 +- .../lib/signerutils.cpp | 83 +- OSX/libsecurity_codesigning/lib/signerutils.h | 36 +- .../lib/singlediskrep.cpp | 6 +- .../lib/singlediskrep.h | 4 +- OSX/libsecurity_codesigning/lib/xpcengine.cpp | 24 +- .../project.pbxproj | 10 + OSX/libsecurity_cssm/lib/cssmapple.h | 27 +- OSX/libsecurity_cssm/lib/cssmapplePriv.h | 17 +- OSX/libsecurity_filedb/lib/AppleDatabase.cpp | 27 + OSX/libsecurity_filedb/lib/AppleDatabase.h | 6 +- OSX/libsecurity_keychain/lib/ACL.cpp | 94 +- OSX/libsecurity_keychain/lib/ACL.h | 26 +- OSX/libsecurity_keychain/lib/Access.cpp | 39 +- OSX/libsecurity_keychain/lib/Access.h | 19 +- OSX/libsecurity_keychain/lib/CCallbackMgr.cp | 8 +- OSX/libsecurity_keychain/lib/Certificate.cpp | 32 +- OSX/libsecurity_keychain/lib/Certificate.h | 6 +- OSX/libsecurity_keychain/lib/Globals.cpp | 9 +- OSX/libsecurity_keychain/lib/Globals.h | 3 + OSX/libsecurity_keychain/lib/Item.cpp | 801 +++++- OSX/libsecurity_keychain/lib/Item.h | 45 + OSX/libsecurity_keychain/lib/KCCursor.cpp | 295 +- OSX/libsecurity_keychain/lib/KCCursor.h | 25 +- OSX/libsecurity_keychain/lib/KeyItem.cpp | 257 +- OSX/libsecurity_keychain/lib/KeyItem.h | 5 + OSX/libsecurity_keychain/lib/Keychains.cpp | 415 ++- OSX/libsecurity_keychain/lib/Keychains.h | 69 +- OSX/libsecurity_keychain/lib/SecACL.cpp | 45 +- OSX/libsecurity_keychain/lib/SecAccess.cpp | 11 +- OSX/libsecurity_keychain/lib/SecAccess.h | 4 + .../lib/SecCertificate.cpp | 19 + .../lib/SecCertificatePriv.h | 3 + OSX/libsecurity_keychain/lib/SecFrameworkP.c | 15 - .../lib/SecImportExportCrypto.cpp | 11 +- OSX/libsecurity_keychain/lib/SecItem.cpp | 4 +- .../lib/SecItemConstants.c | 3 + OSX/libsecurity_keychain/lib/SecItemPriv.h | 14 +- OSX/libsecurity_keychain/lib/SecKeychain.cpp | 12 + .../lib/SecKeychainItem.cpp | 26 + .../lib/SecKeychainItemPriv.h | 11 + .../lib/SecKeychainPriv.h | 3 + OSX/libsecurity_keychain/lib/SecPolicy.cpp | 34 +- OSX/libsecurity_keychain/lib/SecPolicyPriv.h | 14 +- .../lib/StorageManager.cpp | 74 +- OSX/libsecurity_keychain/lib/StorageManager.h | 9 +- OSX/libsecurity_keychain/lib/Trust.cpp | 39 +- OSX/libsecurity_keychain/lib/Trust.h | 24 + .../lib/security_keychain.exp | 4 + .../libDER/libDER.xcodeproj/project.pbxproj | 4 + OSX/libsecurity_keychain/libDER/libDER/oids.c | 17 +- .../libDER/libDER/oidsPriv.h | 4 +- .../project.pbxproj | 14 + .../regressions/kc-30-xara-helpers.h | 210 ++ .../regressions/kc-30-xara-item-helpers.h | 299 ++ .../regressions/kc-30-xara-key-helpers.h | 471 ++++ .../regressions/kc-30-xara-upgrade-helpers.h | 2459 +++++++++++++++++ .../regressions/kc-30-xara.c | 657 +++++ .../regressions/kc-42-trust-revocation.c | 414 +-- .../regressions/keychain_regressions.h | 3 +- .../lib/ManifestInternal.cpp | 4 +- OSX/libsecurity_smime/lib/SecCmsBase.h | 53 +- OSX/libsecurity_smime/lib/SecCmsSignerInfo.h | 18 + OSX/libsecurity_smime/lib/cmsattr.c | 1 + OSX/libsecurity_smime/lib/cmssigdata.c | 2 - OSX/libsecurity_smime/lib/cmssiginfo.c | 113 +- OSX/libsecurity_smime/lib/cmstpriv.h | 1 + OSX/libsecurity_smime/lib/secoid.c | 41 +- OSX/libsecurity_smime/lib/security_smime.exp | 2 + .../lib/SecCustomTransform.cpp | 2 - OSX/libsecurity_transform/lib/c++utils.cpp | 2 +- .../lib/CSPDLTransaction.cpp | 100 + .../lib/CSPDLTransaction.h | 77 + OSX/libsecurity_utilities/lib/cfmunge.cpp | 13 +- OSX/libsecurity_utilities/lib/cfutilities.h | 13 +- .../lib/debugging_internal.cpp | 20 + .../lib/debugging_internal.h | 2 + OSX/libsecurity_utilities/lib/exports | 1 + OSX/libsecurity_utilities/lib/hashing.h | 35 +- OSX/libsecurity_utilities/lib/macho++.cpp | 13 + OSX/libsecurity_utilities/lib/macho++.h | 1 + OSX/libsecurity_utilities/lib/memstreams.h | 24 +- OSX/libsecurity_utilities/lib/superblob.h | 17 +- OSX/libsecurity_utilities/lib/threading.cpp | 51 + OSX/libsecurity_utilities/lib/threading.h | 47 +- OSX/libsecurity_utilities/lib/unix++.h | 2 - .../project.pbxproj | 8 + OSX/libsecurityd/lib/ssblob.cpp | 30 + OSX/libsecurityd/lib/ssblob.h | 7 +- OSX/libsecurityd/lib/ssclient.h | 1 + OSX/libsecurityd/lib/transition.cpp | 9 + OSX/libsecurityd/mig/ucsp.defs | 6 + .../regressions.xcodeproj/project.pbxproj | 8 +- OSX/regressions/test/{testenv.c => testenv.m} | 28 +- .../CloudKeychainProxy/CKDKVSProxy.h | 9 +- .../CloudKeychainProxy/CKDKVSProxy.m | 318 ++- .../CloudKeychainProxy/cloudkeychainproxy.m | 6 +- .../IDSKeychainSyncingProxy/IDSProxy.m | 47 +- ...idskeychainsyncingproxy.entitlements.plist | 2 +- .../idskeychainsyncingproxy.m | 11 +- .../Regressions/SOSRegressionUtilities.c | 2 + .../SOSCircle/Regressions/SOSTestDataSource.c | 1 - OSX/sec/SOSCircle/Regressions/SOSTestDevice.c | 4 +- .../Regressions/sc-130-resignationticket.c | 6 - .../SOSCircle/SecureObjectSync/SOSAccount.c | 113 +- .../SOSCircle/SecureObjectSync/SOSAccount.h | 3 + .../SecureObjectSync/SOSAccountBackup.c | 52 +- .../SecureObjectSync/SOSAccountPeers.c | 71 + .../SecureObjectSync/SOSAccountPersistence.c | 4 +- .../SecureObjectSync/SOSAccountPriv.h | 16 + .../SecureObjectSync/SOSBackupSliceKeyBag.c | 37 + .../SecureObjectSync/SOSBackupSliceKeyBag.h | 3 + .../SOSCircle/SecureObjectSync/SOSCircle.c | 15 +- .../SecureObjectSync/SOSCirclePriv.h | 5 + .../SecureObjectSync/SOSCloudCircle.c | 107 + .../SecureObjectSync/SOSCloudCircle.h | 1 + .../SecureObjectSync/SOSCloudCircleInternal.h | 21 + OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c | 5 +- .../SecureObjectSync/SOSDataSource.h | 5 - .../SOSCircle/SecureObjectSync/SOSEngine.c | 49 +- .../SOSCircle/SecureObjectSync/SOSEngine.h | 4 - .../SecureObjectSync/SOSExports.exp-in | 11 + .../SecureObjectSync/SOSFullPeerInfo.c | 34 +- .../SecureObjectSync/SOSFullPeerInfo.h | 2 + .../SOSCircle/SecureObjectSync/SOSInternal.h | 1 - OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c | 10 +- .../SOSCircle/SecureObjectSync/SOSPeerCoder.c | 3 +- .../SOSCircle/SecureObjectSync/SOSPeerCoder.h | 4 +- .../SecureObjectSync/SOSPeerInfoV2.c | 9 +- .../SecureObjectSync/SOSSysdiagnose.c | 735 +++++ .../SOSCircle/SecureObjectSync/SOSTransport.c | 9 +- .../SecureObjectSync/SOSTransportCoder.c | 229 -- .../SecureObjectSync/SOSTransportCoder.h | 21 - .../SecureObjectSync/SOSTransportMessageIDS.c | 34 +- .../SecureObjectSync/SOSViewManager.c | 190 -- .../SecureObjectSync/SOSViewQueries.c | 93 - .../SecureObjectSync/SOSViewQueries.h | 70 - OSX/sec/SOSCircle/Tool/keychain_log.c | 716 +++++ OSX/sec/SOSCircle/Tool/keychain_log.h | 42 + OSX/sec/SOSCircle/Tool/keychain_sync.c | 153 +- .../Tool/{SOSCommands.h => keychain_sync.h} | 5 + OSX/sec/SOSCircle/Tool/secToolFileIO.c | 67 + OSX/sec/SOSCircle/Tool/secToolFileIO.h | 35 + .../AppleBaselineEscrowCertificates.h | 36 +- .../Regressions/Security_regressions.h | 5 + .../Regressions/secitem/si-13-item-system.m | 125 + .../secitem/si-17-item-system-bluetooth.m | 94 + .../Regressions/secitem/si-20-sectrust.c | 95 +- .../Regressions/secitem/si-20-sectrust.h | 847 ++++++ .../secitem/si-30-keychain-upgrade.c | 4 +- .../Regressions/secitem/si-31-keychain-bad.c | 5 +- .../secitem/si-31-keychain-unreadable.c | 5 +- .../secitem/si-73-secpasswordgenerate.c | 11 +- .../secitem/si-76-shared-credentials.c | 3 + .../secitem/si-88-sectrust-vpnprofile.c | 12 +- .../secitem/si-89-cms-hash-agility.c | 108 + .../secitem/si-89-cms-hash-agility.h | 604 ++++ .../Security/Regressions/secitem/si-90-emcs.m | 62 + .../Regressions/secitem/si-91-sectrust-ast2.c | 105 + .../Regressions/secitem/si-91-sectrust-ast2.h | 265 ++ .../secitem/si_77_SecAccessControl.c | 8 +- OSX/sec/Security/SecCMS.c | 2 +- OSX/sec/Security/SecCertificate.c | 32 +- OSX/sec/Security/SecCertificate.h | 1 + OSX/sec/Security/SecCertificateInternal.h | 2 + OSX/sec/Security/SecEMCS.m | 273 ++ .../SecEMCSPriv.h} | 35 +- OSX/sec/Security/SecExports.exp-in | 25 + OSX/sec/Security/SecFrameworkStrings.h | 3 +- OSX/sec/Security/SecItem.c | 24 +- OSX/sec/Security/SecItemBackup.c | 121 +- OSX/sec/Security/SecItemBackup.h | 2 +- OSX/sec/Security/SecItemConstants.c | 11 +- OSX/sec/Security/SecItemInternal.h | 2 +- OSX/sec/Security/SecItemPriv.h | 46 +- OSX/sec/Security/SecOTRPacketData.h | 4 +- OSX/sec/Security/SecPasswordGenerate.c | 29 + OSX/sec/Security/SecPolicy.c | 59 +- OSX/sec/Security/SecPolicyInternal.h | 11 +- OSX/sec/Security/SecPolicyPriv.h | 9 + OSX/sec/Security/SecSharedCredential.c | 4 +- OSX/sec/Security/SecTrust.c | 9 + OSX/sec/Security/SecuritydXPC.c | 25 + OSX/sec/Security/SecuritydXPC.h | 4 + OSX/sec/SecurityTool/builtin_commands.h | 8 + OSX/sec/SecurityTool/entitlements.plist | 2 + OSX/sec/SecurityTool/syncbubble.m | 65 + OSX/sec/SecurityTool/whoami.m | 56 + OSX/sec/ipc/client.c | 131 +- OSX/sec/ipc/securityd_client.h | 57 +- OSX/sec/ipc/server.c | 482 +++- OSX/sec/sec.xcodeproj/project.pbxproj | 127 +- .../Regressions/SecdTestKeychainUtilities.c | 13 +- OSX/sec/securityd/Regressions/secd-01-items.c | 5 +- ...pted-items.c => secd-05-corrupted-items.m} | 51 +- .../Regressions/secd-154-engine-backoff.c | 279 ++ .../Regressions/secd-20-keychain_upgrade.m | 150 + .../Regressions/secd-21-transmogrify.m | 195 ++ .../Regressions/secd-33-keychain-ctk.c | 11 +- .../Regressions/secd-34-backup-der-parse.c | 2 +- .../Regressions/secd-62-account-backup.c | 10 +- .../securityd/Regressions/secd-70-engine.c | 4 +- .../Regressions/secd-80-views-basic.c | 2 +- .../Regressions/secd-81-item-acl-stress.c | 17 +- .../securityd/Regressions/secd-81-item-acl.c | 9 +- .../secd60-account-cloud-exposure.c | 248 ++ .../securityd/Regressions/secd_regressions.h | 7 +- OSX/sec/securityd/SOSCloudCircleServer.c | 234 +- OSX/sec/securityd/SOSCloudCircleServer.h | 7 + OSX/sec/securityd/SecCAIssuerRequest.c | 19 +- OSX/sec/securityd/SecDbItem.c | 68 +- OSX/sec/securityd/SecDbItem.h | 7 +- OSX/sec/securityd/SecDbQuery.c | 153 +- OSX/sec/securityd/SecDbQuery.h | 49 +- OSX/sec/securityd/SecItemDataSource.c | 24 +- OSX/sec/securityd/SecItemDb.c | 338 ++- OSX/sec/securityd/SecItemDb.h | 24 +- OSX/sec/securityd/SecItemSchema.c | 521 +++- OSX/sec/securityd/SecItemSchema.h | 1 + OSX/sec/securityd/SecItemServer.c | 1012 +++++-- OSX/sec/securityd/SecItemServer.h | 29 +- OSX/sec/securityd/SecKeybagSupport.c | 4 + OSX/sec/securityd/SecPolicyServer.c | 81 +- OSX/sec/securityd/SecTrustServer.c | 19 +- OSX/sec/securityd/entitlements.plist | 2 + OSX/sec/securityd/iCloudTrace.c | 55 +- OSX/sec/securityd/spi.c | 10 +- OSX/sectests/SecurityTests-Entitlements.plist | 2 + OSX/sectests/testlist.h | 1 + OSX/security2/sub_commands.h | 3 +- .../Regressions/su-41-secdb-stress.c | 3 + .../SecurityTool/security_tool_commands.h | 2 +- OSX/utilities/src/SecAKSWrappers.c | 84 +- OSX/utilities/src/SecAKSWrappers.h | 8 + OSX/utilities/src/SecAppleAnchor.c | 7 +- OSX/utilities/src/SecAppleAnchorPriv.h | 1 + OSX/utilities/src/SecDb.c | 13 +- OSX/utilities/src/SecDb.h | 2 +- OSX/utilities/src/SecTrace.c | 49 + OSX/utilities/src/SecTrace.h | 38 + OSX/utilities/src/debugging.c | 2 +- OSX/utilities/src/der_plist.h | 8 + .../utilities.xcodeproj/project.pbxproj | 10 +- OTAPKIAssetTool/OTAServiceApp.m | 9 +- RegressionTests/Security.plist | 61 + RegressionTests/Security_edumode.plist | 35 + .../secbackupntest/secbackupntest.m | 64 + .../secbackuptest/secbackuptest.entitlements | 14 + RegressionTests/secbackuptest/secbackuptest.m | 107 + .../secedumodetest.entitlements | 14 + .../secedumodetest/secedumodetest.m | 65 + Security.xcodeproj/project.pbxproj | 702 ++++- .../xcshareddata/xcschemes/Debug.xcscheme | 32 +- .../xcshareddata/xcschemes/Release.xcscheme | 12 + .../xcshareddata/xcschemes/secdtests.xcscheme | 12 + .../SecurityTests-Entitlements.plist | 2 + .../SecurityTool.xcodeproj/project.pbxproj | 7 + SecurityTool/entitlements.plist | 4 + SecurityTool/keychain_find.c | 351 +++ SecurityTool/keychain_find.h | 4 + SecurityTool/keychain_unlock.c | 7 +- SecurityTool/keychain_utilities.c | 166 +- SecurityTool/keychain_utilities.h | 20 +- SecurityTool/security.c | 37 +- SecurityTool/sub_commands.h | 3 +- codesign_wrapper/codesign_wrapper.c | 15 + libsecurity_smime/lib/SecCmsBase.h | 52 +- libsecurity_smime/lib/SecCmsSignerInfo.h | 18 + libsecurity_smime/lib/cmsattr.c | 1 + libsecurity_smime/lib/cmsrecinfo.c | 2 +- libsecurity_smime/lib/cmssiginfo.c | 87 + libsecurity_smime/lib/cmstpriv.h | 1 + libsecurity_smime/lib/crypto-embedded.c | 65 +- libsecurity_smime/lib/secoid.c | 262 +- libsecurity_smime/lib/security_smime.exp | 2 + .../project.pbxproj | 6 +- resources/English.lproj/CloudKeychain.strings | Bin 12608 -> 12608 bytes secdtests/secdtests-entitlements.plist | 2 + sectask/SecEntitlements.h | 13 + securityd/securityd.xcodeproj/project.pbxproj | 18 +- securityd/src/acl_keychain.cpp | 87 +- securityd/src/acl_keychain.h | 4 +- securityd/src/acl_partition.cpp | 113 + securityd/src/acl_partition.h | 75 + securityd/src/acls.cpp | 212 +- securityd/src/acls.h | 20 + securityd/src/clientid.cpp | 104 + securityd/src/clientid.h | 8 + securityd/src/database.cpp | 6 + securityd/src/database.h | 7 + securityd/src/dbcrypto.cpp | 49 +- securityd/src/dbcrypto.h | 7 +- securityd/src/kcdatabase.cpp | 164 +- securityd/src/kcdatabase.h | 5 + securityd/src/kckey.cpp | 2 + securityd/src/localkey.cpp | 9 + securityd/src/main.cpp | 8 +- securityd/src/server.h | 1 + securityd/src/tempdatabase.cpp | 7 + securityd/src/tempdatabase.h | 1 + securityd/src/tokendatabase.h | 3 + securityd/src/transition.cpp | 32 +- 406 files changed, 23258 insertions(+), 3365 deletions(-) create mode 100644 OSX/libsecurity_cms/regressions/cms-hashagility-test.c create mode 100644 OSX/libsecurity_cms/regressions/cms-hashagility-test.h create mode 100644 OSX/libsecurity_cms/regressions/cms_regressions.h create mode 100644 OSX/libsecurity_codesigning/lib/diskimagerep.cpp create mode 100644 OSX/libsecurity_codesigning/lib/diskimagerep.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h create mode 100644 OSX/libsecurity_keychain/regressions/kc-30-xara.c create mode 100644 OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp create mode 100644 OSX/libsecurity_utilities/lib/CSPDLTransaction.h rename OSX/regressions/test/{testenv.c => testenv.m} (95%) create mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSSysdiagnose.c delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c delete mode 100644 OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.h create mode 100644 OSX/sec/SOSCircle/Tool/keychain_log.c create mode 100644 OSX/sec/SOSCircle/Tool/keychain_log.h rename OSX/sec/SOSCircle/Tool/{SOSCommands.h => keychain_sync.h} (94%) create mode 100644 OSX/sec/SOSCircle/Tool/secToolFileIO.c create mode 100644 OSX/sec/SOSCircle/Tool/secToolFileIO.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-13-item-system.m create mode 100644 OSX/sec/Security/Regressions/secitem/si-17-item-system-bluetooth.m create mode 100644 OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.c create mode 100644 OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.h create mode 100644 OSX/sec/Security/Regressions/secitem/si-90-emcs.m create mode 100644 OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.c create mode 100644 OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.h create mode 100644 OSX/sec/Security/SecEMCS.m rename OSX/sec/{SOSCircle/SecureObjectSync/SOSViewManager.h => Security/SecEMCSPriv.h} (54%) create mode 100644 OSX/sec/SecurityTool/syncbubble.m create mode 100644 OSX/sec/SecurityTool/whoami.m rename OSX/sec/securityd/Regressions/{secd-05-corrupted-items.c => secd-05-corrupted-items.m} (83%) create mode 100644 OSX/sec/securityd/Regressions/secd-154-engine-backoff.c create mode 100644 OSX/sec/securityd/Regressions/secd-20-keychain_upgrade.m create mode 100644 OSX/sec/securityd/Regressions/secd-21-transmogrify.m create mode 100644 OSX/sec/securityd/Regressions/secd60-account-cloud-exposure.c create mode 100644 OSX/utilities/src/SecTrace.c create mode 100644 OSX/utilities/src/SecTrace.h create mode 100644 RegressionTests/Security.plist create mode 100644 RegressionTests/Security_edumode.plist create mode 100644 RegressionTests/secbackupntest/secbackupntest.m create mode 100644 RegressionTests/secbackuptest/secbackuptest.entitlements create mode 100644 RegressionTests/secbackuptest/secbackuptest.m create mode 100644 RegressionTests/secedumodetest/secedumodetest.entitlements create mode 100644 RegressionTests/secedumodetest/secedumodetest.m create mode 100644 securityd/src/acl_partition.cpp create mode 100644 securityd/src/acl_partition.h diff --git a/CircleJoinRequested/CircleJoinRequested.m b/CircleJoinRequested/CircleJoinRequested.m index bdb248f5..4c8bddd3 100644 --- a/CircleJoinRequested/CircleJoinRequested.m +++ b/CircleJoinRequested/CircleJoinRequested.m @@ -422,9 +422,11 @@ static void postApplicationReminderAlert(NSDate *nowish, PersistentState *state, if (CPIsInternalDevice() && state.defaultPendingApplicationReminderAlertInterval != state.pendingApplicationReminderAlertInterval) { +#if !defined(NDEBUG) body = [body stringByAppendingFormat: @"〖debug interval %u; wait time %@〗", state.pendingApplicationReminderAlertInterval, [nowish copyDescriptionOfIntervalSince:state.applicationDate]]; +#endif } NSDictionary *pendingAttributes = @{ diff --git a/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist b/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist index e571be54..9f09d8bc 100644 --- a/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist +++ b/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist @@ -19,6 +19,8 @@ com.apple.security.idskeychainsyncingproxy EnvironmentVariables + DEBUGSCOPE + all WAIT4DEBUGGER NO diff --git a/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist b/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist index 93d2bd92..f62eceff 100644 --- a/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist +++ b/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist @@ -4,6 +4,10 @@ com.apple.wifi.manager-access + com.apple.private.ids.force-encryption-off + + com.apple.private.alloy.keychainsync + com.apple.private.ids.remoteurlconnection com.apple.private.ids.messaging.high-priority diff --git a/OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist b/OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist index 6732c264..6c9d8691 100644 --- a/OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist +++ b/OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist @@ -19,6 +19,8 @@ com.apple.security.idskeychainsyncingproxy EnvironmentVariables + DEBUGSCOPE + all WAIT4DEBUGGER NO diff --git a/OSX/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist b/OSX/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist index 93d2bd92..9d23eb1c 100644 --- a/OSX/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist +++ b/OSX/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist @@ -6,6 +6,10 @@ 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 diff --git a/OSX/Keychain Circle Notification/KNAppDelegate.m b/OSX/Keychain Circle Notification/KNAppDelegate.m index 224bc123..044bd17b 100644 --- a/OSX/Keychain Circle Notification/KNAppDelegate.m +++ b/OSX/Keychain Circle Notification/KNAppDelegate.m @@ -483,7 +483,7 @@ bool isAppleInternal(void) message = [message stringByAppendingString: reason_str]; } - // Improve wording of the iCloud keychain drop/reset error messages + // [ui] MONARCH: Improve wording of the iCloud keychain drop/reset error messages // Contrary to HI spec (and I think it makes more sense) // 1. otherButton == top : Not Now // 2. actionButton == bottom: Continue @@ -523,7 +523,7 @@ bool isAppleInternal(void) } } - // Improve wording of the iCloud keychain drop/reset error messages + // [ui] MONARCH: Improve wording of the iCloud keychain drop/reset error messages // Contrary to HI spec (and I think it makes more sense) // 1. otherButton == top : Not Now // 2. actionButton == bottom: Continue diff --git a/OSX/OSX.xcodeproj/project.pbxproj b/OSX/OSX.xcodeproj/project.pbxproj index 71ef2e33..2bb44ff5 100644 --- a/OSX/OSX.xcodeproj/project.pbxproj +++ b/OSX/OSX.xcodeproj/project.pbxproj @@ -574,6 +574,7 @@ 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, ); }; }; + D4CBC1451BE981F600C5795E /* libsecurity_cms_regressions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */; }; D4DDD3D01BE3EC0300E8AE2D /* libDiagnosticMessagesClient.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4DDD3A71BE3EB4200E8AE2D /* libDiagnosticMessagesClient.dylib */; }; E76079D61951FDAF00F69731 /* liblogging.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E76079D51951FDA800F69731 /* liblogging.a */; }; E778BFBC17176DDE00302C14 /* security.exp-in in Sources */ = {isa = PBXBuildFile; fileRef = 182BB562146F4C73000BF1F3 /* security.exp-in */; }; @@ -582,6 +583,11 @@ EB22F3FB18A26BE40016A8EC /* bc-10-knife-on-bread.c in Sources */ = {isa = PBXBuildFile; fileRef = EB22F3F518A26BA50016A8EC /* bc-10-knife-on-bread.c */; }; 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 */; }; F93C493E1AB8FF670047E01A /* ckcdiagnose.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = F93C493D1AB8FF670047E01A /* ckcdiagnose.sh */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; /* End PBXBuildFile section */ @@ -1902,6 +1908,20 @@ remoteGlobalIDString = 52200F8714F2B87F00F7F6E7; remoteInfo = XPCTimeStampingService; }; + D4CBC1191BE981DE00C5795E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D4C3345B1BE2A2B100D8C1EF; + remoteInfo = libsecurity_cms_regressions; + }; + D4CBC1271BE981DE00C5795E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1879B64B146DE750007E536C /* libsecurity_cms.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D4C3345C1BE2A2B100D8C1EF; + remoteInfo = libsecurity_cms_regressions; + }; E7421C7D1ADC8E0D005FC1C0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0C6D77DE15C8C06500BB4405 /* tlsnke.xcodeproj */; @@ -2641,7 +2661,13 @@ 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; }; EBD8B52718A55668004A650F /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README; path = Breadcrumb/README; 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 = ""; }; /* End PBXFileReference section */ @@ -2650,6 +2676,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBF2D7641C1E3AB2006AB6FF /* Foundation.framework in Frameworks */, + D4CBC1451BE981F600C5795E /* libsecurity_cms_regressions.a in Frameworks */, 18CD682717272EBC005345FB /* libaks.a in Frameworks */, 0CCEBDB416C2D026001BD7F6 /* libregressions.a in Frameworks */, 52669053169D181900ED8231 /* Security.framework in Frameworks */, @@ -2665,6 +2693,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBF2D7141C1E0AF7006AB6FF /* Foundation.framework in Frameworks */, 5E7AF49B1ACD64E600005140 /* libACM.a in Frameworks */, 5E605AFC1AB859B70049FA14 /* libcoreauthd_test_client.a in Frameworks */, 44D78BB91A0A615800B63C6C /* libaks_acl.a in Frameworks */, @@ -2841,6 +2870,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBC1B8E31BE9708300E6ACA6 /* Foundation.framework in Frameworks */, 44D78BB71A0A613900B63C6C /* libaks_acl.a in Frameworks */, 52CD052316A0E24900218387 /* Security.framework in Frameworks */, 432800841B4CE731002E8525 /* libaks.a in Frameworks */, @@ -2883,6 +2913,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBF2D7631C1E2B58006AB6FF /* Foundation.framework in Frameworks */, 5EF7C2521B00EB0A00E5E99C /* libaks.a in Frameworks */, 5EF7C2511B00EAF100E5E99C /* libcoreauthd_client.a in Frameworks */, 5EF7C2501B00EA7A00E5E99C /* libACM.a in Frameworks */, @@ -2905,6 +2936,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBF2E29D1BEC8D9200626DE4 /* IOKit.framework in Frameworks */, 43C3B0D41AFD569600786702 /* Security.framework in Frameworks */, 43C3B3311AFD5E1100786702 /* CoreFoundation.framework in Frameworks */, ); @@ -3074,6 +3106,7 @@ 37AB39101A44A88000B56E04 /* gk_reset_check */, CD63ACE11A8061FA001B5671 /* IDSKeychainSyncingProxy */, 5EF7C20B1B00E25400E5E99C /* secacltests */, + EB93FF2A1BE0889E00978606 /* RegressionTests */, 1807384D146D0D4E00F05C24 /* Frameworks */, 1807384C146D0D4E00F05C24 /* Products */, ); @@ -3108,7 +3141,11 @@ 1807384D146D0D4E00F05C24 /* Frameworks */ = { isa = PBXGroup; children = ( + EBF2D7131C1E0AF7006AB6FF /* Foundation.framework */, D4DDD3A71BE3EB4200E8AE2D /* libDiagnosticMessagesClient.dylib */, + EBF2E29C1BEC8D9200626DE4 /* IOKit.framework */, + EBC1B8E21BE9708300E6ACA6 /* Foundation.framework */, + EB93FF8D1BE08DE600978606 /* IOKit.framework */, 4C97761D17BEB23E0002BFE4 /* AOSAccounts.framework */, 4C328D2F1778EC4F0015EED1 /* AOSUI.framework */, 4C5DD46B17A5F67300696A79 /* AppleSystemInfo.framework */, @@ -3677,6 +3714,7 @@ isa = PBXGroup; children = ( 1879B654146DE750007E536C /* libsecurity_cms.a */, + D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */, ); name = Products; sourceTree = ""; @@ -4103,6 +4141,24 @@ name = Breadcrumb; sourceTree = ""; }; + EB93FF2A1BE0889E00978606 /* RegressionTests */ = { + isa = PBXGroup; + children = ( + EB93FF541BE088FC00978606 /* Security.plist */, + EB93FF521BE088E000978606 /* secbackupntest */, + ); + name = RegressionTests; + path = ../RegressionTests; + sourceTree = ""; + }; + EB93FF521BE088E000978606 /* secbackupntest */ = { + isa = PBXGroup; + children = ( + EB93FF531BE088F600978606 /* secbackupntest.m */, + ); + name = secbackupntest; + sourceTree = ""; + }; F93C493C1AB8FF670047E01A /* ckcdiagnose */ = { isa = PBXGroup; children = ( @@ -4305,6 +4361,7 @@ buildRules = ( ); dependencies = ( + D4CBC11A1BE981DE00C5795E /* PBXTargetDependency */, 0C6C632E15D19D2900BC68CD /* PBXTargetDependency */, ACB6173F18B5232700EBEDD7 /* PBXTargetDependency */, 0CBD50C716C3260D00713B6C /* PBXTargetDependency */, @@ -5462,6 +5519,13 @@ remoteRef = CD63AD0B1A8061FA001B5671 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libsecurity_cms_regressions.a; + remoteRef = D4CBC1271BE981DE00C5795E /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; E7421C7E1ADC8E0D005FC1C0 /* tlsnke.kext */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; @@ -6372,6 +6436,11 @@ name = XPCTimeStampingService; targetProxy = D4A2FC7D1BC89D5200BF6E56 /* PBXContainerItemProxy */; }; + D4CBC11A1BE981DE00C5795E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = libsecurity_cms_regressions; + targetProxy = D4CBC1191BE981DE00C5795E /* PBXContainerItemProxy */; + }; E76079FA1951FDF600F69731 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = liblogging; diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme index 84b9ae52..081a81f4 100644 --- a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme +++ b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme @@ -66,6 +66,10 @@ argument = "ssl-42-ciphers" isEnabled = "NO"> + + @@ -80,7 +84,7 @@ + isEnabled = "NO"> + + + + diff --git a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme index ba3b7779..f92e458a 100644 --- a/OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme +++ b/OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme @@ -11,7 +11,8 @@ buildForRunning = "YES" buildForProfiling = "YES" buildForArchiving = "YES" - buildForAnalyzing = "YES"> + buildForAnalyzing = "YES" + hideIssues = "NO"> + buildForAnalyzing = "YES" + hideIssues = "NO"> + + + + + + diff --git a/OSX/authd/authorization.plist b/OSX/authd/authorization.plist index da098fe2..8406e487 100644 --- a/OSX/authd/authorization.plist +++ b/OSX/authd/authorization.plist @@ -1428,6 +1428,13 @@ See remaining rules for examples. authenticate-admin-30 + com.apple.security.syntheticinput + + class + rule + rule + authenticate-session-owner + rules diff --git a/OSX/authd/engine.c b/OSX/authd/engine.c index 276ac5f2..5e6d2ae8 100644 --- a/OSX/authd/engine.c +++ b/OSX/authd/engine.c @@ -808,7 +808,7 @@ _evaluate_class_mechanism(engine_t engine, rule_t rule) CFIndex count = CFArrayGetCount(mechanisms); for (CFIndex i = 0; i < count; i++) { if (!mechanism_is_privileged((mechanism_t)CFArrayGetValueAtIndex(mechanisms, i))) { - LOGV("engine[%i]: authorization denied (in DarkWake)", connection_get_pid(engine->conn)); + LOGE("engine[%i]: authorization denied (in DW)", connection_get_pid(engine->conn)); goto done; } } @@ -869,7 +869,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) if (rule_check_flags(rule, RuleFlagRequireAppleSigned)) { if (!auth_token_apple_signed(engine->auth)) { - LOGV("engine[%i]: rule deny, creator of authorization is not signed by apple", connection_get_pid(engine->conn)); + LOGE("engine[%i]: rule deny, creator of authorization is not signed by apple", connection_get_pid(engine->conn)); return errAuthorizationDenied; } } @@ -890,7 +890,7 @@ _evaluate_rule(engine_t engine, rule_t rule, bool *save_pwd) case RC_MECHANISM: return _evaluate_class_mechanism(engine, rule); default: - LOGV("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", connection_get_pid(engine->conn)); return errAuthorizationInternal; } } @@ -1038,7 +1038,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en return true; - if (!_verify_sandbox(engine, key)) { + if (!_verify_sandbox(engine, key)) { // _verify_sandbox is already logging failures status = errAuthorizationDenied; return false; } @@ -1125,6 +1125,7 @@ OSStatus engine_authorize(engine_t engine, auth_rights_t rights, auth_items_t en } if (engine->dismissed) { + LOGE("engine[%i]: engine dismissed"); status = errAuthorizationDenied; } diff --git a/OSX/authd/server.c b/OSX/authd/server.c index b29182f1..ef07e325 100644 --- a/OSX/authd/server.c +++ b/OSX/authd/server.c @@ -601,11 +601,12 @@ authorization_copy_rights(connection_t conn, xpc_object_t message, xpc_object_t auth_token_t auth = NULL; status = _process_find_copy_auth_token_from_xpc(proc, message, &auth); require_noerr(status, done); + require_noerr_action_quiet(status, done, LOGE("copy_rights: no auth token")); status = _server_authorize(conn, auth, flags, rights, environment, &engine); - require_noerr(status, done); - - //reply + require_noerr_action_quiet(status, done, LOGE("copy_rights: _server_authorize failed")); + + //reply xpc_object_t outItems = auth_rights_export_xpc(engine_get_granted_rights(engine)); xpc_dictionary_set_value(reply, AUTH_XPC_OUT_ITEMS, outItems); xpc_release_safe(outItems); diff --git a/OSX/codesign_tests/CaspianTests/CaspianTests b/OSX/codesign_tests/CaspianTests/CaspianTests index 241645c8..6865b0dd 100755 --- a/OSX/codesign_tests/CaspianTests/CaspianTests +++ b/OSX/codesign_tests/CaspianTests/CaspianTests @@ -52,7 +52,7 @@ runTest enable-tests spctl --test-devid-enable runTest enable-check eval "spctl --test-devid-status | grep enable >/dev/null" -runTest exec-ls spctl -a -t exec /bin/ls +runTest fail-exec-ls spctl -a -t exec /bin/ls runTest fail-open-txt spctl -a -t open /usr/local/OpenSourceLicenses/xar.txt runTest fail-open-pdf spctl -a -t open /usr/share//cups/ipptool/testfile.pdf @@ -194,8 +194,8 @@ runTest disable-check10 eval "spctl --status | grep disable > /dev/null" # check devid is still revoked while caspian is disabled # -runTest fail-0-hello-revoked spctl -a -t exec ${ct}/hello-revoked -runTest 0-hello-expired spctl -a -t exec ${ct}/hello-expired +runTest fail-0-hello-revoked spctl -a -t exec ${ct}/hello-revoked.app +runTest 0-hello-expired spctl -a -t exec ${ct}/hello-expired.app # # check enabled w/o devid @@ -204,7 +204,7 @@ runTest 0-hello-expired spctl -a -t exec ${ct}/hello-expired runTest enable-tests11 spctl --master-enable runTest enable-check11 eval "spctl --status | grep enable > /dev/null" -runTest fail-1-hello-revoked spctl -a -t exec ${ct}/hello-revoked +runTest fail-1-hello-revoked spctl -a -t exec ${ct}/hello-revoked.app #runTest fail-1-hello-expired spctl -a -t exec ${ct}/hello-expired #### failes because of broken ocsp # @@ -214,8 +214,8 @@ runTest fail-1-hello-revoked spctl -a -t exec ${ct}/hello-revoked runTest enable-tests11 spctl --test-devid-enable runTest enable-check11 eval "spctl --test-devid-status | grep enable > /dev/null" -runTest fail-1id-hello-revoked spctl -a -t exec ${ct}/hello-revoked -runTest 1id-hello-expired spctl -a -t exec ${ct}/hello-expired +runTest fail-1id-hello-revoked spctl -a -t exec ${ct}/hello-revoked.app +runTest 1id-hello-expired spctl -a -t exec ${ct}/hello-expired.app # # diff --git a/OSX/lib/security.exp-in b/OSX/lib/security.exp-in index e04e8e53..39d7aed2 100644 --- a/OSX/lib/security.exp-in +++ b/OSX/lib/security.exp-in @@ -235,6 +235,7 @@ _CMSEncoderSetEncapsulatedContentTypeOID _CMSEncoderSetEncoder _CMSEncoderAddSignedAttributes _CMSEncoderSetSigningTime +_CMSEncoderSetAppleCodesigningHashAgility _CMSEncoderSetCertificateChainMode _CMSEncoderGetCertificateChainMode _CMSEncoderUpdateContent @@ -263,6 +264,7 @@ _CMSDecoderCopySignerTimestampWithPolicy _CMSDecoderCopySignerTimestampCertificates _CMSEncoderCopySignerTimestamp _CMSEncoderCopySignerTimestampWithPolicy +_CMSDecoderCopySignerAppleCodesigningHashAgility // // libsecurity_codesigning @@ -351,6 +353,7 @@ _kSecCodeInfoEntitlementsDict _kSecCodeInfoFlags _kSecCodeInfoFormat _kSecCodeInfoDigestAlgorithm +_kSecCodeInfoDigestAlgorithms _kSecCodeInfoIdentifier _kSecCodeInfoImplicitDesignatedRequirement _kSecCodeInfoMainExecutable @@ -362,6 +365,7 @@ _kSecCodeInfoStatus _kSecCodeInfoTeamIdentifier _kSecCodeInfoTrust _kSecCodeInfoUnique +_kSecCodeInfoCdHashes _kSecCodeInfoCodeDirectory _kSecCodeInfoCodeOffset _kSecCodeInfoResourceDirectory @@ -1106,6 +1110,8 @@ _kSecACLAuthorizationKeychainItemRead _kSecACLAuthorizationKeychainItemInsert _kSecACLAuthorizationKeychainItemModify _kSecACLAuthorizationKeychainItemDelete +_kSecACLAuthorizationPartitionID +_kSecACLAuthorizationIntegrity _kSecIdentityDomainDefault _kSecIdentityDomainKerberosKDC _kSecClass @@ -1308,6 +1314,7 @@ _kSecPolicyAppleTestATVAppSigning _kSecPolicyApplePayIssuerEncryption _kSecPolicyAppleOSXProvisioningProfileSigning _kSecPolicyAppleATVVPNProfileSigning +_kSecPolicyAppleAST2DiagnosticsServerAuth _kSecPolicyOid _kSecPolicyName _kSecPolicyClient @@ -1498,6 +1505,7 @@ _SecCertificateCopyPreferred _SecCertificateCopyPublicKey _SecCertificateCopyPublicKeySHA1Digest _SecCertificateCopyPublicKeySHA1DigestFromCertificateData +_SecCertificateCopySHA256Digest _SecCertificateCopySubjectSummary _SecCertificateCopyDNSNames _SecCertificateCreateItemImplInstance @@ -1664,6 +1672,7 @@ _SecKeychainGetStatus _SecKeychainGetTypeID _SecKeychainGetUserInteractionAllowed _SecKeychainGetVersion +_SecKeychainGetKeychainVersion _SecKeychainMDSInstall _SecKeychainIsValid _SecKeychainItemAdd @@ -1698,6 +1707,7 @@ _SecKeychainItemModifyAttributesAndData _SecKeychainItemModifyEncryptedData _SecKeychainItemModifyContent _SecKeychainItemSetAccess +_SecKeychainItemSetAccessWithPassword _SecKeychainItemSetAttribute _SecKeychainItemSetData _SecKeychainItemSetExtendedAttribute @@ -1751,6 +1761,7 @@ _SecPolicyCreateApplePushService _SecPolicyCreateApplePushServiceLegacy _SecPolicyCreateAppleMMCSService _SecPolicyCreateApplePPQService +_SecPolicyCreateAppleAST2Service _SecPolicyCreateAppleATVAppSigning _SecPolicyCreateTestAppleATVAppSigning _SecPolicyCreateAppleATVVPNProfileSigning @@ -1891,11 +1902,18 @@ __SecKeychainRestoreBackup __SecKeychainSyncUpdateMessage __SecKeychainBackupSyncable __SecKeychainRestoreSyncable +__SecKeychainWriteBackupToFileDescriptor +__SecKeychainRestoreBackupFromFileDescriptor _SecItemBackupWithRegisteredBackups _SecItemBackupSetConfirmedManifest _SecItemBackupRestore _SecItemBackupCopyMatching _SecItemBackupWithChanges +__SecSecuritydCopyWhoAmI +__SecSyncBubbleTransfer +__SecSystemKeychainTransfer +__SecSyncDeleteUserViews + // // libsecurity_manifest @@ -2027,6 +2045,7 @@ _SecCmsSignerInfoAddMSSMIMEEncKeyPrefs _SecCmsSignerInfoAddSMIMECaps _SecCmsSignerInfoAddSMIMEEncKeyPrefs _SecCmsSignerInfoAddSigningTime +_SecCmsSignerInfoAddAppleCodesigningHashAgility _SecCmsSignerInfoCreate _SecCmsSignerInfoCreateWithSubjKeyID _SecCmsSignerInfoDestroy @@ -2038,6 +2057,7 @@ _SecCmsSignerInfoGetSignerEmailAddress _SecCmsSignerInfoGetSigningCertificate _SecCmsSignerInfoGetSigningTime _SecCmsSignerInfoGetTimestampTime +_SecCmsSignerInfoGetAppleCodesigningHashAgility _SecCmsSignerInfoGetVerificationStatus _SecCmsSignerInfoGetEncDigest _SecCmsSignerInfoIncludeCerts @@ -2279,6 +2299,7 @@ _SecKeyCreatePublicFromPrivate _add_security_log_handler _remove_security_log_handler _secdebug_internal +_secdebugfunc_internal // // libSecureObjectSync diff --git a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp index 8ae93c2e..6f15d7a5 100644 --- a/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp +++ b/OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp @@ -100,12 +100,18 @@ RSAKeySizes::RSAKeySizes() maxPubExponentSize = RSA_MAX_PUB_EXPONENT_SIZE; /* now see if there are prefs set for either of these */ - Dictionary* d = Dictionary::CreateDictionary(kRSAKeySizePrefsDomain, Dictionary::US_System, true); + Dictionary* d = NULL; + try { + d = Dictionary::CreateDictionary(kRSAKeySizePrefsDomain, Dictionary::US_System, true); + } catch(...) { + return; + } + if (!d) { return; } - + if (d->dict()) { auto_ptrapd(d); diff --git a/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp index 3c6b24e4..cfc62236 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp @@ -79,8 +79,10 @@ SSCSPDLSession::makeReferenceKey(SSCSPSession &session, KeyHandle inKeyHandle, CssmKey &outKey, SSDatabase &inSSDatabase, uint32 inKeyAttr, const CssmData *inKeyLabel) { - new SSKey(session, inKeyHandle, outKey, inSSDatabase, inKeyAttr, + SSKey* sskey = new SSKey(session, inKeyHandle, outKey, inSSDatabase, inKeyAttr, inKeyLabel); + + secdebug("SecAccessReference", "made a new reference sskey with handle %d [%d]", sskey->keyHandle(), sskey->keyReference()); } SSKey & @@ -93,6 +95,8 @@ 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()); #ifdef someday /* diff --git a/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp b/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp index 8fa42e44..40bc29fa 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp @@ -1312,6 +1312,31 @@ SSDLSession::PassThrough(CSSM_DB_HANDLE inDbHandle, doConvertRecordIdentifier (db, inInputParams, outOutputParams); break; } + case CSSM_APPLECSPDL_DB_GET_BLOB_VERSION: + { + *((uint32*) *outOutputParams) = db->dbBlobVersion(); + break; + } + case CSSM_APPLECSPDL_DB_RECODE_TO_BLOB_VERSION: + { + *((uint32*) *outOutputParams) = db->recodeDbToVersion(*((uint32*) inInputParams)); + break; + } + case CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK: + { + db->takeFileLock(); + break; + } + case CSSM_APPLECSPDL_DB_RELEASE_FILE_LOCK: + { + db->releaseFileLock(*((bool*) inInputParams)); + break; + } + case CSSM_APPLECSPDL_DB_MAKE_BACKUP: + { + db->makeBackup(); + break; + } default: { CSSM_RETURN result = CSSM_DL_PassThrough(db->handle(), inPassThroughId, inInputParams, outOutputParams); diff --git a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp index 672dae88..755d232a 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp @@ -22,6 +22,8 @@ #include "SSDatabase.h" #include +#include +#include using namespace CssmClient; using namespace SecurityServer; @@ -33,6 +35,7 @@ SSDatabaseImpl::SSDatabaseImpl(ClientSession &inClientSession, const CssmClient: const char *inDbName, const CSSM_NET_ADDRESS *inDbLocation) : Db::Impl(dl, inDbName, inDbLocation), mClientSession(inClientSession), mSSDbHandle(noDb) { + mTransaction = NULL; } SSDatabaseImpl::~SSDatabaseImpl() @@ -257,6 +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()); Db::Impl::insert(DBBlobRelationID, NULL, &dbb); if (autoCommit) { @@ -287,6 +291,7 @@ SSDatabaseImpl::createWithBlob(const DLDbIdentifier &dlDbIdentifier, const CSSM_ { bool autoCommit; commonCreate(dlDbIdentifier, autoCommit); + secdebugfunc("integrity", "opening %s", name()); Db::Impl::insert(DBBlobRelationID, NULL, &blob); if (autoCommit) { @@ -311,81 +316,185 @@ SSDatabaseImpl::open(const DLDbIdentifier &dlDbIdentifier) CssmDataContainer dbb(allocator()); getDbBlobId(&dbb); + secdebugfunc("integrity", "opening %s", name()); + + // Pull our version out of the database blob mSSDbHandle = mClientSession.decodeDb(dlDbIdentifier, AccessCredentials::overlay(accessCredentials()), dbb); } void -SSDatabaseImpl::recode(const CssmData &data, const CssmData &extraData) +SSDatabaseImpl::recode(const CssmData &dbHandleArray, const CssmData &agentData) { - // Start a transaction (Implies activate()). - passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, 0); + // Start a transaction (Implies activate()). + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, 0); + + try + { + CssmDataContainer dbb(allocator()); + // Make sure mSSDbHandle is valid. + CssmClient::DbUniqueRecord dbBlobId = getDbBlobId(&dbb); + if (mForked()) { + // re-establish the dbHandle with the SecurityServer + mSSDbHandle = mClientSession.decodeDb(mIdentifier, + AccessCredentials::overlay(accessCredentials()), dbb); + } + dbb.clear(); + + DbHandle successfulHdl = mClientSession.authenticateDbsForSync(dbHandleArray, agentData); + + // Create a newDbHandle using the master secrets from the dbBlob we are + // recoding to. + SecurityServer::DbHandle clonedDbHandle = + mClientSession.recodeDbForSync(successfulHdl, mSSDbHandle); + + // @@@ If the dbb changed since we fetched it we should abort or + // retry the operation here. + + recodeHelper(clonedDbHandle, dbBlobId); + + // Commit the transaction to the db + passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(1)); + } + catch (...) + { + // Something went wrong rollback the transaction + passThrough(CSSM_APPLEFILEDL_ROLLBACK, NULL); + passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + reinterpret_cast(1)); + throw; + } +} - try - { - CssmDataContainer dbb(allocator()); - // Make sure mSSDbHandle is valid. - CssmClient::DbUniqueRecord dbBlobId = getDbBlobId(&dbb); - if (mForked()) { - // re-establish the dbHandle with the SecurityServer - mSSDbHandle = mClientSession.decodeDb(mIdentifier, - AccessCredentials::overlay(accessCredentials()), dbb); - } - dbb.clear(); +uint32 +SSDatabaseImpl::recodeDbToVersion(uint32 newBlobVersion) { + // Start a transaction (Implies activate()). + DLTransaction transaction(handle()); + + try + { + if(isLocked()) { + secdebugfunc("integrity", "is currently locked"); + } else { + secdebugfunc("integrity", "is already unlocked"); + } + + CssmDataContainer dbb(allocator()); + // Make sure mSSDbHandle is valid. + CssmClient::DbUniqueRecord dbBlobId = getDbBlobId(&dbb); + + // always establish the dbHandle with the SecurityServer + mSSDbHandle = mClientSession.decodeDb(mIdentifier, AccessCredentials::overlay(accessCredentials()), dbb); + dbb.clear(); + + // Create a newDbHandle using the master secrets from the dbBlob we are recoding to. + secdebugfunc("integrity", "recoding db with handle %d", mSSDbHandle); + SecurityServer::DbHandle clonedDbHandle = mClientSession.recodeDbToVersion(newBlobVersion, mSSDbHandle); + secdebugfunc("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); + + // Commit the transaction to the db + transaction.success(); + return newBlobVersion; + } + catch (...) + { + throw; + } +} - DbHandle successfulHdl = mClientSession.authenticateDbsForSync(data, extraData); +void SSDatabaseImpl::takeFileLock() { + if(mTransaction) { + // you're already in the middle of a file lock. + return; + } + mTransaction = new DLTransaction(handle()); + passThrough(CSSM_APPLEFILEDL_TAKE_FILE_LOCK, NULL, NULL); +} - // Create a newDbHandle using the master secrets from the dbBlob we are - // recoding to. - SecurityServer::DbHandle clonedDbHandle = - mClientSession.recodeDbForSync(successfulHdl, mSSDbHandle); +void SSDatabaseImpl::releaseFileLock(bool success) { + if(mTransaction) { + try { + if(success) { + mTransaction->success(); + } + // The destructor will commit the database and re-enable autocommit (if needed) + delete mTransaction; + mTransaction = NULL; + } catch(...) { + mTransaction = NULL; + throw; + } + } +} - // @@@ If the dbb changed since we fetched it we should abort or - // retry the operation here. +void SSDatabaseImpl::makeBackup() { + passThrough(CSSM_APPLEFILEDL_MAKE_BACKUP, NULL, NULL); +} - // Recode all keys - DbCursor cursor(SSDatabase(this)); - cursor->recordType(CSSM_DL_DB_RECORD_ALL_KEYS); - CssmDataContainer keyBlob(allocator()); - CssmClient::DbUniqueRecord keyBlobId; - DbAttributes attributes; - while (cursor->next(&attributes, &keyBlob, keyBlobId)) - { - // Decode the old key - CssmKey::Header header; - KeyHandle keyHandle = - mClientSession.decodeKey(mSSDbHandle, keyBlob, header); - // Recode the key - CssmDataContainer newKeyBlob(mClientSession.returnAllocator); - mClientSession.recodeKey(mSSDbHandle, keyHandle, clonedDbHandle, - newKeyBlob); - mClientSession.releaseKey(keyHandle); - // Write the recoded key blob to the database - keyBlobId->modify(attributes.recordType(), NULL, &newKeyBlob, - CSSM_DB_MODIFY_ATTRIBUTE_NONE); - } - // Commit the new blob to securityd, reencode the db blob, release the - // cloned db handle and commit the new blob to the db. - mClientSession.commitDbForSync(mSSDbHandle, clonedDbHandle, - dbb, allocator()); - dbBlobId->modify(DBBlobRelationID, NULL, &dbb, - CSSM_DB_MODIFY_ATTRIBUTE_NONE); - - // Commit the transaction to the db - passThrough(CSSM_APPLEFILEDL_COMMIT, NULL); - passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - reinterpret_cast(1)); - } - catch (...) - { - // Something went wrong rollback the transaction - passThrough(CSSM_APPLEFILEDL_ROLLBACK, NULL); - passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - reinterpret_cast(1)); - throw; - } +uint32 SSDatabaseImpl::recodeHelper(SecurityServer::DbHandle clonedDbHandle, CssmClient::DbUniqueRecord& dbBlobId) { + // Recode all keys + DbCursor cursor(SSDatabase(this)); + cursor->recordType(CSSM_DL_DB_RECORD_ALL_KEYS); + CssmDataContainer keyBlob(allocator()); + CssmClient::DbUniqueRecord keyBlobId; + DbAttributes attributes; + while (cursor->next(&attributes, &keyBlob, keyBlobId)) + { + KeyHandle keyHandle = 0; + try { + // Decode the old key + CssmKey::Header header; + keyHandle = mClientSession.decodeKey(mSSDbHandle, keyBlob, header); + // Recode the key + CssmDataContainer newKeyBlob(mClientSession.returnAllocator); + mClientSession.recodeKey(mSSDbHandle, keyHandle, clonedDbHandle, newKeyBlob); + mClientSession.releaseKey(keyHandle); + keyHandle = 0; + // Write the recoded key blob to the database + keyBlobId->modify(attributes.recordType(), NULL, &newKeyBlob, + 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"); + + + keyBlobId->deleteRecord(); + + if(keyHandle != 0) { + // tell securityd not to worry about this key again + try { + secdebugfunc("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); + } + } + } + } + + // 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); + mClientSession.commitDbForSync(mSSDbHandle, clonedDbHandle, + dbb, allocator()); + dbBlobId->modify(DBBlobRelationID, NULL, &dbb, + CSSM_DB_MODIFY_ATTRIBUTE_NONE); + return getDbVersionFromBlob(dbb); } + void SSDatabaseImpl::getRecordIdentifier(CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, CSSM_DATA &recordID) { // the unique ID is composed of three uint32s (plus one filler word). Pull @@ -418,6 +527,22 @@ void SSDatabaseImpl::copyBlob(CSSM_DATA &data) dbb.Length = 0; } +uint32 +SSDatabaseImpl::dbBlobVersion() { + CssmDataContainer dbb(allocator()); + getDbBlobId(&dbb); + return getDbVersionFromBlob(dbb); +} + +uint32 +SSDatabaseImpl::getDbVersionFromBlob(const CssmData& dbb) { + DbBlob* x = Allocator::standard().malloc(dbb.length()); + memcpy(x, dbb, dbb.length()); + uint32 version = x->version(); + Allocator::standard().free(x); + return version; +} + DbUniqueRecordImpl * SSDatabaseImpl::newDbUniqueRecord() { diff --git a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h index 1566aed2..04ed9c05 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h +++ b/OSX/libsecurity_apple_cspdl/lib/SSDatabase.h @@ -25,6 +25,8 @@ #include #include #include +#include +#include class SSCSPDLSession; class SSUniqueRecord; @@ -67,6 +69,22 @@ public: bool isLocked(); void changePassphrase(const CSSM_ACCESS_CREDENTIALS *cred); void recode(const CssmData &data, const CssmData &extraData); + + + + // Attempt to recode this database to the new blob version + // Returns new version + uint32 recodeDbToVersion(uint32 newBlobVersion); + + // 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 + // is called. Pass success=true if you want the transaction to commit; otherwise + // it will roll back. + void takeFileLock(); + void releaseFileLock(bool success); + + // DbUniqueRecordMaker CssmClient::DbUniqueRecordImpl *newDbUniqueRecord(); @@ -75,11 +93,20 @@ public: void getRecordIdentifier(const CSSM_DB_UNIQUE_RECORD_PTR uniqueRecord, CSSM_DATA &data); void copyBlob(CSSM_DATA &blob); - + + // Get the version of this database's encoding + uint32 dbBlobVersion(); + + // Try to make a backup copy of this database on the filesystem + void makeBackup(); + protected: CssmClient::DbUniqueRecord getDbBlobId(CssmDataContainer *dbb = NULL); void commonCreate (const DLDbIdentifier &dlDbIdentifier, bool &autocommit); + static uint32 getDbVersionFromBlob(const CssmData& dbb); + uint32 recodeHelper(SecurityServer::DbHandle clonedDbHandle, CssmClient::DbUniqueRecord& dbBlobId); + private: // 5 minute default autolock time static const uint32 kDefaultIdleTimeout = 5 * 60; @@ -91,6 +118,9 @@ private: SecurityServer::ClientSession &mClientSession; SecurityServer::DbHandle mSSDbHandle; + + // Transaction for remembering if we've taken the file lock + DLTransaction* mTransaction; }; diff --git a/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp b/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp index 5eacdf95..69c57b51 100644 --- a/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp +++ b/OSX/libsecurity_apple_cspdl/lib/SSKey.cpp @@ -290,6 +290,8 @@ SSKey::keyHandle() clientSession().decodeKey(mUniqueId->database().dbHandle(), blob, dummyHeader); + secdebugfunc("SecAccessReference", "decoded a new key into handle %d [reference %d]", mKeyHandle, keyReference()); + // @@@ Check decoded header against returned header } diff --git a/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp b/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp index 4781af8c..165228a5 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp @@ -2034,8 +2034,9 @@ post_trust_setting: * from the net; we prevent that from happening when the certs * are in inCertGroup or gatheredCerts by keeping track of those * certs' mUsed state. + * Also handle Radar 23734683, endless loop of untrusted roots. */ - if(isInGroup(*issuerCert)) { + if(isInGroup(*issuerCert) || gatheredCerts->isInGroup(*issuerCert)) { tpDebug("buildCertGroup: Multiple instances of cert"); delete issuerCert; issuerCert = NULL; diff --git a/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp b/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp index 5ba632f9..0810f0ba 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp @@ -157,7 +157,7 @@ TPCertInfo *tpDbFindIssuerCert( * Handle temporal invalidity - if so and this is the first one * we've seen, hold on to it while we search for better one. */ - if((crtn == CSSM_OK) && (expiredIssuer == NULL)) { + if(crtn == CSSM_OK) { if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { /* * Exact value not important here, this just uniquely identifies @@ -165,6 +165,11 @@ TPCertInfo *tpDbFindIssuerCert( */ tpDbDebug("tpDbFindIssuerCert: holding expired cert (1)"); crtn = CSSM_CERT_STATUS_EXPIRED; + /* Delete old stashed expired issuer */ + if (expiredIssuer) { + expiredIssuer->freeUniqueRecord(); + delete expiredIssuer; + } expiredIssuer = issuerCert; expiredIssuer->dlDbHandle(dlDb); expiredIssuer->uniqueRecord(record); @@ -174,18 +179,33 @@ TPCertInfo *tpDbFindIssuerCert( * Prefer a root over an intermediate issuer if we can get one * (in case a cross-signed intermediate and root are both available) */ - if((crtn == CSSM_OK) && (nonRootIssuer == NULL)) { - if(!issuerCert->isSelfSigned()) { - /* - * Exact value not important here, this just uniquely identifies - * this situation in the switch below. - */ - tpDbDebug("tpDbFindIssuerCert: holding non-root cert (1)"); - crtn = CSSM_CERT_STATUS_IS_ROOT; + if(crtn == CSSM_OK && !issuerCert->isSelfSigned()) { + /* + * Exact value not important here, this just uniquely identifies + * this situation in the switch below. + */ + tpDbDebug("tpDbFindIssuerCert: holding non-root cert (1)"); + crtn = CSSM_CERT_STATUS_IS_ROOT; + /* + * If the old intermediate was temporally invalid, replace it. + * (Regardless of temporal validity of new one we found, because + * as far as this code is concerned they're equivalent.) + */ + if(!nonRootIssuer || + (nonRootIssuer && (nonRootIssuer->isExpired() || nonRootIssuer->isNotValidYet()))) { + if(nonRootIssuer) { + nonRootIssuer->freeUniqueRecord(); + delete nonRootIssuer; + } nonRootIssuer = issuerCert; nonRootIssuer->dlDbHandle(dlDb); nonRootIssuer->uniqueRecord(record); } + else { + delete issuerCert; + CSSM_DL_FreeUniqueRecord(dlDb, record); + issuerCert = NULL; + } } switch(crtn) { case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE: @@ -248,24 +268,44 @@ TPCertInfo *tpDbFindIssuerCert( } /* temporal validity check, again */ - if((crtn == CSSM_OK) && (expiredIssuer == NULL)) { + if(crtn == CSSM_OK) { if(issuerCert->isExpired() || issuerCert->isNotValidYet()) { tpDbDebug("tpDbFindIssuerCert: holding expired cert (2)"); crtn = CSSM_CERT_STATUS_EXPIRED; + /* Delete old stashed expired issuer */ + if (expiredIssuer) { + expiredIssuer->freeUniqueRecord(); + delete expiredIssuer; + } expiredIssuer = issuerCert; expiredIssuer->dlDbHandle(dlDb); expiredIssuer->uniqueRecord(record); } } /* self-signed check, again */ - if((crtn == CSSM_OK) && (nonRootIssuer == NULL)) { - if(!issuerCert->isSelfSigned()) { - tpDbDebug("tpDbFindIssuerCert: holding non-root cert (2)"); - crtn = CSSM_CERT_STATUS_IS_ROOT; + if(crtn == CSSM_OK && !issuerCert->isSelfSigned()) { + tpDbDebug("tpDbFindIssuerCert: holding non-root cert (2)"); + crtn = CSSM_CERT_STATUS_IS_ROOT; + /* + * If the old intermediate was temporally invalid, replace it. + * (Regardless of temporal validity of new one we found, because + * as far as this code is concerned they're equivalent.) + */ + if(!nonRootIssuer || + (nonRootIssuer && (nonRootIssuer->isExpired() || nonRootIssuer->isNotValidYet()))) { + if(nonRootIssuer) { + nonRootIssuer->freeUniqueRecord(); + delete nonRootIssuer; + } nonRootIssuer = issuerCert; nonRootIssuer->dlDbHandle(dlDb); nonRootIssuer->uniqueRecord(record); } + else { + delete issuerCert; + CSSM_DL_FreeUniqueRecord(dlDb, record); + issuerCert = NULL; + } } foundIt = false; diff --git a/OSX/libsecurity_asn1/lib/secasn1d.c b/OSX/libsecurity_asn1/lib/secasn1d.c index d09592be..456309ab 100644 --- a/OSX/libsecurity_asn1/lib/secasn1d.c +++ b/OSX/libsecurity_asn1/lib/secasn1d.c @@ -37,6 +37,7 @@ * * $Id: secasn1d.c,v 1.16 2004/05/13 15:29:13 dmitch Exp $ */ +#include #include "secasn1.h" #include "secerr.h" @@ -1733,8 +1734,41 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state, len--; } } - PORT_Memcpy (item->Data + item->Length, buf, len); - item->Length += len; + unsigned long offset = item->Length; + if (state->underlying_kind == SEC_ASN1_BIT_STRING) { + // The previous bit string must have no unused bits. + if (item->Length & 0x7) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return 0; + } + // If this is a bit string, the length is bits, not bytes. + offset = item->Length >> 3; + } + if (state->underlying_kind == SEC_ASN1_BIT_STRING) { + // Protect against overflow during the bytes-to-bits conversion. + if (len >= (ULONG_MAX >> 3) + 1) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return 0; + } + unsigned long len_in_bits = (len << 3) - state->bit_string_unused_bits; + // Protect against overflow when computing the total length in bits. + if (UINT_MAX - item->Length < len_in_bits) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return 0; + } + item->Length += len_in_bits; + } else { + if (UINT_MAX - item->Length < len) { + PORT_SetError (SEC_ERROR_BAD_DER); + state->top->status = decodeError; + return 0; + } + item->Length += len; + } + PORT_Memcpy (item->Data + offset, buf, len); } state->pending -= bufLen; if (state->pending == 0) @@ -1808,13 +1842,6 @@ sec_asn1d_parse_more_bit_string (sec_asn1d_state *state, } len = sec_asn1d_parse_leaf (state, buf, len); - if (state->place == beforeEndOfContents && state->dest != NULL) { - SecAsn1Item *item; - - item = (SecAsn1Item *)(state->dest); - if (item->Length) - item->Length = (item->Length << 3) - state->bit_string_unused_bits; - } return len; } @@ -2289,7 +2316,7 @@ sec_asn1d_concat_substrings (sec_asn1d_state *state) * All bit-string substrings except the last one should be * a clean multiple of 8 bits. */ - if (is_bit_string && (substring->next == NULL) + if (is_bit_string && (substring->next != NULL) && (substring->len & 0x7)) { dprintf("decodeError: sec_asn1d_concat_substrings align\n"); PORT_SetError (SEC_ERROR_BAD_DER); diff --git a/OSX/libsecurity_asn1/lib/secasn1e.c b/OSX/libsecurity_asn1/lib/secasn1e.c index e695972f..5f383ade 100644 --- a/OSX/libsecurity_asn1/lib/secasn1e.c +++ b/OSX/libsecurity_asn1/lib/secasn1e.c @@ -40,6 +40,8 @@ #include "secasn1.h" +#include + typedef enum { beforeHeader, duringContents, @@ -1341,13 +1343,16 @@ SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, SEC_ASN1EncoderContext *cx; our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); - if (our_pool == NULL) - return NULL; + if (our_pool == NULL) { + syslog(LOG_ERR,"SEC_ASN1EncoderStart: failed to create new arena"); + return NULL; + } cx = (SEC_ASN1EncoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); if (cx == NULL) { - PORT_FreeArena (our_pool, PR_FALSE); - return NULL; + syslog(LOG_ERR,"SEC_ASN1EncoderStart: failed to alloc"); + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; } cx->our_pool = our_pool; @@ -1362,8 +1367,9 @@ SEC_ASN1EncoderStart (const void *src, const SecAsn1Template *theTemplate, * Trouble initializing (probably due to failed allocations) * requires that we just give up. */ - PORT_FreeArena (our_pool, PR_FALSE); - return NULL; + syslog(LOG_ERR, "SEC_ASN1EncoderStart: unable to initialize state"); + PORT_FreeArena (our_pool, PR_FALSE); + return NULL; } return cx; @@ -1463,6 +1469,9 @@ 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; } @@ -1564,17 +1573,23 @@ 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) - return NULL; + if (rv != SECSuccess) { + syslog(LOG_ERR, "SEC_ASN1EncodeItem: Encode failed %d", rv); + return NULL; + } dest = sec_asn1e_allocate_item (poolp, dest, encoding_length); - if (dest == NULL) - return NULL; + if (dest == NULL) { + syslog(LOG_ERR, "SEC_ASN1EncodeItem: allocate failure"); + return NULL; + } /* XXX necessary? This really just checks for a bug in the allocate fn */ PORT_Assert (dest->Data != NULL); - if (dest->Data == NULL) - return NULL; + if (dest->Data == NULL) { + syslog(LOG_ERR, "SEC_ASN1EncodeItem: data allocate failure"); + return NULL; + } dest->Length = 0; (void) SEC_ASN1Encode (src, theTemplate, sec_asn1e_encode_item_store, dest); diff --git a/OSX/libsecurity_cdsa_client/lib/aclclient.h b/OSX/libsecurity_cdsa_client/lib/aclclient.h index 00b5b513..2daa1cfd 100644 --- a/OSX/libsecurity_cdsa_client/lib/aclclient.h +++ b/OSX/libsecurity_cdsa_client/lib/aclclient.h @@ -120,6 +120,7 @@ protected: Allocator &allocator; operator const AccessCredentials* () const { return mCredentials; } + AccessCredentials* getAccessCredentials() const { return mCredentials; } protected: AutoCredentials *mCredentials; diff --git a/OSX/libsecurity_cdsa_client/lib/dlclient.cpp b/OSX/libsecurity_cdsa_client/lib/dlclient.cpp index 882fde1e..127f9b13 100644 --- a/OSX/libsecurity_cdsa_client/lib/dlclient.cpp +++ b/OSX/libsecurity_cdsa_client/lib/dlclient.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace CssmClient; @@ -472,6 +473,38 @@ void DbImpl::setBatchMode(Boolean mode, Boolean rollback) } } +uint32 DbImpl::dbBlobVersion() { + uint32 dbBlobVersion = 0; + uint32* dbBlobVersionPtr = &dbBlobVersion; + + // We only have a blob version if we're an apple CSPDL + 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"); + } + return dbBlobVersion; +} + +uint32 DbImpl::recodeDbToVersion(uint32 version) { + uint32 newDbVersion; + uint32* newDbVersionPtr = &newDbVersion; + check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_RECODE_TO_BLOB_VERSION, &version, (void**) &newDbVersionPtr)); + return newDbVersion; +} + +void DbImpl::takeFileLock() { + passThrough(CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK, NULL, NULL); +} + +void DbImpl::releaseFileLock(bool success) { + passThrough(CSSM_APPLECSPDL_DB_RELEASE_FILE_LOCK, &success, NULL); +} + +void DbImpl::makeBackup() { + passThrough(CSSM_APPLECSPDL_DB_MAKE_BACKUP, NULL, NULL); +} + // // DbCursorMaker // @@ -903,3 +936,34 @@ DbAttributes::DbAttributes(const Db &db, uint32 capacity, Allocator &allocator) : CssmAutoDbRecordAttributeData(capacity, db->allocator(), allocator) { } + +void DbAttributes::updateWithDbAttributes(DbAttributes* newValues) { + if(!newValues) { + return; + } + + canonicalize(); + newValues->canonicalize(); + + updateWith(newValues); +} + +void +DbAttributes::canonicalize() { + for(int i = 0; i < size(); i++) { + CssmDbAttributeData& data = attributes()[i]; + CssmDbAttributeInfo& datainfo = data.info(); + + // Calling Schema::attributeInfo is the best way to canonicalize. + // There's no way around the try-catch structure, since it throws if it + // can't find something. + + try { + if(datainfo.nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER) { + data.info() = Security::KeychainCore::Schema::attributeInfo(datainfo.intName()); + } + } catch(...) { + // Don't worry about it + } + } +} diff --git a/OSX/libsecurity_cdsa_client/lib/dlclient.h b/OSX/libsecurity_cdsa_client/lib/dlclient.h index 23c242c2..6617a392 100644 --- a/OSX/libsecurity_cdsa_client/lib/dlclient.h +++ b/OSX/libsecurity_cdsa_client/lib/dlclient.h @@ -322,6 +322,24 @@ public: virtual void copyBlob(CssmData &data); virtual void setBatchMode(Boolean mode, Boolean rollback); + // Get the version of this database's encoding + virtual uint32 dbBlobVersion(); + + // Attempt to recode this database to the new version + virtual uint32 recodeDbToVersion(uint32 version); + + // 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 + // is called. Pass success=true if you want the transaction to commit; otherwise + // it will roll back. + virtual void takeFileLock(); + virtual void releaseFileLock(bool success); + + // Make a backup of this database on the filesystem + virtual void makeBackup(); + + // Utility methods // Always use the dbName and dbLocation that were passed in during @@ -527,6 +545,13 @@ class DbAttributes : public CssmAutoDbRecordAttributeData public: DbAttributes(); DbAttributes(const Db &db, uint32 capacity = 0, Allocator &allocator = Allocator::standard()); + + // Similar to CssmAutoDbRecordAttributeData::updateWith, but a different + // signature. Will canonicalize the elements in both this and the newValues dbAttributes. + void updateWithDbAttributes(DbAttributes* newValues); + + // Try to change the infos in this database to a canonicalized form + void canonicalize(); }; diff --git a/OSX/libsecurity_cdsa_client/lib/keychainacl.cpp b/OSX/libsecurity_cdsa_client/lib/keychainacl.cpp index 271774c9..f1166541 100644 --- a/OSX/libsecurity_cdsa_client/lib/keychainacl.cpp +++ b/OSX/libsecurity_cdsa_client/lib/keychainacl.cpp @@ -113,21 +113,3 @@ void KeychainAclFactory::release(AclEntryInput *input) { DataWalkers::chunkFree(input, allocator); } - - -// -// ACL editing -// -void KeychainAclFactory::comment(TypedList &subject) -{ - subject.insert(new(allocator) ListElement(CSSM_ACL_SUBJECT_TYPE_COMMENT), - subject.first()); -} - -void KeychainAclFactory::uncomment(TypedList &subject) -{ - ListElement *first = subject.first(); - assert(*first == CSSM_ACL_SUBJECT_TYPE_COMMENT); - subject -= first; - destroy(first, allocator); -} diff --git a/OSX/libsecurity_cdsa_client/lib/keychainacl.h b/OSX/libsecurity_cdsa_client/lib/keychainacl.h index 05e1354d..5cf097b4 100644 --- a/OSX/libsecurity_cdsa_client/lib/keychainacl.h +++ b/OSX/libsecurity_cdsa_client/lib/keychainacl.h @@ -64,13 +64,6 @@ public: AclEntryInput *anyOwner(); void release(AclEntryInput *input); -public: - // - // Edit ACLs (in external form, as TypedLists) - // - void comment(TypedList &subject); - void uncomment(TypedList &subject); - private: AutoCredentials nullCred; AutoCredentials kcCred; diff --git a/OSX/libsecurity_cdsa_client/lib/securestorage.cpp b/OSX/libsecurity_cdsa_client/lib/securestorage.cpp index 6fb56f0d..40b1c0ed 100644 --- a/OSX/libsecurity_cdsa_client/lib/securestorage.cpp +++ b/OSX/libsecurity_cdsa_client/lib/securestorage.cpp @@ -411,12 +411,16 @@ SSDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, DbUniqueRecord &uniqueId, const CSSM_ACCESS_CREDENTIALS *cred) { - if (!data) - return DbDbCursorImpl::next(attributes, data, uniqueId); + if (!data) { + return DbDbCursorImpl::next(attributes, data, uniqueId); + } DbAttributes noAttrs, *attrs; attrs = attributes ? attributes : &noAttrs; + // To comply with previous behavior, this method will not find symmetric or public/private keys + // if you ask for the data of each item. + // Get the datablob for this record CssmDataContainer dataBlob(allocator()); for (;;) @@ -424,36 +428,42 @@ SSDbCursorImpl::next(DbAttributes *attributes, ::CssmDataContainer *data, if (!DbDbCursorImpl::next(attrs, &dataBlob, uniqueId)) return false; - // Keep going until we find a non key type record. CSSM_DB_RECORDTYPE rt = attrs->recordType(); - if (rt != CSSM_DL_DB_RECORD_SYMMETRIC_KEY - && rt != CSSM_DL_DB_RECORD_PRIVATE_KEY - && rt != CSSM_DL_DB_RECORD_PUBLIC_KEY) + if (rt == CSSM_DL_DB_RECORD_SYMMETRIC_KEY || + rt == CSSM_DL_DB_RECORD_PRIVATE_KEY || + rt == CSSM_DL_DB_RECORD_PUBLIC_KEY) { - // @@@ Check the label and if it doesn't start with the magic for a SSKey return the key. + // This is a key. Free it, and then check if we should return the item (but not the data) + database()->csp()->freeKey(*reinterpret_cast(dataBlob.Data)); + + if(!data) { + break; + } + } else { + // This is a non-key item. Return it. break; } - else + } + + // If the caller requested any data, return the data. + if(data) { + if (!SSGroupImpl::isGroup(dataBlob)) { - // Free the key we just retrieved - database()->csp()->freeKey(*reinterpret_cast(dataBlob.Data)); + data->Data = dataBlob.Data; + data->Length = dataBlob.Length; + dataBlob.Data = NULL; + dataBlob.Length = 0; + return true; } - } - if (!SSGroupImpl::isGroup(dataBlob)) - { - data->Data = dataBlob.Data; - data->Length = dataBlob.Length; - dataBlob.Data = NULL; - dataBlob.Length = 0; - return true; - } + // Get the group for dataBlob + SSGroup group(database(), dataBlob); - // Get the group for dataBlob - SSGroup group(database(), dataBlob); + // TODO: Add attrs to cred - // Decode the dataBlob, pass in the DL allocator. - group->decodeDataBlob(dataBlob, cred, database()->allocator(), *data); + // Decode the dataBlob, pass in the DL allocator. + group->decodeDataBlob(dataBlob, cred, database()->allocator(), *data); + } return true; } diff --git a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp index 41f4ee85..f2b674ff 100644 --- a/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp +++ b/OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp @@ -1044,6 +1044,8 @@ KeyPool::add(ReferencedKey &referencedKey) // Since add is only called from the constructor of ReferencedKey we should // 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()); } ReferencedKey & @@ -1060,6 +1062,8 @@ 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()); + return *it->second; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/Schema.h b/OSX/libsecurity_cdsa_utilities/lib/Schema.h index 69fd626f..5331db0d 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/Schema.h +++ b/OSX/libsecurity_cdsa_utilities/lib/Schema.h @@ -38,6 +38,7 @@ namespace Schema { CSSM_DB_RECORDTYPE recordTypeFor(SecItemClass itemClass); SecItemClass itemClassFor(CSSM_DB_RECORDTYPE recordType); +bool haveAttributeInfo(SecKeychainAttrType attrType); const CSSM_DB_ATTRIBUTE_INFO &attributeInfo(SecKeychainAttrType attrType); extern const CSSM_DB_ATTRIBUTE_INFO RelationID; diff --git a/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 b/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 index 5bc9248f..f3b84278 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 +++ b/OSX/libsecurity_cdsa_utilities/lib/Schema.m4 @@ -387,6 +387,81 @@ itemClassFor(CSSM_DB_RECORDTYPE recordType) } } +bool +haveAttributeInfo(SecKeychainAttrType attrType) +{ +switch (attrType) +{ +case kSecCreationDateItemAttr: return true; +case kSecModDateItemAttr: return true; +case kSecDescriptionItemAttr: return true; +case kSecCommentItemAttr: return true; +case kSecCreatorItemAttr: return true; +case kSecTypeItemAttr: return true; +case kSecScriptCodeItemAttr: return true; +case kSecLabelItemAttr: return true; +case kSecAlias: return true; +case kSecInvisibleItemAttr: return true; +case kSecNegativeItemAttr: return true; +case kSecCustomIconItemAttr: return true; +/* Unique Generic password attributes */ +case kSecAccountItemAttr: return true; +case kSecServiceItemAttr: return true; +case kSecGenericItemAttr: return true; +/* Unique Appleshare password attributes */ +case kSecVolumeItemAttr: return true; +case kSecAddressItemAttr: return true; +case kSecSignatureItemAttr: return true; +/* Unique AppleShare and Internet attributes */ +case kSecServerItemAttr: return true; +case kSecProtocolItemAttr: return true; +/* Unique Internet password attributes */ +case kSecSecurityDomainItemAttr: return true; +case kSecAuthenticationTypeItemAttr: return true; +case kSecPortItemAttr: return true; +case kSecPathItemAttr: return true; +/* Unique Certificate attributes */ +case kSecCertTypeItemAttr: return true; +case kSecCertEncodingItemAttr: return true; +case kSecSubjectItemAttr: return true; +case kSecIssuerItemAttr: return true; +case kSecSerialNumberItemAttr: return true; +case kSecSubjectKeyIdentifierItemAttr: return true; +case kSecPublicKeyHashItemAttr: return true; +/* Unique UserTrust attributes */ +case kSecTrustCertAttr: return true; +case kSecTrustPolicyAttr: return true; +/* Unique UnlockReferral attributes */ +case kSecReferralTypeAttr: return true; +case kSecReferralDbNameAttr: return true; +case kSecReferralDbGuidAttr: return true; +case kSecReferralDbSSIDAttr: return true; +case kSecReferralDbSSTypeAttr: return true; +case kSecReferralDbNetnameAttr: return true; +case kSecReferralKeyLabelAttr: return true; +case kSecReferralKeyAppTagAttr: return true; +/* Unique ExtendedAttribute attributes */ +case kExtendedAttrRecordTypeAttr: return true; +case kExtendedAttrItemIDAttr: return true; +case kExtendedAttrAttributeNameAttr: return true; +case kExtendedAttrAttributeValueAttr: return true; +/* ??? */ +case kSecProtectedDataItemAttr: return true; +default: +{ +if (attrType == 7) +{ +return true; +} +else if (attrType == 8) +{ +return true; +} +return false; +} +} +} + const CSSM_DB_ATTRIBUTE_INFO & attributeInfo(SecKeychainAttrType attrType) { diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_any.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_any.cpp index 25f6a0e5..99479cc7 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_any.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_any.cpp @@ -32,7 +32,7 @@ // // The ANY subject matches all credentials, including none at all. // -bool AnyAclSubject::validate(const AclValidationContext &) const +bool AnyAclSubject::validates(const AclValidationContext &) const { return true; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_any.h b/OSX/libsecurity_cdsa_utilities/lib/acl_any.h index b985c872..7553652f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_any.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_any.h @@ -43,7 +43,7 @@ namespace Security { class AnyAclSubject : public AclSubject { public: AnyAclSubject() : AclSubject(CSSM_ACL_SUBJECT_TYPE_ANY) { } - bool validate(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &ctx) const; CssmList toList(Allocator &alloc) const; class Maker : public AclSubject::Maker { diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp index a848449f..5c0cc03f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp @@ -36,7 +36,7 @@ // a feature of "the" process (defined by the environment), and take no // samples whatsoever. // -bool CodeSignatureAclSubject::validate(const AclValidationContext &context) const +bool CodeSignatureAclSubject::validates(const AclValidationContext &context) const { // a suitable environment is required for a match if (Environment *env = context.environment()) diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.h b/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.h index 2dc2b2b3..39628f2b 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.h @@ -60,7 +60,7 @@ public: CodeSignatureAclSubject(const OSXVerifier &verifier) : AclSubject(CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE), OSXVerifier(verifier) { } - bool validate(const AclValidationContext &baseCtx) const; + bool validates(const AclValidationContext &baseCtx) const; CssmList toList(Allocator &alloc) const; void exportBlob(Writer::Counter &pub, Writer::Counter &priv); diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp index 8cf7501f..fdc29c9f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp @@ -52,7 +52,7 @@ using namespace DataWalkers; // // The COMMENT subject matches nothing, no matter how pretty. // -bool CommentAclSubject::validate(const AclValidationContext &) const +bool CommentAclSubject::validates(const AclValidationContext &) const { return false; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.h b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.h index 98a90b92..55796b7e 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_comment.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_comment.h @@ -49,7 +49,7 @@ public: CommentAclSubject() : AclSubject(CSSM_ACL_SUBJECT_TYPE_COMMENT) { } - bool validate(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &ctx) const; CssmList toList(Allocator &alloc) const; void exportBlob(Writer::Counter &pub, Writer::Counter &priv); diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp index 121b2a27..cd4a5f81 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp @@ -58,7 +58,7 @@ AclSubject *OriginMaker::make(AclSubject::Version version, Reader &pub, Reader & // This tries to find the source AclObject and hands the question off to it. // If anything isn't right, fail the validation. // -bool OriginAclSubject::validate(const AclValidationContext &ctx) const +bool OriginAclSubject::validates(const AclValidationContext &ctx) const { if (Environment *env = ctx.environment()) if (ObjectAcl *source = env->preAuthSource()) @@ -162,7 +162,7 @@ private: const char *mCredTag; }; -bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext &baseCtx) const +bool SourceAclSubject::SourceAclSubject::validates(const AclValidationContext &baseCtx) const { // try to authenticate our sub-subject if (Environment *env = baseCtx.environment()) { @@ -175,7 +175,7 @@ bool SourceAclSubject::SourceAclSubject::validate(const AclValidationContext &ba if (!accepted) { secdebug("preauth", "%p needs to authenticate its subject", this); SourceValidationContext ctx(baseCtx); - if (mSourceSubject->validate(ctx)) { + if (mSourceSubject->validates(ctx)) { secdebug("preauth", "%p pre-authenticated", this); accepted = true; } diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.h b/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.h index ee56b95e..333be37f 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_preauth.h @@ -85,7 +85,7 @@ struct AclState { // class OriginAclSubject : public AclSubject { public: - bool validate(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &ctx) const; CssmList toList(Allocator &alloc) const; OriginAclSubject(AclAuthorization auth); @@ -108,7 +108,7 @@ private: // class SourceAclSubject : public AclSubject { public: - bool validate(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &ctx) const; CssmList toList(Allocator &alloc) const; SourceAclSubject(AclSubject *subSubject, diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp index f8a8cea9..7918ff47 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp @@ -34,7 +34,7 @@ // Validate a credential set against this subject. // No credential is required for this match. // -bool ProcessAclSubject::validate(const AclValidationContext &context) const +bool ProcessAclSubject::validates(const AclValidationContext &context) const { // reality check (internal structure was validated when created) assert(select.uses(CSSM_ACL_MATCH_BITS)); diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_process.h b/OSX/libsecurity_cdsa_utilities/lib/acl_process.h index 79bf66b3..de7632fb 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_process.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_process.h @@ -56,7 +56,7 @@ public: // class ProcessAclSubject : public AclSubject { public: - bool validate(const AclValidationContext &baseCtx) const; + bool validates(const AclValidationContext &baseCtx) const; CssmList toList(Allocator &alloc) const; ProcessAclSubject(const AclProcessSubjectSelector &selector) diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp index be4c2587..cfced63e 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp @@ -47,7 +47,7 @@ ProtectedPasswordAclSubject::ProtectedPasswordAclSubject(Allocator &alloc, CssmM // // Validate a credential set against this subject // -bool ProtectedPasswordAclSubject::validate(const AclValidationContext &context, +bool ProtectedPasswordAclSubject::validates(const AclValidationContext &context, const TypedList &sample) const { if (sample.length() == 1) { diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.h b/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.h index 10c11fdc..a1c9c777 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.h @@ -45,7 +45,7 @@ namespace Security { class ProtectedPasswordAclSubject : public SimpleAclSubject { public: - bool validate(const AclValidationContext &baseCtx, const TypedList &sample) const; + bool validates(const AclValidationContext &baseCtx, const TypedList &sample) const; CssmList toList(Allocator &alloc) const; ProtectedPasswordAclSubject(Allocator &alloc, const CssmData &password); diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp index 87a6c193..df678e2a 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp @@ -88,7 +88,7 @@ void SecretAclSubject::secret(CssmManagedData &s) const // Validate a secret. // The subclass has to come up with the secret somehow. We just validate it. // -bool SecretAclSubject::validate(const AclValidationContext &context, +bool SecretAclSubject::validates(const AclValidationContext &context, const TypedList &sample) const { CssmAutoData secret(allocator); diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_secret.h b/OSX/libsecurity_cdsa_utilities/lib/acl_secret.h index 1166eafa..ead024a5 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_secret.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_secret.h @@ -57,7 +57,7 @@ namespace Security { // class SecretAclSubject : public SimpleAclSubject { public: - bool validate(const AclValidationContext &ctx, const TypedList &sample) const; + bool validates(const AclValidationContext &ctx, const TypedList &sample) const; SecretAclSubject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type, const CssmData &secret); SecretAclSubject(Allocator &alloc, CSSM_ACL_SUBJECT_TYPE type, CssmManagedData &secret); diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp index 17e568f9..835a56be 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp @@ -53,7 +53,7 @@ public: const TypedList &sampleList; }; -bool ThresholdAclSubject::validate(const AclValidationContext &baseCtx, +bool ThresholdAclSubject::validates(const AclValidationContext &baseCtx, const TypedList &sample) const { #ifdef STRICTCOUNTING @@ -71,7 +71,7 @@ bool ThresholdAclSubject::validate(const AclValidationContext &baseCtx, SublistValidationContext ctx(baseCtx, sample); uint32 matched = 0; for (uint32 n = 0; n < totalSubjects; n++) { - if ((matched += elements[n]->validate(ctx)) >= minimumNeeded) + if ((matched += elements[n]->validates(ctx)) >= minimumNeeded) return true; #ifdef STRICTCOUNTING else if (matched + subSampleCount - n <= minimumNeeded) diff --git a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.h b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.h index 437f78f0..edbc3e7b 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.h +++ b/OSX/libsecurity_cdsa_utilities/lib/acl_threshold.h @@ -50,7 +50,7 @@ class ThresholdAclSubject : public SimpleAclSubject { typedef ObjectAcl::AclSubjectPointer AclSubjectPointer; typedef vector AclSubjectVector; public: - bool validate(const AclValidationContext &baseCtx, const TypedList &sample) const; + bool validates(const AclValidationContext &baseCtx, const TypedList &sample) const; CssmList toList(Allocator &alloc) const; ThresholdAclSubject(uint32 n, uint32 k, const AclSubjectVector &subSubjects); diff --git a/OSX/libsecurity_cdsa_utilities/lib/aclsubject.cpp b/OSX/libsecurity_cdsa_utilities/lib/aclsubject.cpp index 70ec05e5..07951e03 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/aclsubject.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/aclsubject.cpp @@ -115,13 +115,13 @@ AclSubject::Maker::~Maker() // A SimpleAclSubject accepts only a single type of sample, validates // samples independently, and makes no use of certificates. // -bool SimpleAclSubject::validate(const AclValidationContext &ctx) const +bool SimpleAclSubject::validates(const AclValidationContext &ctx) const { for (uint32 n = 0; n < ctx.count(); n++) { const TypedList &sample = ctx[n]; if (!sample.isProper()) CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); - if (sample.type() == type() && validate(ctx, sample)) { + if (sample.type() == type() && validates(ctx, sample)) { ctx.matched(ctx[n]); return true; // matched this sample; validation successful } diff --git a/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h b/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h index 4ad71347..d7603184 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h +++ b/OSX/libsecurity_cdsa_utilities/lib/aclsubject.h @@ -61,6 +61,9 @@ public: // provide an Adornable for a given subject to store data in, or throw if none available (default) virtual Adornable &store(const AclSubject *subject); + + // special-purpose bypass (force validation to succeed) + bool forceSuccess = false; }; @@ -121,6 +124,25 @@ private: AclValidationEnvironment *mEnv; // environmental context (if any) const char *mEntryTag; // entry tag }; + + +// +// An AclValidationContext that simply presents all top-level credentials +// to all subjects. +// +class BaseValidationContext : public AclValidationContext { +public: + BaseValidationContext(const AccessCredentials *cred, + AclAuthorization auth, AclValidationEnvironment *env) + : AclValidationContext(cred, auth, env) { } + + uint32 count() const { return cred() ? cred()->samples().length() : 0; } + uint32 size() const { return count(); } + const TypedList &sample(uint32 n) const + { assert(n < count()); return cred()->samples()[n]; } + + void matched(const TypedList *) const { } // ignore match info +}; // @@ -151,7 +173,7 @@ public: CSSM_ACL_SUBJECT_TYPE type() const { return mType; } // validation (evaluation) primitive - virtual bool validate(const AclValidationContext &ctx) const = 0; + virtual bool validates(const AclValidationContext &ctx) const = 0; // export to CSSM interface virtual CssmList toList(Allocator &alloc) const = 0; @@ -212,8 +234,8 @@ class SimpleAclSubject : public AclSubject { public: SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE type) : AclSubject(type) { } - bool validate(const AclValidationContext &ctx) const; - virtual bool validate(const AclValidationContext &baseCtx, + virtual bool validates(const AclValidationContext &ctx) const; + virtual bool validates(const AclValidationContext &baseCtx, const TypedList &sample) const = 0; }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp index 96a32b50..347971db 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp @@ -71,12 +71,17 @@ void AuthorizationGroup::destroy(Allocator &alloc) { alloc.free(AuthTags); } - + bool AuthorizationGroup::contains(CSSM_ACL_AUTHORIZATION_TAG tag) const { return find(AuthTags, &AuthTags[NumberOfAuthTags], tag) != &AuthTags[NumberOfAuthTags]; } +bool AuthorizationGroup::containsOnly(CSSM_ACL_AUTHORIZATION_TAG tag) const +{ + return count() == 1 && (*this)[0] == tag; +} + AuthorizationGroup::operator AclAuthorizationSet() const { diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.h b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.h index bf23f7df..8a4635aa 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.h @@ -68,6 +68,7 @@ public: { assert(ix < size()); return AuthTags[ix]; } bool contains(CSSM_ACL_AUTHORIZATION_TAG tag) const; + bool containsOnly(CSSM_ACL_AUTHORIZATION_TAG tag) const; operator AclAuthorizationSet () const; }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp index ff7d0925..44a31a05 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp @@ -77,6 +77,35 @@ void AccessCredentials::tag(const char *tagString) strcpy(EntryTag, tagString); } +bool AccessCredentials::authorizesUI() const { + list uisamples; + + if(samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT, uisamples)) { + // The existence of a lone keychain prompt gives UI access + return true; + } + + samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, uisamples); + samples().collect(CSSM_SAMPLE_TYPE_THRESHOLD, uisamples); + + for (list::iterator it = uisamples.begin(); it != uisamples.end(); it++) { + TypedList &sample = *it; + + if(!sample.isProper()) { + secdebugfunc("integrity", "found a non-proper sample, skipping..."); + continue; + } + + switch (sample.type()) { + case CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT: + // these credentials allow UI + return true; + } + } + + // no interesting credential found; no UI for you + return false; +} // // AutoCredentials self-constructing credentials structure diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h index e0e8aae3..1b70b767 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmcred.h @@ -97,7 +97,10 @@ public: // pass-throughs to our SampleGroup uint32 size() const { return samples().size(); } CssmSample &operator [] (uint32 ix) const { return samples()[ix]; } - + + // Do these access credentials allow you to pop ui? + bool authorizesUI() const; + public: static const AccessCredentials &null; // all null credential diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp index e3546459..58b6f781 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp @@ -26,6 +26,9 @@ // // #include +#include + +using namespace DataWalkers; bool DLDbIdentifier::Impl::operator < (const DLDbIdentifier::Impl &other) const { @@ -552,6 +555,21 @@ CssmAutoDbRecordAttributeData::add(const CSSM_DB_ATTRIBUTE_INFO &info, const Css return anAttr; } +void +CssmAutoDbRecordAttributeData::updateWith(const CssmAutoDbRecordAttributeData* newValues) { + if(!newValues) { + return; + } + for(int i = 0; i < newValues->size(); i++) { + CssmDbAttributeData& c = newValues->at(i); + CssmDbAttributeData& target = add(c.info()); + + target.info(c.info()); + target.copyValues(c, mValueAllocator); + //.set(c, mValueAllocator); + } +} + // // CssmAutoQuery // diff --git a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h index 5ecb5a29..186e7669 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h +++ b/OSX/libsecurity_cdsa_utilities/lib/cssmdb.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include @@ -518,12 +518,16 @@ public: CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info); CssmDbAttributeData &add(const CSSM_DB_ATTRIBUTE_INFO &info, const CssmPolyData &value); + // Take the attributes from the object, and overlay them onto this one + void updateWith(const CssmAutoDbRecordAttributeData* newValues); + // So clients can pass this as the allocator argument to add() operator Allocator &() const { return mValueAllocator; } + + CssmDbAttributeData* findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info); private: Allocator &mValueAllocator; - - CssmDbAttributeData* findAttribute (const CSSM_DB_ATTRIBUTE_INFO &info); + CssmDbAttributeData& getAttributeReference (const CSSM_DB_ATTRIBUTE_INFO &info); }; diff --git a/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp b/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp index c89cb273..90f8d484 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp +++ b/OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp @@ -90,21 +90,6 @@ ObjectAcl::Entry::~Entry() // Returns normally if 'auth' is granted to the bearer of 'cred'. // Otherwise, throws a suitable (ACL-related) CssmError exception. // -class BaseValidationContext : public AclValidationContext { -public: - BaseValidationContext(const AccessCredentials *cred, - AclAuthorization auth, AclValidationEnvironment *env) - : AclValidationContext(cred, auth, env) { } - - uint32 count() const { return cred() ? cred()->samples().length() : 0; } - uint32 size() const { return count(); } - const TypedList &sample(uint32 n) const - { assert(n < count()); return cred()->samples()[n]; } - - void matched(const TypedList *) const { } // ignore match info -}; - - bool ObjectAcl::validates(AclAuthorization auth, const AccessCredentials *cred, AclValidationEnvironment *env) { @@ -123,14 +108,17 @@ bool ObjectAcl::validates(AclValidationContext &ctx) #if defined(ACL_OMNIPOTENT_OWNER) // try owner (owner can do anything) - if (mOwner.validate(ctx)) + if (mOwner.validates(ctx)) return; #endif //ACL_OMNIPOTENT_OWNER // try applicable ACLs pair range; - if (getRange(ctx.s_credTag(), range) == 0) // no such tag + if (getRange(ctx.s_credTag(), range) == 0) { + // no such tag + secdebugfunc("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 for (EntryMap::const_iterator it = range.first; it != range.second; it++) { const AclEntry &slot = it->second; @@ -138,7 +126,7 @@ bool ObjectAcl::validates(AclValidationContext &ctx) if (slot.authorizes(ctx.authorization())) { ctx.init(this, slot.subject); ctx.entryTag(slot.tag); - if (slot.validate(ctx)) { + if (slot.validates(ctx)) { IFDUMPING("acleval", Debug::dump(">PASS>>\n")); return true; // passed } @@ -175,7 +163,7 @@ void ObjectAcl::validateOwner(AclValidationContext &ctx) instantiateAcl(); ctx.init(this, mOwner.subject); - if (mOwner.validate(ctx)) + if (mOwner.validates(ctx)) return; CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); } @@ -258,15 +246,17 @@ void ObjectAcl::changedAcl() // ACL utility methods // unsigned int ObjectAcl::getRange(const std::string &tag, - pair &range) const + 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()); range = mEntries.equal_range(tag); unsigned int count = (unsigned int)mEntries.count(tag); - if (count == 0) - CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_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"); range.first = mEntries.begin(); range.second = mEntries.end(); return (unsigned int)mEntries.size(); @@ -292,15 +282,19 @@ void ObjectAcl::cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls) count = getRange(tag ? tag : "", range); acls = allocator.alloc(count); uint32 n = 0; + + secdebugfunc("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); } count = n; } void ObjectAcl::cssmChangeAcl(const AclEdit &edit, - const AccessCredentials *cred, AclValidationEnvironment *env) + const AccessCredentials *cred, AclValidationEnvironment *env, const char *preserveTag) { IFDUMPING("acl", debugDump("acl-change-from")); @@ -309,26 +303,49 @@ void ObjectAcl::cssmChangeAcl(const AclEdit &edit, // validate access credentials validateOwner(CSSM_ACL_AUTHORIZATION_CHANGE_ACL, cred, env); - + // 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); 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); } 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); // 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); + 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); mEntries.erase(it); } break; - case CSSM_ACL_EDIT_MODE_DELETE: - mEntries.erase(findEntryHandle(edit.OldEntryHandle)); + case CSSM_ACL_EDIT_MODE_DELETE: { + secdebugfunc("SecAccess", "deleting ACL for %p (%d) 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); + + mEntries.erase(it); break; + } default: + secdebugfunc("SecAccess", "no idea what this CSSM_ACL_EDIT type is: %d", edit.EditMode); CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_EDIT_MODE); } @@ -343,6 +360,8 @@ void ObjectAcl::cssmGetOwner(AclOwnerPrototype &outOwner) instantiateAcl(); outOwner.TypedSubject = mOwner.subject->toList(allocator); outOwner.Delegate = mOwner.delegate; + + secdebugfunc("SecAccess", "%p: getting the owner ACL: type %d", this, outOwner.TypedSubject.Head->WordID); } void ObjectAcl::cssmChangeOwner(const AclOwnerPrototype &newOwner, @@ -357,6 +376,8 @@ 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); changedAcl(); @@ -413,6 +434,7 @@ void ObjectAcl::add(const std::string &tag, const AclEntry &newEntry) void ObjectAcl::add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle) { + newEntry.tag = tag; //@@@ This should use a hook-registry mechanism. But for now, we are explicit: if (!newEntry.authorizesAnything) { for (AclAuthorizationSet::const_iterator it = newEntry.authorizations.begin(); @@ -460,9 +482,12 @@ bool ObjectAcl::OwnerEntry::authorizes(AclAuthorization) const return true; // owner can do anything } -bool ObjectAcl::OwnerEntry::validate(const AclValidationContext &ctx) const +bool ObjectAcl::OwnerEntry::validates(const AclValidationContext &ctx) const { - return subject->validate(ctx); // simple subject match - no strings attached + if (AclValidationEnvironment* env = ctx.environment()) + if (env->forceSuccess) + return true; + return subject->validates(ctx); // simple subject match - no strings attached } @@ -507,12 +532,19 @@ bool ObjectAcl::AclEntry::authorizes(AclAuthorization auth) const return authorizesAnything || authorizations.find(auth) != authorizations.end(); } -bool ObjectAcl::AclEntry::validate(const AclValidationContext &ctx) const +bool ObjectAcl::AclEntry::validates(const AclValidationContext &ctx) const { //@@@ not checking time ranges - return subject->validate(ctx); + return subject->validates(ctx); } +void ObjectAcl::AclEntry::addAuthorization(AclAuthorization auth) +{ + authorizations.insert(auth); + authorizesAnything = false; +} + + void ObjectAcl::AclEntry::importBlob(Reader &pub, Reader &priv) { Entry::importBlob(pub, priv); diff --git a/OSX/libsecurity_cdsa_utilities/lib/objectacl.h b/OSX/libsecurity_cdsa_utilities/lib/objectacl.h index c1d08253..78a08bf7 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/objectacl.h +++ b/OSX/libsecurity_cdsa_utilities/lib/objectacl.h @@ -88,7 +88,7 @@ public: // (Gets are not const because underlying implementations usually want them writable) void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls); void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred, - AclValidationEnvironment *env = NULL); + AclValidationEnvironment *env = NULL, const char *preserveTag = NULL); void cssmGetOwner(AclOwnerPrototype &owner); void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred, AclValidationEnvironment *env = NULL); @@ -122,7 +122,7 @@ public: Allocator &alloc) const; // encode copy in CSSM format virtual bool authorizes(AclAuthorization auth) const = 0; - virtual bool validate(const AclValidationContext &ctx) const = 0; + virtual bool validates(const AclValidationContext &ctx) const = 0; template void exportBlob(Action &pub, Action &priv) @@ -152,7 +152,7 @@ public: OwnerEntry(const Input &owner) : Entry(owner) { } bool authorizes(AclAuthorization auth) const; - bool validate(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &ctx) const; }; class AclEntry : public Entry { @@ -171,8 +171,10 @@ public: Allocator &alloc) const; // encode copy in CSSM format bool authorizes(AclAuthorization auth) const; - bool validate(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &ctx) const; + void addAuthorization(AclAuthorization auth); + template void exportBlob(Action &pub, Action &priv) { @@ -214,7 +216,7 @@ public: EntryMap::const_iterator end() const { return mEntries.end(); } unsigned int getRange(const std::string &tag, - pair &range) const; + pair &range, bool tolerant = false) const; EntryMap::iterator findEntryHandle(CSSM_ACL_HANDLE handle); // construct an AclSubject through the Maker registry (by subject type) @@ -227,7 +229,7 @@ protected: void owner(const Input &input); void entries(uint32 count, const AclEntryInfo *infos); -private: +public: void add(const std::string &tag, const AclEntry &newEntry); void add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle); diff --git a/OSX/libsecurity_cdsa_utilities/lib/walkers.h b/OSX/libsecurity_cdsa_utilities/lib/walkers.h index 6178a359..b8fcb598 100644 --- a/OSX/libsecurity_cdsa_utilities/lib/walkers.h +++ b/OSX/libsecurity_cdsa_utilities/lib/walkers.h @@ -121,6 +121,7 @@ public: }; + // // Walk a structure and apply a constant linear shift to all pointers // encountered. This is useful when a structure and its deep components diff --git a/OSX/libsecurity_cms/lib/CMSDecoder.cpp b/OSX/libsecurity_cms/lib/CMSDecoder.cpp index a420e5eb..a8d81d09 100644 --- a/OSX/libsecurity_cms/lib/CMSDecoder.cpp +++ b/OSX/libsecurity_cms/lib/CMSDecoder.cpp @@ -999,3 +999,47 @@ OSStatus CMSDecoderCopySignerTimestampCertificates( xit: return status; } + +/* + * Obtain the Hash Agility attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue) /* RETURNED */ +{ + OSStatus status = errSecParam; + SecCmsMessageRef cmsg; + SecCmsSignedDataRef signedData = NULL; + int numContentInfos = 0; + CFDataRef returnedValue = NULL; + + require(cmsDecoder && hashAgilityAttrValue, xit); + require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit); + numContentInfos = SecCmsMessageContentLevelCount(cmsg); + for (int dex = 0; !signedData && dex < numContentInfos; dex++) + { + SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex); + SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci); + if (tag == SEC_OID_PKCS7_SIGNED_DATA) + if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci)))) + if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex)) + { + status = SecCmsSignerInfoGetAppleCodesigningHashAgility(signerInfo, &returnedValue); + break; + } + } +xit: + if (status == errSecSuccess && returnedValue) { + *hashAgilityAttrValue = (CFDataRef) CFRetain(returnedValue); + } else { + *hashAgilityAttrValue = NULL; + } + return status; +} diff --git a/OSX/libsecurity_cms/lib/CMSEncoder.cpp b/OSX/libsecurity_cms/lib/CMSEncoder.cpp index c60110c7..4055192a 100644 --- a/OSX/libsecurity_cms/lib/CMSEncoder.cpp +++ b/OSX/libsecurity_cms/lib/CMSEncoder.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,7 @@ struct _CMSEncoder { SECOidTag digestalgtag; CMSCertificateChainMode chainMode; + CFDataRef hashAgilityAttrValue; }; static void cmsEncoderInit(CFTypeRef enc); @@ -525,6 +527,16 @@ static OSStatus cmsSetupForSignedData( break; } } + if(cmsEncoder->signedAttributes & kCMSAttrAppleCodesigningHashAgility) { + ortn = SecCmsSignerInfoAddAppleCodesigningHashAgility(signerInfo, cmsEncoder->hashAgilityAttrValue); + /* libsecurity_smime made a copy of the attribute value. We don't need it anymore. */ + CFReleaseNull(cmsEncoder->hashAgilityAttrValue); + if(ortn) { + ortn = cmsRtnToOSStatus(ortn); + CSSM_PERROR("SecCmsSignerInfoAddAppleCodesigningHashAgility", ortn); + break; + } + } ortn = SecCmsSignedDataAddSignerInfo(signedData, signerInfo); if(ortn) { @@ -982,7 +994,7 @@ OSStatus CMSEncoderAddSignedAttributes( if(cmsEncoder->encState != ES_Init) { return errSecParam; } - cmsEncoder->signedAttributes = signedAttributes; + cmsEncoder->signedAttributes |= signedAttributes; return errSecSuccess; } @@ -1004,6 +1016,21 @@ OSStatus CMSEncoderSetSigningTime( return errSecSuccess; } +/* + * Set the hash agility attribute for a CMSEncoder. + * This is only used if the kCMSAttrAppleCodesigningHashAgility attribute + * is included. + */ +OSStatus CMSEncoderSetAppleCodesigningHashAgility( + CMSEncoderRef cmsEncoder, + CFDataRef hashAgilityAttrValue) +{ + if (cmsEncoder == NULL || cmsEncoder->encState != ES_Init) { + return errSecParam; + } + cmsEncoder->hashAgilityAttrValue = CFRetainSafe(hashAgilityAttrValue); + return errSecSuccess; +} OSStatus CMSEncoderSetCertificateChainMode( CMSEncoderRef cmsEncoder, diff --git a/OSX/libsecurity_cms/lib/CMSEncoder.h b/OSX/libsecurity_cms/lib/CMSEncoder.h index 955989bb..f24227b2 100644 --- a/OSX/libsecurity_cms/lib/CMSEncoder.h +++ b/OSX/libsecurity_cms/lib/CMSEncoder.h @@ -262,7 +262,11 @@ typedef CF_ENUM(uint32_t, CMSSignedAttributes) { /* * Include the signing time. */ - kCMSAttrSigningTime = 0x0008 + kCMSAttrSigningTime = 0x0008, + /* + * Include the Apple Codesigning Hash Agility. + */ + kCMSAttrAppleCodesigningHashAgility = 0x0010 }; /* diff --git a/OSX/libsecurity_cms/lib/CMSPrivate.h b/OSX/libsecurity_cms/lib/CMSPrivate.h index 3b90d51a..b61296b2 100644 --- a/OSX/libsecurity_cms/lib/CMSPrivate.h +++ b/OSX/libsecurity_cms/lib/CMSPrivate.h @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -82,6 +83,15 @@ OSStatus CMSEncoderSetSigningTime( CMSEncoderRef cmsEncoder, CFAbsoluteTime time); +/* + * Set the hash agility attribute for a CMSEncoder. + * This is only used if the kCMSAttrAppleCodesigningHashAgility attribute + * is included. + */ +OSStatus CMSEncoderSetAppleCodesigningHashAgility( + CMSEncoderRef cmsEncoder, + CFDataRef hashAgilityAttrValue); + void CmsMessageSetTSAContext(CMSEncoderRef cmsEncoder, CFTypeRef tsaContext); @@ -123,6 +133,20 @@ OSStatus CMSDecoderSetDecoder( OSStatus CMSDecoderGetDecoder( CMSDecoderRef cmsDecoder, SecCmsDecoderRef *decoder); /* RETURNED */ + +/* + * Obtain the Hash Agility attribute value of signer 'signerIndex' + * of a CMS message, if present. + * + * Returns errSecParam if the CMS message was not signed or if signerIndex + * is greater than the number of signers of the message minus one. + * + * This cannot be called until after CMSDecoderFinalizeMessage() is called. + */ +OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility( + CMSDecoderRef cmsDecoder, + size_t signerIndex, /* usually 0 */ + CFDataRef CF_RETURNS_RETAINED *hashAgilityAttrValue); /* RETURNED */ #ifdef __cplusplus } diff --git a/OSX/libsecurity_cms/lib/security_cms.exp b/OSX/libsecurity_cms/lib/security_cms.exp index c416c46a..81256d88 100644 --- a/OSX/libsecurity_cms/lib/security_cms.exp +++ b/OSX/libsecurity_cms/lib/security_cms.exp @@ -19,6 +19,7 @@ _CMSEncoderSetEncapsulatedContentTypeOID _CMSEncoderSetEncoder _CMSEncoderAddSignedAttributes _CMSEncoderSetSigningTime +_CMSEncoderSetAppleCodesigningHashAgility _CMSEncoderSetCertificateChainMode _CMSEncoderGetCertificateChainMode _CMSEncoderUpdateContent @@ -46,5 +47,6 @@ _CMSDecoderCopySignerTimestampWithPolicy _CMSDecoderCopySignerTimestampCertificates _CMSEncoderCopySignerTimestamp _CMSEncoderCopySignerTimestampWithPolicy +_CMSDecoderCopySignerAppleCodesigningHashAgility diff --git a/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj b/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj index 5963aa79..8900beec 100644 --- a/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj @@ -14,6 +14,9 @@ 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 */; }; + 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 */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -30,6 +33,10 @@ 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 = ""; }; + 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 = ""; }; + D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cms-hashagility-test.h"; path = "regressions/cms-hashagility-test.h"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -40,6 +47,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4C334591BE2A2B100D8C1EF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -73,6 +87,7 @@ 4CA1FEA7052A3C3800F22E42 = { isa = PBXGroup; children = ( + D4C334561BE29F1700D8C1EF /* regressions */, 4C308388053237100028A8C6 /* lib */, 18446176146E984400B12992 /* config */, 4CA1FEBF052A3C8100F22E42 /* Products */, @@ -83,10 +98,21 @@ isa = PBXGroup; children = ( 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */, + D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */, ); name = Products; sourceTree = ""; }; + D4C334561BE29F1700D8C1EF /* regressions */ = { + isa = PBXGroup; + children = ( + D4C334571BE29F5200D8C1EF /* cms_regressions.h */, + D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */, + D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */, + ); + name = regressions; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -101,6 +127,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4C3345A1BE2A2B100D8C1EF /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D4C334641BE2A31200D8C1EF /* cms-hashagility-test.h in Headers */, + D4C334601BE2A2B900D8C1EF /* cms_regressions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -121,6 +156,23 @@ productReference = 4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */; productType = "com.apple.product-type.library.static"; }; + D4C3345B1BE2A2B100D8C1EF /* libsecurity_cms_regressions */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4C3345D1BE2A2B100D8C1EF /* Build configuration list for PBXNativeTarget "libsecurity_cms_regressions" */; + buildPhases = ( + D4C334581BE2A2B100D8C1EF /* Sources */, + D4C334591BE2A2B100D8C1EF /* Frameworks */, + D4C3345A1BE2A2B100D8C1EF /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = libsecurity_cms_regressions; + productName = libsecurity_cms_regressions; + productReference = D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -128,6 +180,11 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0700; + TargetAttributes = { + D4C3345B1BE2A2B100D8C1EF = { + CreatedOnToolsVersion = 7.1; + }; + }; }; buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_cms" */; compatibilityVersion = "Xcode 3.2"; @@ -142,6 +199,7 @@ projectRoot = ""; targets = ( 4CA1FEBD052A3C8100F22E42 /* libsecurity_cms */, + D4C3345B1BE2A2B100D8C1EF /* libsecurity_cms_regressions */, ); }; /* End PBXProject section */ @@ -157,6 +215,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4C334581BE2A2B100D8C1EF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4C334631BE2A31200D8C1EF /* cms-hashagility-test.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -204,6 +270,71 @@ }; name = Release; }; + D4C3345E1BE2A2B100D8C1EF /* 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_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "-"; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + 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; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + D4C3345F1BE2A2B100D8C1EF /* 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_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = "-"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -225,6 +356,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D4C3345D1BE2A2B100D8C1EF /* Build configuration list for PBXNativeTarget "libsecurity_cms_regressions" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D4C3345E1BE2A2B100D8C1EF /* Debug */, + D4C3345F1BE2A2B100D8C1EF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 4CA1FEAB052A3C3800F22E42 /* Project object */; diff --git a/OSX/libsecurity_cms/regressions/cms-hashagility-test.c b/OSX/libsecurity_cms/regressions/cms-hashagility-test.c new file mode 100644 index 00000000..3024ca49 --- /dev/null +++ b/OSX/libsecurity_cms/regressions/cms-hashagility-test.c @@ -0,0 +1,231 @@ +/* + * 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 "cms-hashagility-test.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TMP_KEYCHAIN_PATH "/tmp/cms_signer.keychain" + +/* encode test */ +static void encode_test(void) +{ + CMSEncoderRef encoder = NULL; + CFDataRef attributeData = NULL, message = NULL, p12Data = NULL; + CFArrayRef imported_items = NULL; + SecIdentityRef identity = NULL; + SecKeychainRef keychain = NULL; + SecExternalFormat sef = kSecFormatPKCS12; + SecItemImportExportKeyParameters keyParams = { + .passphrase = CFSTR("password") + }; + + /* Create encoder */ + ok_status(CMSEncoderCreate(&encoder), "Create CMS encoder"); + ok_status(CMSEncoderSetSignerAlgorithm(encoder, kCMSEncoderDigestAlgorithmSHA256), + "Set digest algorithm to SHA256"); + + /* Load identity and set as signer */ + 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)), + "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(CMSEncoderAddSigners(encoder, identity), "Set Signer identity"); + + /* Add signing time attribute for 3 November 2015 */ + ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrSigningTime), + "Set signing time flag"); + ok_status(CMSEncoderSetSigningTime(encoder, 468295000.0), "Set Signing time"); + + /* Add hash agility attribute */ + ok_status(CMSEncoderAddSignedAttributes(encoder, kCMSAttrAppleCodesigningHashAgility), + "Set hash agility flag"); + ok(attributeData = CFDataCreate(NULL, attribute, sizeof(attribute)), + "Create atttribute object"); + ok_status(CMSEncoderSetAppleCodesigningHashAgility(encoder, attributeData), + "Set hash agility data"); + + /* Load content */ + ok_status(CMSEncoderSetHasDetachedContent(encoder, true), "Set detached content"); + ok_status(CMSEncoderUpdateContent(encoder, content, sizeof(content)), "Set content"); + + /* output cms message */ + ok_status(CMSEncoderCopyEncodedContent(encoder, &message), "Finish encoding and output message"); + + /* decode message */ + CMSDecoderRef decoder = NULL; + CFDataRef contentData = NULL; + isnt(message, NULL, "Encoded message exists"); + ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); + ok_status(CMSDecoderUpdateMessage(decoder, CFDataGetBytePtr(message), CFDataGetLength(message)), + "Update decoder with CMS message"); + ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); + ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); + ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); + + /* Cleanup */ + ok_status(SecKeychainDelete(keychain), "Delete temporary keychain"); + + CFReleaseNull(encoder); + CFReleaseNull(keychain); + CFReleaseNull(p12Data); + CFReleaseNull(imported_items); + CFReleaseNull(identity); + CFReleaseNull(attributeData); + CFReleaseNull(message); + CFReleaseNull(decoder); + CFReleaseNull(contentData); +} + +static void decode_positive_test(void) +{ + CMSDecoderRef decoder = NULL; + CFDataRef contentData = NULL, attrValue = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CMSSignerStatus signerStatus; + CFAbsoluteTime signingTime = 0.0; + + /* Create decoder and decode */ + ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); + ok_status(CMSDecoderUpdateMessage(decoder, valid_message, sizeof(valid_message)), + "Update decoder with CMS message"); + ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); + ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); + ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); + + /* Get signer status */ + ok(policy = SecPolicyCreateBasicX509(), "Create policy"); + ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL), + "Copy Signer status"); + is(signerStatus, kCMSSignerValid, "Valid signature"); + + /* Get Hash Agility Attribute value */ + ok_status(CMSDecoderCopySignerAppleCodesigningHashAgility(decoder, 0, &attrValue), + "Copy hash agility attribute value"); + is(CFDataGetLength(attrValue), sizeof(attribute), "Decoded attribute size"); + is(memcmp(attribute, CFDataGetBytePtr(attrValue), sizeof(attribute)), 0, + "Decoded value same as input value"); + + /* Get Signing Time Attribute value */ + ok_status(CMSDecoderCopySignerSigningTime(decoder, 0, &signingTime), + "Copy signing time attribute value"); + is(signingTime, 468295000.0, "Decoded date same as input date"); + + CFReleaseNull(decoder); + CFReleaseNull(contentData); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(attrValue); +} + +static void decode_negative_test(void) +{ + CMSDecoderRef decoder = NULL; + CFDataRef contentData = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CMSSignerStatus signerStatus; + + /* Create decoder and decode */ + ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); + ok_status(CMSDecoderUpdateMessage(decoder, invalid_message, sizeof(invalid_message)), + "Update decoder with CMS message"); + ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); + ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); + ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); + + /* Get signer status */ + ok(policy = SecPolicyCreateBasicX509(), "Create policy"); + ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL), + "Copy Signer status"); + is(signerStatus, kCMSSignerInvalidSignature, "Invalid signature"); + + CFReleaseNull(decoder); + CFReleaseNull(contentData); + CFReleaseNull(policy); + CFReleaseNull(trust); +} + +static void decode_no_attr_test(void) +{ + CMSDecoderRef decoder = NULL; + CFDataRef contentData = NULL, attrValue = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CMSSignerStatus signerStatus; + + /* Create decoder and decode */ + ok_status(CMSDecoderCreate(&decoder), "Create CMS decoder"); + ok_status(CMSDecoderUpdateMessage(decoder, valid_no_attr, sizeof(valid_no_attr)), + "Update decoder with CMS message"); + ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); + ok_status(CMSDecoderSetDetachedContent(decoder, contentData), "Set detached content"); + ok_status(CMSDecoderFinalizeMessage(decoder), "Finalize decoder"); + + /* Get signer status */ + ok(policy = SecPolicyCreateBasicX509(), "Create policy"); + ok_status(CMSDecoderCopySignerStatus(decoder, 0, policy, false, &signerStatus, &trust, NULL), + "Copy Signer status"); + is(signerStatus, kCMSSignerValid, "Valid signature"); + + /* Get Hash Agility Attribute value */ + ok_status(CMSDecoderCopySignerAppleCodesigningHashAgility(decoder, 0, &attrValue), + "Copy empty hash agility attribute value"); + is(attrValue, NULL, "NULL attribute value"); + + CFReleaseNull(decoder); + CFReleaseNull(contentData); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(attrValue); +} + +int cms_hash_agility_test(int argc, char *const *argv) +{ + plan_tests(24+13+8+10); + + encode_test(); + decode_positive_test(); + decode_negative_test(); + decode_no_attr_test(); + + return 0; +} diff --git a/OSX/libsecurity_cms/regressions/cms-hashagility-test.h b/OSX/libsecurity_cms/regressions/cms-hashagility-test.h new file mode 100644 index 00000000..24055e72 --- /dev/null +++ b/OSX/libsecurity_cms/regressions/cms-hashagility-test.h @@ -0,0 +1,839 @@ +/* + * 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 cms_hashagility_test_h +#define cms_hashagility_test_h + +#include + +int cms_hash_agility_test(int argc, char *const *argv); + +/* + * password: "password" + * localKeyID: 01 AE 1A 61 75 AE 23 D9 11 5C 28 93 A9 E2 49 5E 74 28 4C 08 + * subject=/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering and Architecture/CN=CMS Test Signer + * issuer=/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering and Architecture/CN=CMS Test Signer + */ +unsigned char signing_identity_p12[4477] = { + 0x30, 0x82, 0x11, 0x79, 0x02, 0x01, 0x03, 0x30, 0x82, 0x11, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01, 0xa0, 0x82, 0x11, 0x30, 0x04, 0x82, 0x11, 0x2c, 0x30, 0x82, 0x11, 0x28, 0x30, 0x82, 0x07, 0x57, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06, 0xa0, 0x82, 0x07, 0x48, 0x30, 0x82, 0x07, 0x44, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x07, 0x3d, 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, 0xed, 0xd8, 0x65, 0x57, 0xbb, 0xca, 0x25, + 0x46, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x07, 0x10, 0xc0, 0x1d, 0x0d, 0x5c, 0x7f, 0x3b, 0xbe, 0x20, 0xd4, 0x9a, 0x0d, + 0xaf, 0xb6, 0x4b, 0xc7, 0x7f, 0xa8, 0xa8, 0x3f, 0x6c, 0x96, 0x1c, 0xea, 0x90, 0xd2, 0x79, 0x9f, 0x56, 0x3a, 0x5a, 0x29, + 0x93, 0xff, 0x72, 0x39, 0x9e, 0x41, 0xd9, 0x5a, 0xfc, 0xb5, 0x54, 0x2d, 0x89, 0x60, 0x18, 0xf2, 0xea, 0x8c, 0xeb, 0x7f, + 0xba, 0x87, 0xc6, 0x70, 0x42, 0x25, 0x55, 0x24, 0xc5, 0x4f, 0x26, 0x66, 0x8d, 0x78, 0x44, 0x47, 0x85, 0x36, 0x53, 0x86, + 0xc9, 0x18, 0x83, 0x33, 0x4b, 0x4b, 0x08, 0x2d, 0x7b, 0x68, 0x37, 0x29, 0x4c, 0x20, 0x74, 0xd4, 0x4f, 0xbb, 0x6e, 0x97, + 0x7a, 0xf4, 0xbf, 0xcb, 0x40, 0x26, 0x2d, 0xac, 0x95, 0x82, 0xe0, 0x88, 0xfe, 0x54, 0x80, 0xe9, 0xf5, 0xda, 0x8e, 0x6e, + 0x3a, 0x47, 0x2d, 0xc8, 0xd4, 0xe7, 0x2e, 0xff, 0xec, 0xfa, 0xa5, 0x70, 0xcd, 0x2e, 0x99, 0x26, 0x32, 0xc8, 0x1d, 0x53, + 0x60, 0x1e, 0x6f, 0x68, 0xcb, 0x49, 0xd0, 0xa2, 0xf8, 0x47, 0x70, 0x1b, 0x9e, 0x85, 0xbe, 0x4e, 0x56, 0xb5, 0x8b, 0x66, + 0x45, 0x57, 0xe3, 0xbd, 0x57, 0xed, 0x94, 0x53, 0xf6, 0x72, 0xd7, 0xb7, 0xc6, 0x9f, 0x05, 0xf5, 0x98, 0xb4, 0x13, 0x35, + 0x69, 0x24, 0x94, 0xd9, 0x3d, 0x80, 0xbc, 0xa8, 0xea, 0x78, 0x0c, 0xe0, 0xa2, 0xfe, 0x1b, 0xd2, 0x82, 0x3d, 0x83, 0x34, + 0x76, 0xb4, 0x45, 0xf8, 0x14, 0x09, 0x66, 0x02, 0x68, 0xc3, 0x1b, 0xcb, 0x6c, 0x91, 0x6b, 0x3e, 0xdc, 0x35, 0x68, 0xab, + 0x49, 0x47, 0x6c, 0x60, 0xea, 0xe3, 0xd5, 0x59, 0x82, 0x9c, 0x18, 0xb0, 0x6d, 0x45, 0xc0, 0x2f, 0x58, 0xf1, 0x44, 0x79, + 0xe3, 0xd2, 0xd6, 0x16, 0xbc, 0xde, 0x17, 0xae, 0xf7, 0xea, 0x3c, 0xe4, 0xb4, 0x7b, 0xdf, 0xba, 0x9b, 0xf1, 0xb8, 0xa8, + 0xb0, 0x51, 0xeb, 0xe8, 0xc3, 0xe9, 0x9c, 0x1b, 0x06, 0xdd, 0x89, 0x07, 0x98, 0xf8, 0x01, 0x7f, 0xde, 0x7e, 0x05, 0xa6, + 0x72, 0x0b, 0x3f, 0xf4, 0x7d, 0xca, 0x74, 0x7b, 0xc9, 0x87, 0x0d, 0x35, 0x8b, 0x05, 0x3a, 0x73, 0x04, 0x08, 0x7a, 0x51, + 0x34, 0x29, 0x5b, 0xd8, 0x90, 0x0f, 0xa7, 0xf0, 0x48, 0xfc, 0x9c, 0x74, 0xca, 0xe9, 0x34, 0x75, 0x1c, 0xd1, 0xa6, 0xd1, + 0xfb, 0x9f, 0xc7, 0x82, 0x40, 0x75, 0x87, 0xdd, 0xa2, 0x22, 0xeb, 0x91, 0xd7, 0x85, 0x1a, 0x2c, 0xa7, 0x3d, 0xd5, 0xe4, + 0xca, 0x85, 0x00, 0x33, 0x11, 0x6d, 0x62, 0xa8, 0xb7, 0xd3, 0x45, 0x46, 0xdc, 0xb4, 0xa3, 0xeb, 0xae, 0x5e, 0x8c, 0xc2, + 0x7a, 0x0b, 0x83, 0x98, 0x5a, 0x94, 0x0f, 0x68, 0x61, 0x36, 0x57, 0x6e, 0x94, 0xe0, 0x6d, 0x93, 0x76, 0xa0, 0x5d, 0x3f, + 0x25, 0x8b, 0x3b, 0x46, 0x1e, 0x0c, 0x15, 0x6b, 0x9f, 0x1d, 0xc3, 0x5f, 0x61, 0x42, 0xd5, 0xf8, 0x79, 0xcd, 0xd1, 0x0a, + 0x96, 0xce, 0x49, 0x8a, 0xff, 0x54, 0x46, 0x77, 0x65, 0x37, 0x70, 0xcd, 0x65, 0x6f, 0x3d, 0x49, 0xc1, 0x29, 0x8d, 0x16, + 0xbd, 0x36, 0x47, 0x54, 0xa5, 0x4d, 0x06, 0xfb, 0x33, 0x00, 0x29, 0xd8, 0x31, 0x09, 0x58, 0x12, 0x4c, 0xfe, 0xef, 0x8e, + 0xf9, 0x1e, 0x30, 0xf7, 0x05, 0xb2, 0xd8, 0xd4, 0x7d, 0xae, 0xab, 0x57, 0xb7, 0x46, 0x09, 0xff, 0xca, 0xc7, 0x7b, 0xca, + 0x73, 0xfa, 0xf9, 0x50, 0xa0, 0xb8, 0x09, 0xc2, 0x80, 0x43, 0x0d, 0x99, 0x7f, 0x4e, 0xdf, 0xd5, 0x6c, 0xc4, 0x42, 0x1a, + 0x05, 0xbd, 0x65, 0xf4, 0x57, 0x2a, 0xe5, 0xc4, 0xcb, 0x79, 0x3f, 0x8f, 0x74, 0x93, 0x66, 0x8d, 0x93, 0xda, 0xba, 0x23, + 0x77, 0x3f, 0xad, 0xd3, 0x8b, 0xae, 0xf5, 0xf1, 0x5c, 0xc1, 0xd2, 0x00, 0x3a, 0x60, 0x8e, 0xc3, 0x32, 0xd6, 0x8e, 0xce, + 0x95, 0x24, 0x03, 0x79, 0x03, 0xf2, 0xb8, 0x2a, 0x94, 0xeb, 0x15, 0x97, 0xdc, 0x18, 0x8d, 0xc7, 0xd9, 0xc2, 0x63, 0x69, + 0xfb, 0xf9, 0x8f, 0x05, 0xd3, 0x7c, 0x60, 0x5a, 0x57, 0xe4, 0xa5, 0xc1, 0xdf, 0x1d, 0x11, 0x84, 0x69, 0xba, 0x20, 0xd8, + 0x79, 0xc3, 0x34, 0x3a, 0xb1, 0x63, 0x4c, 0xd2, 0x91, 0x2d, 0x87, 0x1e, 0xec, 0x06, 0xea, 0x35, 0x97, 0x0e, 0x59, 0x54, + 0x83, 0x50, 0x3e, 0xac, 0xf2, 0xea, 0x6c, 0x0c, 0xa0, 0x57, 0xfb, 0xe8, 0x6b, 0xf9, 0xd1, 0x25, 0xc0, 0xa2, 0xb0, 0xa2, + 0xcd, 0xde, 0x2b, 0xa7, 0xb3, 0x40, 0x75, 0x36, 0xf7, 0x20, 0xbe, 0xd7, 0xd1, 0x2e, 0x66, 0xc5, 0x3c, 0xf8, 0x6e, 0xce, + 0xcb, 0x76, 0x7f, 0x1d, 0x32, 0x3b, 0x14, 0x27, 0x9c, 0x9e, 0xa3, 0xeb, 0x0c, 0x2f, 0x71, 0xba, 0x0d, 0xca, 0x27, 0x90, + 0x42, 0xfd, 0xd4, 0x34, 0xb9, 0x96, 0xae, 0xcb, 0xd8, 0xfe, 0x31, 0x62, 0xe8, 0x4c, 0x07, 0x71, 0xb9, 0x0c, 0x9f, 0xe2, + 0x8e, 0x66, 0xc2, 0x39, 0xc5, 0xc3, 0x1c, 0xfd, 0x5e, 0x18, 0x0b, 0xd4, 0x93, 0x3d, 0x98, 0x33, 0xaf, 0x6d, 0xb4, 0x6f, + 0xe6, 0x75, 0x67, 0x62, 0xe7, 0x42, 0xee, 0xc6, 0xf2, 0x2e, 0x21, 0xa9, 0x75, 0xde, 0x0a, 0x8c, 0x39, 0xb7, 0x4b, 0x54, + 0x01, 0xa7, 0xeb, 0x5a, 0x88, 0x79, 0xa8, 0xb3, 0x3f, 0x31, 0x8c, 0x47, 0x08, 0x94, 0x47, 0x52, 0xcf, 0x3c, 0xac, 0xd9, + 0x32, 0x57, 0x4a, 0x18, 0x55, 0x5b, 0x66, 0xdc, 0x89, 0xd2, 0xc6, 0xa1, 0x11, 0x40, 0x19, 0x9c, 0x46, 0x88, 0x21, 0x77, + 0xc1, 0x7f, 0x09, 0xc7, 0xfb, 0x52, 0x92, 0xec, 0x1a, 0xe0, 0xdd, 0x76, 0xb9, 0xfd, 0xa7, 0x8f, 0x61, 0xe3, 0xf0, 0x1b, + 0x4e, 0xdb, 0xa0, 0xde, 0x90, 0xd6, 0x49, 0xea, 0xe9, 0x86, 0xc6, 0x5d, 0xac, 0xd0, 0xc2, 0xc5, 0x01, 0xcb, 0x3f, 0xcb, + 0xf0, 0x62, 0x90, 0xa1, 0x17, 0x4b, 0x72, 0x5c, 0xc8, 0xe9, 0x24, 0x93, 0xda, 0x5c, 0x75, 0x24, 0x96, 0x35, 0x54, 0xf4, + 0xfa, 0xc8, 0x27, 0xe1, 0xdd, 0x32, 0xda, 0x2f, 0x2b, 0x7d, 0xf6, 0xd8, 0x0b, 0xf2, 0xca, 0xb5, 0xee, 0x8a, 0xcf, 0xb6, + 0x26, 0x71, 0x65, 0x85, 0xfe, 0x8c, 0x37, 0xf1, 0x17, 0x6b, 0x5e, 0x8a, 0xee, 0xb4, 0xc7, 0x0a, 0xff, 0xb2, 0x9a, 0x72, + 0xe5, 0x85, 0xf3, 0xc0, 0xf9, 0x84, 0xbc, 0xe0, 0x18, 0x3c, 0x12, 0x0c, 0xa1, 0xe9, 0x10, 0xd4, 0x3b, 0x1a, 0x21, 0x35, + 0xc6, 0x06, 0x93, 0xa0, 0xdf, 0x0d, 0x68, 0xa3, 0xf1, 0x06, 0xd9, 0xed, 0xb7, 0xa7, 0xba, 0xb0, 0x22, 0xc2, 0x0b, 0x6b, + 0x70, 0x50, 0xf5, 0x49, 0x9a, 0x4f, 0x99, 0xaa, 0x1e, 0x9c, 0xa6, 0xf3, 0x99, 0x3a, 0xfd, 0x3b, 0xd2, 0xeb, 0xce, 0x1e, + 0x72, 0x62, 0x99, 0xc0, 0x1e, 0x2b, 0x09, 0x75, 0x4a, 0xfb, 0xc8, 0x26, 0xcf, 0x76, 0xa2, 0x0e, 0xef, 0xf4, 0xa8, 0x70, + 0x31, 0xd8, 0xa1, 0x22, 0x62, 0xcc, 0x9f, 0xd5, 0xa3, 0x55, 0xc2, 0x78, 0xd7, 0x27, 0xfc, 0x3c, 0x53, 0xe8, 0xeb, 0x7e, + 0x7a, 0x27, 0xcf, 0x6d, 0x52, 0xb5, 0x9a, 0x2b, 0x49, 0x8d, 0x3f, 0x89, 0x80, 0x1a, 0x5c, 0x39, 0xe7, 0x53, 0xb3, 0xf3, + 0x33, 0x97, 0xcf, 0x7d, 0xfb, 0x8e, 0x19, 0xf4, 0x72, 0xeb, 0xe7, 0xdf, 0xb1, 0xe3, 0xc1, 0x6c, 0x7f, 0x17, 0x89, 0x34, + 0x4f, 0x45, 0x0f, 0xc5, 0xfc, 0x15, 0xb3, 0x3f, 0xc6, 0xdc, 0x25, 0xa6, 0xda, 0x28, 0x85, 0x5d, 0x25, 0x02, 0x78, 0x74, + 0xd9, 0x74, 0xb8, 0x65, 0x48, 0x3a, 0x8a, 0x2a, 0xd5, 0xa9, 0xb8, 0x7f, 0xaa, 0x9d, 0xe7, 0xaf, 0xbd, 0xdf, 0xfd, 0x00, + 0x67, 0xab, 0x39, 0xe1, 0x2c, 0x3d, 0xd1, 0x5c, 0x9b, 0x61, 0x2b, 0x51, 0xdc, 0x87, 0x19, 0x6c, 0xa0, 0x12, 0xd4, 0x60, + 0xed, 0x94, 0xe9, 0xeb, 0x4e, 0x51, 0xd8, 0x50, 0xcb, 0x97, 0x8a, 0x20, 0x21, 0xdf, 0xe9, 0x2c, 0xd2, 0xe2, 0x04, 0x14, + 0xaf, 0x7b, 0x7e, 0xd6, 0xeb, 0x1d, 0x25, 0x09, 0x98, 0x8e, 0x9e, 0x56, 0xf8, 0x7d, 0xfc, 0x0f, 0xbf, 0xd2, 0x6b, 0xbc, + 0xab, 0xed, 0xca, 0x43, 0x6d, 0x28, 0xbe, 0xd5, 0x20, 0x44, 0xcb, 0x6b, 0xbc, 0x80, 0x5a, 0x82, 0x13, 0x50, 0xbd, 0xda, + 0x18, 0x10, 0xac, 0xae, 0x56, 0xb9, 0x46, 0xc5, 0xa2, 0xca, 0xb2, 0x03, 0xf0, 0x57, 0xfe, 0xcd, 0x9a, 0x1b, 0x81, 0x6a, + 0x10, 0x51, 0x2e, 0x88, 0x30, 0x57, 0x3c, 0xfe, 0x7c, 0x56, 0x0c, 0x00, 0x89, 0x5c, 0x21, 0x57, 0x19, 0x96, 0x85, 0x98, + 0xeb, 0x43, 0x71, 0x0d, 0x8a, 0x35, 0xc3, 0xae, 0x36, 0x59, 0x72, 0x97, 0x12, 0x6d, 0xcd, 0x28, 0x64, 0x17, 0x9e, 0xe7, + 0x2c, 0x28, 0xfd, 0x32, 0xa8, 0x10, 0x67, 0x4e, 0xc0, 0x14, 0x21, 0x7c, 0x36, 0x20, 0xe9, 0x46, 0x68, 0x62, 0xc1, 0xff, + 0xb0, 0xdf, 0xaa, 0x87, 0xff, 0x94, 0xa4, 0xf3, 0xb3, 0xc8, 0x53, 0x57, 0x18, 0x92, 0x15, 0xc7, 0x78, 0x2d, 0x91, 0xba, + 0xb3, 0x1f, 0x06, 0x13, 0x79, 0x21, 0x86, 0x1d, 0xa2, 0x38, 0x2c, 0xda, 0x35, 0x31, 0xbb, 0x04, 0x65, 0xa3, 0x01, 0xa6, + 0x63, 0xa4, 0x4a, 0xa2, 0xc1, 0xad, 0x04, 0xc1, 0xfa, 0x78, 0xe1, 0xb6, 0x50, 0x46, 0xab, 0xad, 0x1c, 0xcf, 0xf4, 0xe5, + 0xba, 0xa5, 0xe2, 0x91, 0x29, 0x4b, 0xa1, 0xc6, 0x4b, 0x30, 0xa5, 0x31, 0x02, 0xe9, 0xd0, 0x50, 0x72, 0x2c, 0x8e, 0xbd, + 0xb2, 0x12, 0xd9, 0x4f, 0x7c, 0x87, 0x4b, 0xa0, 0x45, 0x71, 0x0c, 0x23, 0x37, 0x6b, 0x60, 0xd7, 0x9f, 0x19, 0xe8, 0x0b, + 0x85, 0x57, 0x72, 0xb6, 0xbb, 0x20, 0x23, 0xd3, 0x7d, 0x9a, 0x9b, 0x9a, 0x05, 0x46, 0x5c, 0xf5, 0x02, 0xf1, 0x56, 0x00, + 0xc2, 0x05, 0x85, 0x48, 0xd3, 0x8d, 0x8e, 0xe1, 0xcb, 0xc5, 0x83, 0x1f, 0x78, 0xd0, 0xc5, 0xb1, 0xdf, 0x80, 0x9d, 0x04, + 0xe7, 0xac, 0xd1, 0x68, 0x1a, 0x19, 0x18, 0x16, 0xfa, 0x3a, 0xe2, 0xd2, 0x30, 0x08, 0x17, 0x4d, 0x50, 0x2b, 0xd4, 0xa3, + 0xbe, 0x98, 0x5f, 0xe0, 0xcf, 0xed, 0x7d, 0x74, 0x94, 0xd1, 0xb2, 0x77, 0xbc, 0x72, 0xbc, 0xf5, 0xc7, 0x82, 0x26, 0x53, + 0x14, 0xcc, 0xf9, 0xf7, 0x71, 0xea, 0x97, 0xaa, 0xbf, 0x21, 0x46, 0x59, 0x2c, 0x9a, 0xc4, 0xeb, 0xa3, 0x4a, 0x97, 0x91, + 0x11, 0xf1, 0x01, 0x19, 0x7e, 0xb1, 0xb2, 0x63, 0x0d, 0xf0, 0x5d, 0xaf, 0x53, 0xdf, 0x4d, 0xa1, 0x90, 0xe5, 0x12, 0x82, + 0x33, 0x6f, 0x1d, 0x73, 0xdf, 0xdb, 0x1f, 0x18, 0xa0, 0x72, 0xc1, 0xd6, 0xa7, 0x4d, 0xb2, 0x3e, 0x24, 0xb7, 0xa7, 0x76, + 0x15, 0x46, 0x22, 0x48, 0x49, 0x55, 0xd1, 0xfb, 0x66, 0x32, 0x02, 0xa9, 0xfc, 0xbe, 0x7e, 0x16, 0xcf, 0xac, 0x32, 0xbc, + 0xdb, 0xd5, 0xd8, 0xa3, 0x23, 0x6a, 0x10, 0xa6, 0x37, 0x03, 0xf6, 0x2a, 0xde, 0xba, 0xde, 0x2d, 0x7d, 0xef, 0x1d, 0xb9, + 0xf3, 0x93, 0xd4, 0xf2, 0x13, 0xf4, 0x9c, 0x5a, 0x32, 0xba, 0x5f, 0xef, 0x7b, 0xd0, 0x6b, 0xd7, 0x91, 0x6d, 0x7b, 0xe1, + 0x4d, 0xf2, 0x8c, 0xe7, 0xf1, 0x66, 0xb9, 0xad, 0xc6, 0x30, 0x08, 0x9e, 0x51, 0xd4, 0x39, 0x87, 0x09, 0xfa, 0x6b, 0x7a, + 0xa7, 0x5f, 0x1a, 0x9c, 0x98, 0xc5, 0x76, 0xb0, 0x71, 0x76, 0xf5, 0xfc, 0x56, 0x88, 0x1c, 0xca, 0xee, 0x76, 0xd4, 0x2c, + 0xa6, 0x64, 0x80, 0x59, 0x12, 0x8c, 0x08, 0xce, 0x83, 0xb3, 0xd9, 0x68, 0x59, 0xc1, 0x26, 0x86, 0xa7, 0x80, 0x10, 0xbc, + 0x41, 0x28, 0x6c, 0x45, 0xd4, 0x6d, 0x15, 0xd0, 0x76, 0x44, 0x0e, 0xcf, 0xc1, 0xde, 0xef, 0x7a, 0x97, 0x36, 0x8f, 0x0d, + 0x8a, 0xf5, 0x45, 0xde, 0xae, 0x61, 0xd0, 0x55, 0xe9, 0x8d, 0x62, 0xfd, 0xa3, 0x0d, 0x44, 0x0f, 0x49, 0xb6, 0x5a, 0xa4, + 0xaa, 0x03, 0x4e, 0x60, 0x35, 0x53, 0x86, 0x9e, 0xec, 0x75, 0xd9, 0x0a, 0xca, 0x14, 0xe3, 0x1b, 0x06, 0x05, 0xd6, 0x8f, + 0x4f, 0x11, 0xb3, 0x13, 0xdd, 0x26, 0x35, 0xbd, 0x56, 0x55, 0xf1, 0x43, 0x89, 0x5e, 0x5b, 0x25, 0x4d, 0xa8, 0x09, 0xdd, + 0xf2, 0x6d, 0x9e, 0x8c, 0xcd, 0xa2, 0xde, 0x84, 0x00, 0x6a, 0x0a, 0xc6, 0x92, 0x30, 0x82, 0xcf, 0xa4, 0x31, 0x67, 0xbd, + 0xd4, 0x36, 0x6a, 0x8b, 0xc6, 0x33, 0xdf, 0x8b, 0xde, 0x33, 0x01, 0x7b, 0x9d, 0xbf, 0xe9, 0x12, 0x35, 0x8a, 0x97, 0x07, + 0x72, 0x0b, 0x6b, 0x60, 0xe6, 0x1e, 0x7d, 0x78, 0x22, 0x9f, 0xbf, 0x66, 0x8e, 0x02, 0xf4, 0xdc, 0xa1, 0xb0, 0x42, 0x73, + 0x86, 0xca, 0x34, 0xf0, 0xa7, 0x2e, 0x15, 0x84, 0xa4, 0x60, 0xa8, 0x47, 0x05, 0x80, 0x03, 0x27, 0xa8, 0x04, 0x03, 0xfe, + 0x47, 0xd4, 0xeb, 0x33, 0x27, 0xbf, 0x89, 0xff, 0x4c, 0xd9, 0x27, 0x0e, 0xd0, 0xa9, 0x41, 0x8b, 0xd5, 0x7c, 0xc4, 0x14, + 0x7a, 0x9c, 0xb3, 0xaa, 0x13, 0x32, 0xa4, 0x67, 0xd5, 0x95, 0xdc, 0x4a, 0x3d, 0xf2, 0x54, 0xd7, 0x02, 0xf8, 0x06, 0x7b, + 0x1d, 0x9a, 0xa4, 0x53, 0xa0, 0x9c, 0x76, 0x7d, 0xf4, 0x01, 0xa3, 0x4b, 0xb2, 0x8b, 0x44, 0x85, 0xf6, 0x80, 0x99, 0x2f, + 0x77, 0x08, 0x20, 0xea, 0x08, 0xf8, 0x14, 0x76, 0xfe, 0xa0, 0x5a, 0xf9, 0x1f, 0x87, 0x03, 0xff, 0x8d, 0x1f, 0x5d, 0x02, + 0x64, 0x8a, 0xf4, 0xa5, 0x8c, 0xb7, 0x0a, 0x34, 0x68, 0xaa, 0xca, 0xc8, 0xe1, 0x78, 0x9b, 0xd3, 0x6c, 0x5c, 0x07, 0x99, + 0xc1, 0x10, 0x3f, 0x77, 0x0c, 0x45, 0xa2, 0xda, 0xda, 0xab, 0x7c, 0xf0, 0x90, 0x12, 0xa2, 0x7c, 0x84, 0x30, 0x82, 0x09, + 0xc9, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x09, 0xba, 0x04, 0x82, 0x09, 0xb6, + 0x30, 0x82, 0x09, 0xb2, 0x30, 0x82, 0x09, 0xae, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, + 0x02, 0xa0, 0x82, 0x09, 0x76, 0x30, 0x82, 0x09, 0x72, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xd3, 0x5d, 0xa8, 0x14, 0xbc, 0x7a, 0xaa, 0x5f, 0x02, 0x02, 0x08, 0x00, 0x04, + 0x82, 0x09, 0x50, 0xaf, 0xe9, 0x63, 0xb6, 0x05, 0x8b, 0x48, 0xe1, 0x11, 0xd0, 0x37, 0x1d, 0x48, 0x71, 0x22, 0x70, 0xdc, + 0xbd, 0xca, 0x98, 0x5d, 0x72, 0xca, 0x38, 0xdc, 0x2e, 0x4f, 0xd4, 0x71, 0xd3, 0xac, 0xf3, 0x0c, 0xcf, 0x78, 0x4e, 0x5c, + 0x63, 0x35, 0xaa, 0xac, 0x5a, 0xf0, 0xef, 0x6c, 0xc0, 0x89, 0x28, 0xc4, 0x64, 0xec, 0x5c, 0x92, 0x72, 0xbc, 0xe5, 0x30, + 0xe9, 0x5c, 0x35, 0xff, 0xe0, 0xb1, 0x1f, 0xc6, 0x37, 0x50, 0xb7, 0x3d, 0x94, 0x28, 0xbd, 0x3b, 0xf0, 0xd9, 0x5c, 0xb1, + 0x45, 0x93, 0xde, 0x41, 0x5b, 0x12, 0xba, 0xfa, 0x27, 0x49, 0x6b, 0xb7, 0x9a, 0xa6, 0x46, 0x8e, 0xe3, 0x15, 0x1b, 0x7f, + 0x2c, 0x91, 0x2e, 0x33, 0xf3, 0xef, 0x7a, 0x9b, 0x9d, 0xa8, 0x82, 0x95, 0xa0, 0x7e, 0x43, 0xd6, 0x9d, 0xe2, 0xfb, 0xb1, + 0xb0, 0xcf, 0xbd, 0xb6, 0x9b, 0x55, 0x4c, 0xc8, 0x4a, 0xc7, 0x82, 0xeb, 0x3d, 0x09, 0x8d, 0x85, 0x6f, 0x8c, 0x42, 0x6d, + 0x10, 0x7d, 0x77, 0x57, 0x29, 0x00, 0xe2, 0xd8, 0x2f, 0xed, 0x7c, 0x10, 0x5b, 0x03, 0xfa, 0x60, 0x34, 0xc9, 0x63, 0x25, + 0x4d, 0x02, 0x77, 0x8f, 0x7f, 0x4b, 0x53, 0xe4, 0x8d, 0x1e, 0x4e, 0x2c, 0x0c, 0x7f, 0x0e, 0x48, 0x4b, 0xcd, 0xc8, 0x6a, + 0xfa, 0xd3, 0x9f, 0x6f, 0x20, 0x4e, 0x2c, 0x77, 0x2a, 0x84, 0x5e, 0x6c, 0xc3, 0x57, 0xba, 0x97, 0xa7, 0xa8, 0xcb, 0x6f, + 0x22, 0xc1, 0xa7, 0x61, 0xf7, 0x7e, 0x7a, 0xae, 0xda, 0xbd, 0x3a, 0xea, 0xb3, 0x46, 0x54, 0x8d, 0x46, 0x48, 0x1f, 0xf3, + 0x5c, 0xaa, 0x2e, 0x44, 0xe1, 0x83, 0x69, 0x45, 0x30, 0x02, 0x49, 0x63, 0xa6, 0xdd, 0xf0, 0x25, 0xce, 0x81, 0xab, 0x66, + 0x20, 0x04, 0x12, 0x2f, 0x94, 0x2f, 0x8f, 0xf9, 0x88, 0xea, 0x5b, 0xba, 0x87, 0xd7, 0xbe, 0x63, 0x2e, 0xb4, 0xa4, 0x15, + 0xe8, 0x56, 0x9e, 0xb5, 0x7b, 0x27, 0xf8, 0x06, 0xfd, 0xf5, 0x21, 0x93, 0x2b, 0x64, 0xb0, 0xe2, 0x31, 0xb3, 0x19, 0xe0, + 0x6b, 0x10, 0x8c, 0xa5, 0xa5, 0x38, 0x27, 0x78, 0xc9, 0x9c, 0x01, 0xa7, 0x42, 0x22, 0x3d, 0xf8, 0x8c, 0x23, 0x46, 0xc5, + 0x4e, 0x47, 0xa5, 0x9e, 0xd7, 0xa5, 0x50, 0x24, 0x02, 0x30, 0xe9, 0x15, 0x3e, 0x17, 0xba, 0x2c, 0xf2, 0x5e, 0xc7, 0x01, + 0x25, 0x9a, 0x74, 0x73, 0x5c, 0x5e, 0xca, 0x01, 0xe2, 0x58, 0x96, 0x47, 0x3e, 0x4c, 0xb9, 0x0f, 0x95, 0xbf, 0xf3, 0xc4, + 0x24, 0x98, 0x6c, 0xc5, 0x40, 0xd2, 0xf3, 0x88, 0x62, 0xb0, 0x25, 0x54, 0xb5, 0xf6, 0x2b, 0xfd, 0xf5, 0x6a, 0x6d, 0x15, + 0xb2, 0x18, 0x7d, 0xef, 0x3e, 0x66, 0x7d, 0x38, 0x4c, 0xda, 0xc9, 0x1a, 0xcd, 0x40, 0x2a, 0xc6, 0x7b, 0x2e, 0x8a, 0x15, + 0xa7, 0xae, 0x99, 0xf5, 0x93, 0x39, 0x20, 0xd2, 0xd8, 0xfd, 0x1f, 0x87, 0x2e, 0xa0, 0xcd, 0x95, 0xa2, 0xd7, 0xd0, 0x48, + 0xf7, 0x6e, 0x81, 0x91, 0x1c, 0x37, 0x8a, 0x28, 0x6f, 0x22, 0x7b, 0x37, 0x69, 0x30, 0x3a, 0x64, 0x6e, 0x4a, 0x5f, 0x0a, + 0xa6, 0xd7, 0x53, 0xce, 0x1d, 0x60, 0x88, 0xa5, 0x0b, 0xde, 0xf5, 0x01, 0x3a, 0x20, 0xfa, 0xd6, 0x08, 0xdf, 0x83, 0x39, + 0x2e, 0xb8, 0x3a, 0x91, 0xec, 0x39, 0x47, 0xaa, 0x66, 0x8a, 0xb4, 0x35, 0x70, 0xaf, 0x88, 0x24, 0xb2, 0xc3, 0xdc, 0x7c, + 0xd0, 0x8f, 0x93, 0x0d, 0xa4, 0x53, 0xf1, 0x55, 0x92, 0xae, 0xd9, 0xeb, 0x31, 0xa0, 0x68, 0x29, 0xf5, 0xdb, 0x2f, 0xd1, + 0xa3, 0xfe, 0x34, 0x2f, 0xcd, 0x64, 0x0c, 0x11, 0x13, 0x14, 0x50, 0xeb, 0x27, 0x56, 0xda, 0xc0, 0x30, 0x3a, 0x8c, 0x92, + 0xb3, 0xb8, 0xc8, 0xb7, 0x19, 0xea, 0x4c, 0x74, 0xb9, 0x95, 0x46, 0x9f, 0xc0, 0x63, 0xfd, 0x72, 0x35, 0x0b, 0xb9, 0x1d, + 0x1e, 0x85, 0xf8, 0xf9, 0x23, 0xf7, 0x42, 0xe2, 0xf4, 0x67, 0xbf, 0x3d, 0x30, 0x4b, 0x6a, 0xf2, 0x44, 0x2f, 0xcb, 0x6f, + 0xe9, 0x73, 0x4b, 0x8f, 0x09, 0x29, 0x69, 0xcd, 0x8d, 0xcd, 0xc7, 0xd4, 0xa2, 0x0c, 0x6a, 0xc4, 0x9a, 0x33, 0xe2, 0x64, + 0x5f, 0x07, 0xf2, 0xb6, 0xf8, 0x86, 0x7f, 0x05, 0x04, 0xf1, 0x1d, 0x9d, 0xd1, 0xc8, 0x3c, 0x16, 0x6e, 0x18, 0x96, 0x15, + 0x33, 0xda, 0x84, 0xb6, 0xfd, 0x13, 0x29, 0x2f, 0x5e, 0xa0, 0x0e, 0xaa, 0xf6, 0x24, 0xb4, 0xa5, 0x48, 0x01, 0x02, 0x07, + 0x31, 0x98, 0x0d, 0x9c, 0x65, 0x59, 0x68, 0x61, 0x22, 0xdb, 0x64, 0x16, 0x05, 0xae, 0xd8, 0x64, 0x5f, 0xba, 0x51, 0xab, + 0x5e, 0xe0, 0xbe, 0x3d, 0x29, 0x67, 0x20, 0x94, 0x63, 0xfe, 0xc7, 0x90, 0x30, 0xc9, 0x43, 0xf1, 0xce, 0x9c, 0x53, 0x01, + 0x2c, 0x64, 0x56, 0x85, 0xb7, 0x3b, 0xa4, 0x05, 0x5d, 0x88, 0xdf, 0x44, 0xda, 0x18, 0xf3, 0x8c, 0xdb, 0xae, 0xd2, 0x9f, + 0xee, 0x4e, 0x08, 0x17, 0xf9, 0xd8, 0xe0, 0xc9, 0x7d, 0xa5, 0xad, 0x79, 0x06, 0x1b, 0x8c, 0x92, 0xe7, 0x53, 0xdf, 0xde, + 0xa3, 0xa5, 0x84, 0x1d, 0xd8, 0x75, 0x35, 0x78, 0x32, 0x55, 0x6f, 0x4f, 0x29, 0x34, 0x4e, 0x6f, 0x32, 0x16, 0xe4, 0xfd, + 0xbc, 0xf5, 0x76, 0x99, 0xf3, 0x48, 0x5b, 0xa0, 0x65, 0xb2, 0xef, 0xeb, 0x58, 0x6c, 0xf4, 0x1e, 0x97, 0x34, 0xee, 0xf9, + 0x74, 0xe2, 0x94, 0xc0, 0xf2, 0xf5, 0x0b, 0x97, 0x40, 0xce, 0x25, 0xd6, 0xe5, 0xdf, 0x0b, 0x3b, 0x6b, 0xf3, 0x38, 0x28, + 0xc3, 0xa6, 0x30, 0xa5, 0x22, 0x3c, 0xb0, 0xbd, 0x4d, 0xd5, 0x79, 0x25, 0xb9, 0xb2, 0xb4, 0xc4, 0x31, 0x62, 0x0b, 0xe7, + 0x73, 0x4e, 0xf9, 0xa7, 0x57, 0xdf, 0x33, 0x0e, 0xf0, 0xb9, 0x3b, 0x6d, 0xff, 0x6b, 0x11, 0xb0, 0x90, 0x10, 0x2a, 0x7b, + 0xb5, 0x0b, 0x41, 0x17, 0x0b, 0x12, 0xc7, 0x61, 0xef, 0xb1, 0x9b, 0x57, 0x3a, 0x01, 0x55, 0x91, 0xe3, 0xd5, 0xc8, 0xd5, + 0xeb, 0x26, 0x90, 0x2b, 0x67, 0x5b, 0xc2, 0x0b, 0xad, 0x6f, 0x26, 0x3a, 0xf5, 0x45, 0xb2, 0xd7, 0x6a, 0x78, 0xaa, 0x43, + 0xd0, 0xdb, 0x53, 0x6f, 0x1a, 0x7a, 0x5c, 0x92, 0xe1, 0xb7, 0xe5, 0xad, 0xda, 0xac, 0x3b, 0x5a, 0x20, 0x06, 0xe1, 0x56, + 0xf0, 0x55, 0x66, 0x64, 0x42, 0xd4, 0xe4, 0x77, 0x3b, 0xa5, 0x60, 0x8d, 0x5b, 0x24, 0x7a, 0x2a, 0xb9, 0xe2, 0x2f, 0xc6, + 0x02, 0xd1, 0x21, 0xf3, 0x08, 0xbd, 0x7b, 0xf4, 0x44, 0x47, 0x00, 0xd2, 0xca, 0x3c, 0x80, 0x37, 0xb0, 0xf2, 0x3d, 0x07, + 0x87, 0xbd, 0xe8, 0x59, 0x01, 0x17, 0x7b, 0xb3, 0x1b, 0xc3, 0xce, 0x45, 0x77, 0x3c, 0x0e, 0xdd, 0xac, 0x38, 0xf1, 0x5e, + 0xde, 0x5e, 0xdd, 0xad, 0xf2, 0xc9, 0x0f, 0xed, 0xec, 0xe5, 0x00, 0x8b, 0x61, 0xf4, 0x62, 0xd5, 0x58, 0x37, 0xec, 0xbf, + 0x36, 0xcf, 0x7a, 0x6a, 0x55, 0x1f, 0x25, 0x53, 0xba, 0xcd, 0x76, 0xc3, 0x07, 0x5e, 0x12, 0xf0, 0xc3, 0x82, 0x52, 0x5f, + 0xc6, 0x24, 0x54, 0x76, 0x49, 0xa3, 0xf1, 0xdd, 0x67, 0x29, 0x81, 0x19, 0x5f, 0x7b, 0xcd, 0xc6, 0x60, 0x3e, 0x80, 0x02, + 0xb3, 0xd9, 0xb6, 0x9d, 0x29, 0x59, 0xdc, 0x79, 0x90, 0xab, 0x53, 0xf4, 0xe6, 0x23, 0xb4, 0x77, 0x0f, 0xc8, 0xf2, 0x88, + 0xb3, 0x1c, 0x70, 0xb4, 0xeb, 0xa8, 0xdf, 0x25, 0x5b, 0x94, 0xa6, 0xce, 0x80, 0xbd, 0x46, 0xe6, 0x26, 0x8c, 0x4f, 0xee, + 0x37, 0x81, 0x84, 0xc6, 0xff, 0x0a, 0x37, 0x2e, 0xa4, 0xcb, 0xdf, 0x62, 0x81, 0x79, 0x3b, 0xa2, 0xdb, 0x07, 0x14, 0x0c, + 0xf7, 0x44, 0x1e, 0xda, 0xe0, 0x6c, 0x1a, 0xb6, 0x52, 0x7f, 0xd8, 0xce, 0xe7, 0x29, 0x98, 0xc1, 0x69, 0x40, 0xb9, 0x2a, + 0xe7, 0xb4, 0xee, 0x04, 0x67, 0xf7, 0x54, 0xac, 0x94, 0x12, 0x5c, 0x67, 0xb4, 0x51, 0x9c, 0xf6, 0xfa, 0x9b, 0x10, 0xd3, + 0x7e, 0xce, 0x78, 0xd5, 0x88, 0x80, 0xd7, 0x88, 0xea, 0x16, 0x51, 0x0c, 0xc9, 0xf2, 0x55, 0xda, 0xbd, 0x22, 0x34, 0x1a, + 0x65, 0x8f, 0xd7, 0x52, 0x00, 0x98, 0xc3, 0x76, 0xff, 0x3e, 0xfc, 0x44, 0x4b, 0x7e, 0xc2, 0x40, 0x00, 0x94, 0xf3, 0xc6, + 0xd5, 0xa3, 0x0f, 0x95, 0x9a, 0x96, 0xbb, 0x50, 0xcd, 0xd0, 0x6f, 0x75, 0xd7, 0xcc, 0x89, 0xb4, 0xc2, 0x85, 0x7f, 0x5f, + 0x06, 0xc1, 0xdf, 0x3c, 0xdd, 0x32, 0xdb, 0x44, 0xae, 0x1e, 0xd8, 0x56, 0xde, 0x93, 0xb0, 0xbd, 0xed, 0x8c, 0xb6, 0xcc, + 0x15, 0xe7, 0x81, 0x98, 0x36, 0x36, 0xd6, 0x91, 0x61, 0xd8, 0x65, 0x57, 0x5d, 0xcd, 0xbf, 0xf1, 0x3b, 0x31, 0xb6, 0xdd, + 0x6e, 0xc6, 0xd3, 0x1b, 0xc9, 0x47, 0x8c, 0x09, 0x03, 0x81, 0x7d, 0xbd, 0x64, 0xa9, 0x09, 0x66, 0x81, 0x2d, 0x56, 0x43, + 0xe8, 0x3c, 0x3e, 0xaa, 0xf8, 0x28, 0x92, 0x13, 0xea, 0x1f, 0xc1, 0x81, 0x4f, 0xb1, 0x1e, 0x88, 0xd2, 0x47, 0xdb, 0xb4, + 0x7e, 0xcb, 0xac, 0xc4, 0xbc, 0x07, 0x68, 0x83, 0x7d, 0xd2, 0x90, 0x90, 0x01, 0xa7, 0x0b, 0xac, 0x60, 0x67, 0x0f, 0xf4, + 0x1b, 0x2c, 0x1e, 0x93, 0x93, 0x6a, 0x16, 0x63, 0x78, 0x36, 0x7d, 0xc5, 0xa5, 0x04, 0xf4, 0x96, 0x1d, 0xae, 0x1a, 0xdf, + 0x1d, 0xba, 0xfc, 0x00, 0x21, 0x07, 0x8c, 0xa7, 0x9d, 0x00, 0x60, 0xb7, 0xa4, 0x05, 0xdd, 0xcd, 0x05, 0xee, 0x70, 0x5e, + 0xc5, 0x79, 0x6c, 0xc1, 0x22, 0x57, 0xfb, 0x5a, 0x25, 0x3e, 0xb9, 0x37, 0x76, 0x61, 0xc2, 0x7d, 0x14, 0x3c, 0xd3, 0x3a, + 0x13, 0xb9, 0x33, 0x07, 0xf6, 0x53, 0xc9, 0x5b, 0xb9, 0x97, 0x03, 0xd0, 0x76, 0xb8, 0xd1, 0xf1, 0x43, 0x9d, 0x7f, 0x37, + 0x46, 0x1a, 0xda, 0xdf, 0xd7, 0x4a, 0xb7, 0x79, 0x84, 0x9e, 0x47, 0x73, 0xac, 0x26, 0xf7, 0xd7, 0x54, 0x16, 0xad, 0x49, + 0x5e, 0x5d, 0x77, 0x61, 0x79, 0xdd, 0x52, 0x13, 0x2f, 0x20, 0xce, 0x26, 0x35, 0xa3, 0x60, 0x28, 0x3f, 0xc5, 0x67, 0xce, + 0x43, 0xa0, 0x86, 0x28, 0xf7, 0xa6, 0xf9, 0x6a, 0xbf, 0x25, 0x41, 0xb7, 0x7d, 0xbc, 0x04, 0x02, 0xd1, 0xe5, 0xed, 0x74, + 0xf5, 0xf5, 0x39, 0xf5, 0x18, 0x42, 0x9f, 0xdc, 0xaf, 0x46, 0xb6, 0x55, 0x48, 0x72, 0xa6, 0x66, 0x94, 0xef, 0x4a, 0x45, + 0x92, 0xf8, 0x31, 0x7a, 0x19, 0x69, 0xcb, 0xcf, 0xf3, 0x10, 0x4a, 0x65, 0x53, 0x18, 0xf4, 0x7f, 0x47, 0xe8, 0xe5, 0x07, + 0xb1, 0x8b, 0x3c, 0x3b, 0xb1, 0x1f, 0xdb, 0xb8, 0x5d, 0x53, 0xcb, 0xad, 0xf7, 0x38, 0x91, 0x8a, 0x1e, 0xa6, 0x76, 0x05, + 0x48, 0x89, 0xcc, 0xff, 0x51, 0x59, 0x53, 0xe9, 0xd7, 0x6e, 0x1a, 0x6e, 0xad, 0xf2, 0xcb, 0xf5, 0xfd, 0x48, 0xbe, 0xa8, + 0x70, 0xae, 0x5e, 0xc1, 0x7e, 0x1e, 0x07, 0x8e, 0x64, 0x0d, 0x70, 0xb7, 0x92, 0xda, 0x6f, 0x45, 0xb0, 0xe3, 0x8a, 0x30, + 0xbc, 0x45, 0xd1, 0x65, 0xf2, 0xb7, 0xab, 0x4e, 0x16, 0x5c, 0xa2, 0xb2, 0x9a, 0x4d, 0x2f, 0x76, 0x26, 0x62, 0x92, 0x7a, + 0x3c, 0x47, 0xf6, 0x87, 0x04, 0x0f, 0x7b, 0xda, 0x4b, 0x02, 0x6b, 0xd6, 0x16, 0x79, 0xbd, 0x16, 0x24, 0x42, 0x7a, 0xf4, + 0x44, 0x58, 0xb4, 0x68, 0x71, 0xce, 0xb3, 0x28, 0xba, 0x84, 0x6c, 0x26, 0x82, 0x1e, 0xba, 0x19, 0x83, 0xb7, 0x75, 0x1b, + 0xde, 0x09, 0xf6, 0x1b, 0x4f, 0x31, 0x65, 0xae, 0xb6, 0x45, 0xc2, 0xa7, 0x35, 0x2d, 0x9f, 0x14, 0x10, 0xe0, 0x3e, 0x43, + 0xa7, 0x82, 0x01, 0x06, 0x95, 0x2c, 0x19, 0x43, 0x8c, 0x94, 0xd4, 0x8c, 0x85, 0x6d, 0x88, 0x33, 0xff, 0x19, 0x51, 0xd3, + 0x7c, 0xf2, 0xa7, 0x5b, 0x05, 0xd1, 0x2b, 0x56, 0x18, 0x5e, 0xa6, 0xb9, 0x66, 0x3c, 0xf7, 0x4d, 0xbd, 0xa9, 0x95, 0x75, + 0xa9, 0xa1, 0x87, 0x24, 0x87, 0xf0, 0x60, 0xbb, 0x39, 0xec, 0xd1, 0xe5, 0x67, 0x51, 0x76, 0x99, 0xbc, 0x64, 0x7b, 0x5a, + 0xd5, 0xa6, 0x54, 0x4f, 0x16, 0x10, 0xb2, 0xe9, 0x43, 0x1c, 0x3a, 0x4c, 0x88, 0x51, 0xf4, 0xc2, 0x95, 0x16, 0x8e, 0xbf, + 0x79, 0x19, 0x22, 0x95, 0xd1, 0x76, 0x99, 0xb8, 0x68, 0xf3, 0x6a, 0x1a, 0x4e, 0x43, 0xf8, 0x9c, 0x6b, 0x75, 0x8c, 0xa5, + 0xbd, 0x65, 0x3a, 0x83, 0x0b, 0x47, 0xcf, 0x08, 0xf7, 0x22, 0x86, 0xad, 0xd5, 0x89, 0xd0, 0x6f, 0x4e, 0xbe, 0x2a, 0x81, + 0x1d, 0x1c, 0xf1, 0xc8, 0xf3, 0x18, 0x44, 0x40, 0xf3, 0x99, 0xfd, 0x18, 0xe3, 0x1a, 0xc9, 0x7f, 0x3b, 0x93, 0x68, 0x84, + 0xe2, 0x49, 0xb9, 0xcf, 0x00, 0x5c, 0x76, 0xc4, 0xcc, 0x4b, 0x7e, 0x86, 0x7e, 0x3f, 0x4b, 0x23, 0x61, 0x92, 0x7c, 0xcb, + 0x0c, 0x0c, 0x3e, 0x97, 0x34, 0xcc, 0xfd, 0x34, 0xa9, 0xcc, 0xf0, 0x83, 0xb1, 0xbc, 0x50, 0x4c, 0x84, 0x6f, 0xba, 0x68, + 0x01, 0x4f, 0x71, 0x57, 0x05, 0x7f, 0x01, 0xe2, 0x18, 0x23, 0xe9, 0x44, 0xa8, 0x4d, 0x93, 0x11, 0xee, 0xc0, 0x79, 0x5a, + 0x94, 0x13, 0x81, 0xf4, 0x67, 0xa0, 0x50, 0x79, 0x83, 0xa1, 0x13, 0x5f, 0x0e, 0x82, 0x9a, 0x72, 0x90, 0xba, 0x43, 0x21, + 0x28, 0xa9, 0x65, 0x1c, 0x16, 0x97, 0x6f, 0xdb, 0xc3, 0x1e, 0x23, 0xc5, 0x4a, 0xdb, 0x3b, 0x3c, 0x42, 0x4a, 0xc4, 0xb5, + 0x7f, 0x6b, 0x5d, 0xfc, 0x09, 0x08, 0x43, 0x2f, 0xf8, 0x11, 0x27, 0x6f, 0x1d, 0xc0, 0x12, 0x59, 0x04, 0xa4, 0x5b, 0xe9, + 0x9f, 0x25, 0xd1, 0x58, 0x3a, 0x1f, 0xac, 0x05, 0x15, 0x18, 0xea, 0xbd, 0x4b, 0xd2, 0xba, 0x67, 0xf3, 0x1d, 0x89, 0x09, + 0x52, 0xe5, 0x0e, 0x15, 0xd6, 0x5b, 0x87, 0xf5, 0xc3, 0x3c, 0x98, 0xbc, 0x46, 0x4e, 0x19, 0x8d, 0xbb, 0x3e, 0xe0, 0xde, + 0x19, 0x59, 0x53, 0x32, 0x62, 0x31, 0x16, 0xd4, 0xea, 0x63, 0xda, 0xf4, 0xcc, 0x94, 0xd0, 0x18, 0x98, 0xbc, 0x00, 0xd3, + 0x6c, 0xe2, 0xa5, 0xac, 0x30, 0x08, 0x9d, 0x68, 0x82, 0x8e, 0xbb, 0xdf, 0x9a, 0xa1, 0x13, 0xa5, 0x98, 0x18, 0xa9, 0x11, + 0xde, 0x49, 0x18, 0x88, 0xab, 0xff, 0xc6, 0x2c, 0xa8, 0xe1, 0xf7, 0x49, 0xba, 0x17, 0x93, 0x1c, 0x6c, 0x7f, 0x2c, 0xa9, + 0x3a, 0xee, 0x77, 0x9d, 0x46, 0x0c, 0xf9, 0x1c, 0x24, 0x33, 0x6f, 0x9b, 0xf8, 0x47, 0x9d, 0xc9, 0x7f, 0x9c, 0x80, 0xa0, + 0x2c, 0x96, 0x63, 0xe1, 0x97, 0x75, 0x75, 0x1f, 0xb3, 0xc6, 0x0d, 0xa9, 0x49, 0x82, 0x66, 0x86, 0x13, 0xa4, 0x62, 0x4c, + 0x56, 0x89, 0x73, 0x03, 0x1b, 0x61, 0xff, 0xfa, 0x0f, 0xf4, 0x84, 0xe3, 0xad, 0x89, 0xc0, 0x8e, 0x03, 0x91, 0x1c, 0x99, + 0x9f, 0x99, 0x92, 0x7e, 0xb5, 0xd8, 0xe3, 0xee, 0x6c, 0x21, 0x27, 0x5d, 0xa2, 0xa5, 0x90, 0xf2, 0x67, 0xed, 0xf3, 0xca, + 0x51, 0x56, 0x28, 0x7d, 0xa9, 0xd0, 0x4a, 0x4b, 0x76, 0x2b, 0xa8, 0x95, 0x8a, 0x37, 0xb4, 0x72, 0x96, 0xb2, 0xa0, 0xbe, + 0x90, 0x4f, 0x4e, 0x37, 0xbb, 0x14, 0xf8, 0xd2, 0x76, 0x7c, 0x79, 0xf3, 0xd2, 0xbf, 0x35, 0xad, 0x64, 0xbc, 0x98, 0x73, + 0xe5, 0xb9, 0xb3, 0xa2, 0x9b, 0x54, 0x17, 0x9b, 0x99, 0xa1, 0xeb, 0xfd, 0xc2, 0x8b, 0xbd, 0xac, 0x6d, 0x14, 0x35, 0xc2, + 0x3b, 0xc9, 0x88, 0x57, 0x64, 0xaa, 0x52, 0x3d, 0xf1, 0x80, 0x9c, 0xb2, 0xfc, 0xe9, 0x53, 0x7c, 0x12, 0x81, 0xe6, 0x07, + 0xa1, 0x0b, 0x2b, 0xb3, 0x88, 0xa6, 0x07, 0xb8, 0x10, 0x7e, 0xc4, 0x55, 0x14, 0xa2, 0x66, 0xf1, 0xcc, 0xff, 0x49, 0x84, + 0xbc, 0x54, 0x15, 0x41, 0x26, 0x15, 0x44, 0xf1, 0xe4, 0x4e, 0x8a, 0xf4, 0x02, 0xb1, 0x87, 0x51, 0xa7, 0xa4, 0xe6, 0x4f, + 0xbb, 0xff, 0xfe, 0x94, 0x51, 0x54, 0x20, 0x7e, 0x16, 0x60, 0x23, 0xfe, 0x05, 0x8c, 0x1a, 0xe1, 0x12, 0x7c, 0xd4, 0xc0, + 0xae, 0x3a, 0x96, 0x13, 0x5d, 0x83, 0x89, 0x49, 0x99, 0x2c, 0x3e, 0x19, 0x8b, 0xa8, 0xf0, 0x0d, 0x65, 0x5d, 0x35, 0x37, + 0xa1, 0x2d, 0xdd, 0xe2, 0x6b, 0x0d, 0xa9, 0x47, 0x9e, 0xf0, 0x22, 0xb5, 0x8e, 0xab, 0xc1, 0x34, 0x93, 0x4c, 0xff, 0x89, + 0x9b, 0x24, 0xd4, 0x01, 0x24, 0xbc, 0xf5, 0x42, 0xd8, 0xee, 0xc2, 0xbc, 0x78, 0x03, 0xc1, 0x24, 0xa8, 0x88, 0xba, 0x3f, + 0x71, 0x58, 0x3d, 0xdd, 0xef, 0xa8, 0xf8, 0x15, 0x4c, 0xb0, 0x68, 0x7c, 0xbc, 0x41, 0x66, 0x72, 0xc4, 0x4d, 0x9f, 0xd0, + 0xdb, 0x9a, 0xd0, 0x65, 0xde, 0xf1, 0x25, 0x02, 0x35, 0xff, 0x49, 0x4a, 0xd8, 0xa4, 0x19, 0x49, 0xb4, 0x51, 0xda, 0x4b, + 0x75, 0x81, 0x17, 0xa7, 0x84, 0x80, 0x70, 0x3f, 0xc7, 0x0d, 0xb2, 0x79, 0x24, 0x25, 0x7c, 0xe2, 0x30, 0x67, 0x15, 0x00, + 0x80, 0x68, 0x1e, 0xde, 0xf0, 0x3e, 0xda, 0xc6, 0x31, 0x4d, 0xa7, 0xf0, 0x53, 0x0d, 0x88, 0x08, 0xe1, 0xd8, 0xe2, 0x8b, + 0x01, 0xdb, 0x9f, 0x5b, 0x7c, 0xd4, 0x68, 0x89, 0xb1, 0xeb, 0xdb, 0x4e, 0x6f, 0xac, 0x21, 0xad, 0xf2, 0xed, 0x6f, 0x61, + 0x4d, 0x1f, 0x2f, 0x64, 0x0b, 0xdb, 0x07, 0x54, 0x65, 0xd7, 0xf0, 0xf8, 0x40, 0xdb, 0xd9, 0x5e, 0x2d, 0xaf, 0x4f, 0x14, + 0x9f, 0x5b, 0x0b, 0x74, 0x4e, 0xad, 0x07, 0x60, 0xac, 0x24, 0x04, 0x5b, 0xc8, 0xf4, 0xc9, 0x6f, 0x28, 0xb0, 0x2b, 0xb3, + 0xd9, 0x43, 0xf1, 0x55, 0xc9, 0x25, 0x01, 0xb7, 0xab, 0x8f, 0xd8, 0x0f, 0x78, 0x6a, 0xbf, 0xa0, 0x4e, 0x80, 0x22, 0xc6, + 0x8a, 0x42, 0x37, 0x6d, 0x3a, 0xbd, 0xf3, 0x66, 0xbe, 0x84, 0x87, 0xf6, 0xa1, 0xa0, 0x99, 0x7f, 0x13, 0x66, 0x40, 0x39, + 0xce, 0x43, 0x8f, 0xe5, 0x83, 0x48, 0x94, 0xc6, 0x59, 0xc2, 0xce, 0x55, 0x35, 0x44, 0x74, 0xa6, 0x37, 0x0c, 0x3c, 0x69, + 0xdc, 0xdb, 0x2b, 0x3a, 0xd8, 0x32, 0x4d, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x01, 0xae, 0x1a, 0x61, 0x75, 0xae, 0x23, 0xd9, 0x11, 0x5c, 0x28, 0x93, 0xa9, 0xe2, + 0x49, 0x5e, 0x74, 0x28, 0x4c, 0x08, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14, 0x3d, 0xc6, 0xb0, 0x07, 0xf5, 0xd4, 0xa7, 0x42, 0x90, 0xa1, 0x2f, 0x4d, 0x1e, 0x43, 0x09, 0x7d, 0xd5, + 0xfe, 0x15, 0xb1, 0x04, 0x08, 0xdd, 0xee, 0x2c, 0x8a, 0x3d, 0x65, 0x41, 0x94, 0x02, 0x02, 0x08, 0x00 +}; + +/* Random data for content */ +uint8_t content[1024] = { + 0x2a, 0xb1, 0x8c, 0xf1, 0x66, 0x52, 0xd5, 0x3c, 0xdd, 0x53, 0xc0, 0x07, 0x6a, 0x13, 0xda, 0x25, 0x9c, 0x04, 0x64, 0x5c, + 0x97, 0xb8, 0xb3, 0xb5, 0xcf, 0xf8, 0xe1, 0x8f, 0xdd, 0x49, 0x64, 0x55, 0x97, 0xad, 0xbc, 0xad, 0xff, 0xd1, 0xd9, 0xdf, + 0x0f, 0x26, 0x96, 0x27, 0x78, 0x1b, 0x13, 0xf6, 0x2e, 0x75, 0xb2, 0x6a, 0xf1, 0x04, 0x71, 0xa3, 0x51, 0x8d, 0x9c, 0xe8, + 0xab, 0xee, 0xf4, 0xf4, 0xfa, 0x75, 0x16, 0xbe, 0x08, 0xaf, 0xdf, 0x23, 0xc2, 0x17, 0x75, 0x80, 0xad, 0x0e, 0x68, 0xc1, + 0x37, 0xd9, 0x49, 0x0b, 0xea, 0x8a, 0x29, 0x3a, 0x2d, 0xff, 0x45, 0xe9, 0x13, 0x93, 0xac, 0x2e, 0x25, 0x3d, 0x5f, 0xd1, + 0x36, 0x66, 0x61, 0x14, 0xa9, 0xf1, 0xae, 0x83, 0x3a, 0x96, 0xe3, 0xcd, 0xe1, 0xdd, 0xb8, 0x8b, 0x85, 0xe7, 0xd9, 0x1b, + 0x76, 0xf9, 0x55, 0xf7, 0xd8, 0xb6, 0xca, 0x5b, 0x0f, 0xb8, 0x40, 0x1b, 0x69, 0x54, 0x07, 0xde, 0xd5, 0x26, 0x85, 0x9b, + 0xd1, 0x4a, 0xce, 0x2b, 0xe1, 0xd8, 0xe7, 0x6a, 0x06, 0x28, 0x4b, 0x05, 0xa9, 0x0b, 0x65, 0x07, 0x3d, 0xf5, 0xca, 0x31, + 0xd0, 0xfb, 0x5b, 0xf8, 0x1e, 0x19, 0x5f, 0x69, 0x64, 0x1b, 0xe1, 0x6d, 0x15, 0x88, 0x9c, 0xd1, 0x25, 0x4d, 0xf2, 0xa5, + 0x74, 0x82, 0xa4, 0xd3, 0x21, 0xc2, 0x4f, 0x78, 0xcf, 0x37, 0xdd, 0x3c, 0xe5, 0x69, 0x27, 0x82, 0xf1, 0xc8, 0xe9, 0x2f, + 0x7a, 0x7d, 0xd4, 0x65, 0x78, 0xad, 0x4c, 0xfc, 0xa5, 0x29, 0x51, 0xe2, 0x67, 0xac, 0x29, 0xa4, 0x23, 0x46, 0xe0, 0x10, + 0x55, 0x2a, 0x7e, 0xef, 0x04, 0xd4, 0x9f, 0xe3, 0x65, 0x09, 0x2d, 0x33, 0x07, 0xa5, 0x6c, 0x3d, 0x6e, 0xf5, 0x3e, 0xda, + 0x92, 0xb3, 0x47, 0x89, 0xa8, 0xda, 0x04, 0xe0, 0xa6, 0xcd, 0xd5, 0x84, 0xd6, 0xd5, 0x6f, 0xa5, 0x30, 0x3f, 0xcc, 0x9e, + 0xfe, 0xd5, 0xd6, 0xb8, 0x61, 0xf6, 0xb0, 0x10, 0x9d, 0x4d, 0x5c, 0x90, 0xc8, 0x05, 0x4d, 0xba, 0x99, 0x8e, 0xa7, 0xc8, + 0x53, 0xe7, 0x5d, 0xd7, 0x37, 0xf3, 0x0b, 0xc9, 0x0f, 0x97, 0x2d, 0x3e, 0x22, 0xed, 0xdc, 0x28, 0x22, 0x32, 0x04, 0xc0, + 0x6a, 0x38, 0xd8, 0xc8, 0x85, 0xef, 0x57, 0x9c, 0xa1, 0xe0, 0x0b, 0x7e, 0x6a, 0xb4, 0x5a, 0x76, 0x7c, 0xaf, 0x6f, 0x5d, + 0xcc, 0x56, 0xef, 0x60, 0x3c, 0xce, 0x0f, 0x0a, 0x5e, 0xfa, 0xbb, 0xb6, 0xd8, 0xba, 0xda, 0x9d, 0xf5, 0x86, 0x55, 0xc2, + 0x84, 0x9b, 0x3d, 0xc2, 0x54, 0x5b, 0xa9, 0x23, 0x57, 0xe1, 0x0a, 0x84, 0x7e, 0x3c, 0x52, 0x9c, 0x3d, 0x02, 0x9b, 0xb5, + 0x9c, 0x50, 0xfb, 0xfc, 0x43, 0xf9, 0x07, 0x34, 0xd9, 0xad, 0x3f, 0x59, 0x44, 0x6b, 0x47, 0xa0, 0xb9, 0x29, 0x63, 0xfb, + 0xd9, 0xd7, 0xfc, 0x62, 0xda, 0x23, 0x7e, 0x2b, 0xb6, 0x09, 0xfc, 0x52, 0x70, 0x77, 0xb9, 0x4d, 0x92, 0xdd, 0xf2, 0x82, + 0x8c, 0xa3, 0xf5, 0x79, 0xf9, 0x21, 0xe8, 0x36, 0xea, 0xf5, 0xa7, 0x8c, 0x3c, 0x46, 0xab, 0x29, 0xdc, 0x91, 0xa8, 0x8e, + 0xc5, 0xe7, 0xe5, 0x95, 0xd5, 0xca, 0xed, 0xad, 0x54, 0x24, 0xf2, 0xee, 0x40, 0x9c, 0x06, 0x08, 0x03, 0x36, 0x0a, 0x73, + 0xa4, 0xcb, 0xbb, 0x28, 0x83, 0x28, 0x66, 0xc3, 0x79, 0xba, 0x7a, 0x76, 0x90, 0x10, 0x88, 0x04, 0x3f, 0x0f, 0x67, 0xd2, + 0x53, 0xab, 0x63, 0xc7, 0x83, 0xc9, 0x2b, 0xdd, 0x9c, 0x61, 0x99, 0xe4, 0x12, 0x18, 0xc6, 0x9a, 0x9d, 0x3c, 0xea, 0x13, + 0x87, 0x32, 0x57, 0x8d, 0x01, 0x11, 0x39, 0x56, 0x94, 0xb2, 0x4d, 0x73, 0xc0, 0xdc, 0x2d, 0x4c, 0xb3, 0xd1, 0x90, 0x36, + 0xd8, 0xae, 0xd3, 0x06, 0xd7, 0x70, 0xa5, 0xd6, 0x0e, 0x64, 0xf8, 0x80, 0xb6, 0x36, 0x0c, 0x31, 0xd3, 0xcc, 0x46, 0xba, + 0xb4, 0x14, 0xb4, 0xcb, 0x43, 0x68, 0x0f, 0x8d, 0xf7, 0x2c, 0x61, 0xf4, 0xfb, 0xce, 0xf1, 0xaf, 0xe9, 0x2e, 0x52, 0x02, + 0x29, 0x5e, 0xd7, 0xc6, 0xed, 0xf6, 0x22, 0xb9, 0x7b, 0xe8, 0x1a, 0xe6, 0x59, 0xdb, 0x43, 0xdd, 0x58, 0xe2, 0x50, 0xab, + 0x57, 0x01, 0xf0, 0x61, 0xb0, 0x83, 0xa9, 0x40, 0x0c, 0x24, 0x08, 0x6e, 0x95, 0x45, 0xba, 0xb3, 0x02, 0xa9, 0x41, 0xde, + 0xaf, 0xc2, 0x4c, 0xc2, 0x71, 0x1e, 0x86, 0xe4, 0xe9, 0x81, 0x9e, 0xdf, 0xea, 0x11, 0x66, 0x91, 0x02, 0x8c, 0xf5, 0xa3, + 0x05, 0xe3, 0xe9, 0x6e, 0x7f, 0x34, 0xb5, 0x0a, 0x3f, 0xc3, 0x70, 0x18, 0x33, 0x33, 0x7e, 0x85, 0x81, 0x04, 0x1f, 0xaa, + 0x14, 0x0c, 0x57, 0xca, 0x41, 0x97, 0x79, 0x62, 0x2e, 0x99, 0xbc, 0x6f, 0xce, 0x21, 0xad, 0xde, 0x7d, 0x74, 0x73, 0x3f, + 0x75, 0x00, 0x65, 0xc2, 0x40, 0x5e, 0xda, 0xce, 0x41, 0x4e, 0x8b, 0xd0, 0x32, 0x4f, 0x7f, 0xee, 0xbe, 0xc9, 0x41, 0xb2, + 0x42, 0xe9, 0x5a, 0xe5, 0xee, 0x18, 0x0c, 0x70, 0x93, 0xec, 0xb2, 0x46, 0xcd, 0x11, 0x16, 0x31, 0x81, 0x33, 0x5e, 0x82, + 0x20, 0x85, 0x1b, 0x02, 0x76, 0xeb, 0x13, 0xb9, 0xd4, 0xbd, 0xf9, 0xe7, 0xb5, 0x5e, 0x5e, 0x05, 0x48, 0x74, 0x27, 0xf2, + 0xdc, 0x3e, 0x87, 0x8b, 0x33, 0x3f, 0x50, 0xb6, 0xc6, 0x52, 0xf8, 0x61, 0x69, 0x7e, 0x6b, 0x30, 0xef, 0x2c, 0x6c, 0x5e, + 0x69, 0xc8, 0xba, 0x1e, 0x3d, 0x2a, 0x0c, 0x74, 0xbd, 0x93, 0xc9, 0x36, 0xcc, 0x72, 0x15, 0xe6, 0xbb, 0xd0, 0xc0, 0xe3, + 0xaf, 0x60, 0xcd, 0x83, 0x54, 0x50, 0x67, 0xbb, 0x70, 0x2a, 0xa1, 0x51, 0x87, 0x9b, 0xc5, 0xe0, 0xbb, 0xa3, 0xb1, 0x6f, + 0x3a, 0x1a, 0x62, 0x72, 0x6f, 0x89, 0x8a, 0x1d, 0xc4, 0x09, 0x55, 0xac, 0x67, 0x7b, 0xa3, 0xe6, 0xed, 0x4e, 0xbb, 0xf2, + 0x5f, 0x42, 0x95, 0x7b, 0x95, 0x7a, 0xbe, 0x3e, 0xf5, 0x2f, 0xee, 0x5f, 0x30, 0x57, 0x51, 0x94, 0x7d, 0x45, 0xd5, 0xd7, + 0x6e, 0xcc, 0xf6, 0x4d, 0xac, 0x7b, 0x51, 0x70, 0x32, 0x07, 0x1c, 0xaf, 0x97, 0xdd, 0x92, 0x0d, 0x9d, 0xba, 0x53, 0xf5, + 0x49, 0xc7, 0xa5, 0x6a, 0x7a, 0x3b, 0xb0, 0x3f, 0x0c, 0x01, 0xa5, 0x00, 0x4a, 0x33, 0x90, 0xf7, 0xee, 0x0a, 0x12, 0x5d, + 0xc0, 0x5d, 0xb1, 0x85, 0x63, 0xed, 0xcf, 0xb8, 0x84, 0xde, 0x51, 0x8f, 0xd9, 0xf4, 0x15, 0x76, 0x43, 0xc4, 0xfe, 0x89, + 0x16, 0xfe, 0x13, 0x92, 0xbd, 0x25, 0x66, 0xb9, 0x56, 0x60, 0x1f, 0x85, 0x3d, 0xc6, 0x9a, 0x02, 0xc4, 0x2a, 0xbf, 0x8b, + 0x1b, 0xf1, 0x41, 0xbb, 0x37, 0x77, 0xe1, 0x18, 0xa7, 0x5f, 0x2a, 0x30, 0x37, 0xf6, 0xf4, 0x2a, 0x4b, 0x77, 0xf8, 0x15, + 0xc5, 0xb9, 0xb5, 0xdd, 0x93, 0x4f, 0x59, 0x97, 0x6b, 0xf2, 0xe8, 0x6e, 0xf5, 0x7e, 0x21, 0x20, 0x64, 0xac, 0xe8, 0x8d, + 0x60, 0xcb, 0xd2, 0xdc, 0xa7, 0xc8, 0x16, 0xb2, 0x7c, 0xf3, 0xbe, 0x88, 0x5b, 0x75, 0xcb, 0xf7, 0x38, 0x79, 0xa5, 0x32, + 0x5f, 0xa7, 0xf2, 0xfd, 0x6a, 0x21, 0x71, 0x16, 0x1b, 0xe9, 0xde, 0xd9, 0x88, 0xf2, 0x89, 0xef, 0x4f, 0x9a, 0xc4, 0x9b, + 0x04, 0xa0, 0x16, 0xab, 0x39, 0x62, 0x3f, 0x1f, 0x06, 0x2a, 0x88, 0x04, 0x68, 0x63, 0xb1, 0x21, 0x87, 0x25, 0xfb, 0xc3, + 0xb5, 0xe0, 0xc8, 0x48, 0x42, 0x4e, 0x3a, 0xc9, 0x90, 0x4c, 0xc1, 0xa5, 0x69, 0x62, 0xd6, 0x25, 0xdc, 0xc9, 0x51, 0xeb, + 0x6f, 0x00, 0x70, 0x91, 0x86, 0x57, 0x36, 0x23, 0x1f, 0x29, 0x8b, 0x52, 0xb2, 0x31, 0xd5, 0x8d, 0xc5, 0xa3, 0x5f, 0xd3, + 0x7a, 0xe4, 0x2e, 0x3a +}; + +/* Random data for hash agility attribute */ +uint8_t attribute[32] = { + 0x2e, 0xd0, 0xd3, 0x8f, 0xfd, 0xab, 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, + 0x87, 0xa0, 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6 +}; + +/* Valid CMS message on content with hash agility attribute */ +uint8_t valid_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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, + 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, + 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, + 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, + 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, + 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, + 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, + 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, + 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, + 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, + 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, + 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, + 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, + 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, + 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, + 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, + 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, + 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, + 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, + 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, + 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, + 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, + 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, + 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, + 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, + 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, + 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, + 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, + 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, + 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, + 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, + 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, + 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, + 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, + 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, + 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, + 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, + 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, + 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, + 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, + 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, + 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, + 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, + 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, + 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, + 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, + 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, + 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, + 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, + 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, + 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, + 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, + 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, + 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, + 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, + 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, + 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, + 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, + 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, + 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, + 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, + 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, + 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, + 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, + 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, + 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, + 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, + 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, + 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, + 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, + 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, + 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, + 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x6d, + 0x30, 0x82, 0x03, 0x69, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0x9a, + 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, 0x35, 0x31, 0x31, 0x30, + 0x34, 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, + 0xb9, 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, + 0xec, 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x63, 0x64, 0x09, 0x01, 0x31, 0x22, 0x04, 0x20, 0x2e, 0xd0, 0xd3, 0x8f, 0xfd, 0xab, + 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, 0x87, 0xa0, + 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x89, 0xd3, 0x00, + 0x9b, 0xd0, 0x99, 0x21, 0x21, 0x47, 0xff, 0xa3, 0x4c, 0xef, 0xa7, 0x6e, 0x03, 0x1e, 0xbf, 0x6d, + 0x10, 0x3e, 0xf7, 0x36, 0x7e, 0x98, 0xb4, 0xb6, 0x74, 0xa0, 0xa6, 0x2c, 0x83, 0x33, 0xec, 0xeb, + 0xb5, 0x69, 0x3b, 0x10, 0x80, 0x60, 0x2b, 0xf4, 0x71, 0x84, 0x2a, 0x22, 0xfa, 0xbe, 0x51, 0x3d, + 0x69, 0xdc, 0x2b, 0x94, 0xf6, 0x8a, 0x82, 0xee, 0x88, 0xa3, 0xa4, 0x8a, 0x4d, 0x13, 0xee, 0x4b, + 0xf2, 0xd0, 0xef, 0x3a, 0x2d, 0xe0, 0x3e, 0x52, 0xe9, 0x75, 0xf3, 0xf1, 0x8a, 0xc6, 0x68, 0xab, + 0x5f, 0x97, 0x7c, 0xef, 0x2e, 0x06, 0xe4, 0x53, 0x2e, 0xa5, 0x20, 0x8b, 0x8a, 0x1f, 0x0b, 0x8a, + 0xb2, 0x0e, 0xe0, 0x77, 0xbf, 0x4d, 0x0f, 0x45, 0x15, 0x7f, 0x03, 0xdc, 0x0a, 0x5c, 0xcc, 0x88, + 0x49, 0x0b, 0x19, 0xde, 0xd8, 0xdd, 0x62, 0xc6, 0xad, 0x77, 0xaa, 0x37, 0x19, 0x31, 0x6d, 0x57, + 0x7f, 0x29, 0xc1, 0xe2, 0x7a, 0x15, 0xf9, 0xb9, 0xa5, 0xe2, 0xf3, 0xeb, 0x3f, 0x27, 0x5d, 0xac, + 0x02, 0xb8, 0xf7, 0x6d, 0xfe, 0x0f, 0x22, 0x89, 0xe3, 0x5d, 0xcc, 0xf3, 0x6a, 0x8f, 0x1a, 0xe5, + 0x94, 0xfd, 0xad, 0x9a, 0xc2, 0x5d, 0xb5, 0x1b, 0x48, 0xd8, 0x0b, 0x77, 0x9c, 0x27, 0x24, 0x55, + 0xf3, 0x8f, 0x5b, 0x7e, 0x0a, 0x73, 0x35, 0xb4, 0x6c, 0xc7, 0x84, 0xc3, 0x0b, 0x22, 0x57, 0x4d, + 0xff, 0x45, 0x4d, 0x78, 0xa7, 0xd0, 0x7d, 0xcf, 0x74, 0x5c, 0xe8, 0xa6, 0x26, 0x76, 0xda, 0xf1, + 0x4f, 0x75, 0x89, 0xd1, 0x6c, 0x7e, 0x52, 0x8c, 0x6e, 0xa8, 0x6e, 0x4c, 0x5b, 0x54, 0x94, 0x35, + 0x92, 0xec, 0x22, 0x5c, 0xdd, 0x97, 0x41, 0xef, 0x9f, 0x6d, 0xa2, 0x63, 0xaa, 0x22, 0x81, 0xab, + 0xfa, 0x0d, 0x2d, 0xed, 0xe6, 0x45, 0xe4, 0x2a, 0x51, 0x1d, 0xa6, 0x8d, 0x24, 0x99, 0xda, 0xb6, + 0xe3, 0xeb, 0x56, 0xf8, 0x6d, 0xe7, 0xbf, 0x14, 0xfa, 0x41, 0x82, 0x93, 0x28, 0xb0, 0x3f, 0x83, + 0x3a, 0x10, 0x79, 0x18, 0x4f, 0x21, 0xc7, 0xd1, 0x5f, 0x80, 0x77, 0x98, 0x0e, 0x26, 0xdd, 0x36, + 0xc7, 0xc6, 0x6b, 0xd2, 0x42, 0xd8, 0xa1, 0xfc, 0x69, 0x90, 0xa6, 0xea, 0xe6, 0xf2, 0x5b, 0x78, + 0xb7, 0x27, 0xe2, 0x13, 0xc2, 0xe7, 0xdf, 0x37, 0x30, 0x94, 0xaf, 0xbf, 0x88, 0x63, 0x3d, 0xad, + 0xfc, 0xdb, 0xf4, 0x5f, 0x5c, 0x4b, 0x07, 0x36, 0xc2, 0xc2, 0xca, 0xe3, 0x3d, 0xd9, 0x51, 0x88, + 0x37, 0xb5, 0xd6, 0x36, 0x63, 0x42, 0x8b, 0xd3, 0x86, 0xc3, 0xc0, 0x1c, 0x08, 0x2c, 0x5c, 0x93, + 0x21, 0x3e, 0x7a, 0x54, 0x21, 0xa4, 0xbc, 0x78, 0xdc, 0x41, 0x78, 0x18, 0x83, 0xf6, 0x4d, 0x2d, + 0x3a, 0xa1, 0xf3, 0xd2, 0x3e, 0x31, 0x91, 0x6f, 0xf9, 0xd3, 0xd6, 0xe1, 0xef, 0x83, 0xd7, 0x59, + 0xc9, 0xa3, 0x36, 0xcc, 0x26, 0xfd, 0x7c, 0x93, 0x0a, 0x4e, 0xae, 0x45, 0x4b, 0xb0, 0x58, 0xd0, + 0xb0, 0xca, 0x70, 0x35, 0x2f, 0x63, 0x28, 0x9d, 0x5a, 0xc8, 0x02, 0xf9, 0x8b, 0xaa, 0xcf, 0x6d, + 0x8b, 0xbb, 0xb5, 0xf6, 0x44, 0xe4, 0xcb, 0x3d, 0xbe, 0xd2, 0x70, 0x2d, 0xb3, 0xe9, 0x05, 0x6c, + 0xfe, 0x41, 0xa3, 0x05, 0xec, 0xe4, 0xf1, 0x9e, 0x37, 0x04, 0xd1, 0x9a, 0x60, 0xf9, 0x95, 0xc4, + 0x11, 0xb3, 0xbf, 0x17, 0xa4, 0x72, 0x2a, 0x03, 0x2d, 0x9a, 0x2b, 0xed, 0x97, 0xc9, 0x29, 0x05, + 0x23, 0xbb, 0xd2, 0xfe, 0x0b, 0x91, 0x5b, 0x93, 0x3f, 0x93, 0x10, 0x69, 0xcb, 0x92, 0x14, 0x8c, + 0xd4, 0xf3, 0x4f, 0x51, 0xc4, 0x78, 0x52, 0xc1, 0xea, 0x20, 0xa9, 0x16, 0x9b, 0x51, 0xb3, 0x69, + 0xf7, 0x92, 0xea, 0x6e, 0x94, 0x53, 0xc8, 0xf0, 0xd1, 0x24, 0x38, 0x3a, 0x1d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +/* + * Invalid CMS message on content with hash agility attribute. + * Only the hash agility attribute value has been changed from the valid message. + */ +uint8_t invalid_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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, + 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, + 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, + 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, + 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, + 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, + 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, + 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, + 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, + 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, + 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, + 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, + 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, + 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, + 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, + 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, + 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, + 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, + 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, + 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, + 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, + 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, + 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, + 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, + 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, + 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, + 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, + 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, + 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, + 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, + 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, + 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, + 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, + 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, + 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, + 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, + 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, + 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, + 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, + 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, + 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, + 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, + 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, + 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, + 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, + 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, + 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, + 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, + 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, + 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, + 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, + 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, + 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, + 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, + 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, + 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, + 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, + 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, + 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, + 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, + 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, + 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, + 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, + 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, + 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, + 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, + 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, + 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, + 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, + 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, + 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, + 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, + 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x6d, + 0x30, 0x82, 0x03, 0x69, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0x9a, + 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, 0x35, 0x31, 0x31, 0x30, + 0x34, 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, + 0xb9, 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, + 0xec, 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x63, 0x64, 0x09, 0x01, 0x31, 0x22, 0x04, 0x20, 0x2e, 0xd0, 0xd0, 0x8f, 0xfd, 0xab, + 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, 0x87, 0xa0, + 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x89, 0xd3, 0x00, + 0x9b, 0xd0, 0x99, 0x21, 0x21, 0x47, 0xff, 0xa3, 0x4c, 0xef, 0xa7, 0x6e, 0x03, 0x1e, 0xbf, 0x6d, + 0x10, 0x3e, 0xf7, 0x36, 0x7e, 0x98, 0xb4, 0xb6, 0x74, 0xa0, 0xa6, 0x2c, 0x83, 0x33, 0xec, 0xeb, + 0xb5, 0x69, 0x3b, 0x10, 0x80, 0x60, 0x2b, 0xf4, 0x71, 0x84, 0x2a, 0x22, 0xfa, 0xbe, 0x51, 0x3d, + 0x69, 0xdc, 0x2b, 0x94, 0xf6, 0x8a, 0x82, 0xee, 0x88, 0xa3, 0xa4, 0x8a, 0x4d, 0x13, 0xee, 0x4b, + 0xf2, 0xd0, 0xef, 0x3a, 0x2d, 0xe0, 0x3e, 0x52, 0xe9, 0x75, 0xf3, 0xf1, 0x8a, 0xc6, 0x68, 0xab, + 0x5f, 0x97, 0x7c, 0xef, 0x2e, 0x06, 0xe4, 0x53, 0x2e, 0xa5, 0x20, 0x8b, 0x8a, 0x1f, 0x0b, 0x8a, + 0xb2, 0x0e, 0xe0, 0x77, 0xbf, 0x4d, 0x0f, 0x45, 0x15, 0x7f, 0x03, 0xdc, 0x0a, 0x5c, 0xcc, 0x88, + 0x49, 0x0b, 0x19, 0xde, 0xd8, 0xdd, 0x62, 0xc6, 0xad, 0x77, 0xaa, 0x37, 0x19, 0x31, 0x6d, 0x57, + 0x7f, 0x29, 0xc1, 0xe2, 0x7a, 0x15, 0xf9, 0xb9, 0xa5, 0xe2, 0xf3, 0xeb, 0x3f, 0x27, 0x5d, 0xac, + 0x02, 0xb8, 0xf7, 0x6d, 0xfe, 0x0f, 0x22, 0x89, 0xe3, 0x5d, 0xcc, 0xf3, 0x6a, 0x8f, 0x1a, 0xe5, + 0x94, 0xfd, 0xad, 0x9a, 0xc2, 0x5d, 0xb5, 0x1b, 0x48, 0xd8, 0x0b, 0x77, 0x9c, 0x27, 0x24, 0x55, + 0xf3, 0x8f, 0x5b, 0x7e, 0x0a, 0x73, 0x35, 0xb4, 0x6c, 0xc7, 0x84, 0xc3, 0x0b, 0x22, 0x57, 0x4d, + 0xff, 0x45, 0x4d, 0x78, 0xa7, 0xd0, 0x7d, 0xcf, 0x74, 0x5c, 0xe8, 0xa6, 0x26, 0x76, 0xda, 0xf1, + 0x4f, 0x75, 0x89, 0xd1, 0x6c, 0x7e, 0x52, 0x8c, 0x6e, 0xa8, 0x6e, 0x4c, 0x5b, 0x54, 0x94, 0x35, + 0x92, 0xec, 0x22, 0x5c, 0xdd, 0x97, 0x41, 0xef, 0x9f, 0x6d, 0xa2, 0x63, 0xaa, 0x22, 0x81, 0xab, + 0xfa, 0x0d, 0x2d, 0xed, 0xe6, 0x45, 0xe4, 0x2a, 0x51, 0x1d, 0xa6, 0x8d, 0x24, 0x99, 0xda, 0xb6, + 0xe3, 0xeb, 0x56, 0xf8, 0x6d, 0xe7, 0xbf, 0x14, 0xfa, 0x41, 0x82, 0x93, 0x28, 0xb0, 0x3f, 0x83, + 0x3a, 0x10, 0x79, 0x18, 0x4f, 0x21, 0xc7, 0xd1, 0x5f, 0x80, 0x77, 0x98, 0x0e, 0x26, 0xdd, 0x36, + 0xc7, 0xc6, 0x6b, 0xd2, 0x42, 0xd8, 0xa1, 0xfc, 0x69, 0x90, 0xa6, 0xea, 0xe6, 0xf2, 0x5b, 0x78, + 0xb7, 0x27, 0xe2, 0x13, 0xc2, 0xe7, 0xdf, 0x37, 0x30, 0x94, 0xaf, 0xbf, 0x88, 0x63, 0x3d, 0xad, + 0xfc, 0xdb, 0xf4, 0x5f, 0x5c, 0x4b, 0x07, 0x36, 0xc2, 0xc2, 0xca, 0xe3, 0x3d, 0xd9, 0x51, 0x88, + 0x37, 0xb5, 0xd6, 0x36, 0x63, 0x42, 0x8b, 0xd3, 0x86, 0xc3, 0xc0, 0x1c, 0x08, 0x2c, 0x5c, 0x93, + 0x21, 0x3e, 0x7a, 0x54, 0x21, 0xa4, 0xbc, 0x78, 0xdc, 0x41, 0x78, 0x18, 0x83, 0xf6, 0x4d, 0x2d, + 0x3a, 0xa1, 0xf3, 0xd2, 0x3e, 0x31, 0x91, 0x6f, 0xf9, 0xd3, 0xd6, 0xe1, 0xef, 0x83, 0xd7, 0x59, + 0xc9, 0xa3, 0x36, 0xcc, 0x26, 0xfd, 0x7c, 0x93, 0x0a, 0x4e, 0xae, 0x45, 0x4b, 0xb0, 0x58, 0xd0, + 0xb0, 0xca, 0x70, 0x35, 0x2f, 0x63, 0x28, 0x9d, 0x5a, 0xc8, 0x02, 0xf9, 0x8b, 0xaa, 0xcf, 0x6d, + 0x8b, 0xbb, 0xb5, 0xf6, 0x44, 0xe4, 0xcb, 0x3d, 0xbe, 0xd2, 0x70, 0x2d, 0xb3, 0xe9, 0x05, 0x6c, + 0xfe, 0x41, 0xa3, 0x05, 0xec, 0xe4, 0xf1, 0x9e, 0x37, 0x04, 0xd1, 0x9a, 0x60, 0xf9, 0x95, 0xc4, + 0x11, 0xb3, 0xbf, 0x17, 0xa4, 0x72, 0x2a, 0x03, 0x2d, 0x9a, 0x2b, 0xed, 0x97, 0xc9, 0x29, 0x05, + 0x23, 0xbb, 0xd2, 0xfe, 0x0b, 0x91, 0x5b, 0x93, 0x3f, 0x93, 0x10, 0x69, 0xcb, 0x92, 0x14, 0x8c, + 0xd4, 0xf3, 0x4f, 0x51, 0xc4, 0x78, 0x52, 0xc1, 0xea, 0x20, 0xa9, 0x16, 0x9b, 0x51, 0xb3, 0x69, + 0xf7, 0x92, 0xea, 0x6e, 0x94, 0x53, 0xc8, 0xf0, 0xd1, 0x24, 0x38, 0x3a, 0x1d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +/* Valid CMS message with no hash agility attribute */ +unsigned char valid_no_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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, + 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, + 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, + 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, + 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, + 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, + 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, + 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, + 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, + 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, + 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, + 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, + 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, + 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, + 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, + 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, + 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, + 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, + 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, + 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, + 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, + 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, + 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, + 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, + 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, + 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, + 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, + 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, + 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, + 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, + 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, + 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, + 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, + 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, + 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, + 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, + 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, + 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, + 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, + 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, + 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, + 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, + 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, + 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, + 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, + 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, + 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, + 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, + 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, + 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, + 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, + 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, + 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, + 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, + 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, + 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, + 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, + 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, + 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, + 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, + 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, + 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, + 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, + 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, + 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, + 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, + 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, + 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, + 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, + 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, + 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, + 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, + 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x3b, + 0x30, 0x82, 0x03, 0x37, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 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, 0x35, 0x31, 0x31, 0x30, 0x34, + 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, 0xb9, + 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, 0xec, + 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xbc, 0x5a, 0x74, 0xac, 0x24, + 0x13, 0xa5, 0xa3, 0xfb, 0x61, 0xfb, 0x19, 0x7a, 0x3f, 0x7b, 0x46, 0x5a, 0xcd, 0x8a, 0x92, 0x23, + 0xeb, 0xd0, 0xdf, 0xf2, 0x05, 0xbe, 0x02, 0xf9, 0xd5, 0x81, 0xca, 0x16, 0xf9, 0xd9, 0x63, 0x9e, + 0x19, 0xb8, 0xea, 0x1d, 0x51, 0x2c, 0xfc, 0x65, 0x0c, 0x67, 0x31, 0x5d, 0xa2, 0x87, 0x40, 0xa2, + 0x58, 0x57, 0x35, 0xe1, 0xa2, 0xc8, 0x25, 0xe4, 0x79, 0xd1, 0xc2, 0x76, 0x26, 0x20, 0x11, 0x76, + 0x38, 0xc8, 0xa1, 0x08, 0x98, 0x7c, 0x28, 0x8a, 0x14, 0x23, 0x89, 0xfa, 0xe6, 0x55, 0xaf, 0x47, + 0x1f, 0xe8, 0x5c, 0xc4, 0x0b, 0x88, 0x27, 0x75, 0xf5, 0x2d, 0x2c, 0x63, 0x63, 0x7b, 0xd3, 0x2b, + 0xd2, 0xb1, 0x4d, 0xf5, 0xd3, 0xa9, 0xdc, 0xc1, 0x34, 0x9d, 0xb8, 0x44, 0xae, 0xa3, 0x41, 0xd7, + 0x1e, 0x02, 0xff, 0x06, 0x3d, 0x8b, 0x3b, 0x01, 0xc6, 0xa9, 0x0f, 0x7a, 0x59, 0x03, 0x05, 0x2a, + 0xcf, 0x19, 0xc1, 0xd2, 0xea, 0x30, 0x3f, 0xbd, 0x83, 0x80, 0x26, 0xd7, 0x73, 0x32, 0x00, 0x8d, + 0x4f, 0x69, 0xaa, 0xf0, 0x39, 0x3f, 0xae, 0x46, 0xfc, 0x19, 0x7e, 0x62, 0xd2, 0xc8, 0x59, 0xa2, + 0xd1, 0x23, 0xa2, 0xab, 0xdd, 0x5b, 0xbc, 0xa9, 0x4d, 0x8c, 0x3a, 0xa4, 0x9d, 0x8e, 0x80, 0x0c, + 0x2b, 0x2d, 0x26, 0x27, 0xb7, 0xf2, 0xb9, 0x19, 0xc5, 0x8e, 0x17, 0x44, 0xb2, 0x19, 0x29, 0x3b, + 0x25, 0x7e, 0x76, 0xf8, 0x97, 0x85, 0xbc, 0x78, 0xa4, 0x41, 0xcb, 0x10, 0xed, 0xd7, 0x8c, 0x4c, + 0x56, 0x44, 0xfc, 0x7c, 0xa8, 0x98, 0xff, 0xa5, 0xef, 0x21, 0xe4, 0xc2, 0x2b, 0xaf, 0xfb, 0xb2, + 0xcb, 0x4c, 0x63, 0x19, 0x53, 0xae, 0xc4, 0xbc, 0x44, 0x31, 0xcb, 0x06, 0x2f, 0x01, 0x2b, 0x6b, + 0x7e, 0xd8, 0x24, 0x76, 0x16, 0x74, 0xa5, 0xb2, 0x46, 0xff, 0x14, 0xde, 0xc8, 0xe5, 0xfc, 0xeb, + 0xfa, 0xb8, 0xc2, 0x39, 0x9d, 0xf6, 0xdd, 0xbb, 0xba, 0x7d, 0x2d, 0x49, 0x4c, 0x7d, 0x87, 0xe2, + 0x0a, 0xb7, 0x52, 0xb5, 0x3d, 0x9d, 0x02, 0xf2, 0x04, 0x3d, 0x9b, 0x8b, 0x04, 0xe8, 0x84, 0x50, + 0x19, 0xb7, 0xfa, 0x4f, 0x9f, 0xa6, 0x00, 0x06, 0x2a, 0x44, 0xb2, 0x58, 0x91, 0x2f, 0xde, 0xd6, + 0x25, 0xcc, 0xd5, 0x68, 0x04, 0x51, 0xb1, 0x0f, 0x08, 0x41, 0xdd, 0xea, 0x16, 0x70, 0xbd, 0x5a, + 0xbc, 0x05, 0x60, 0xbc, 0xd4, 0x67, 0x62, 0xe2, 0xc3, 0xc0, 0x79, 0xdf, 0x49, 0xd7, 0x52, 0x62, + 0xde, 0xce, 0x68, 0x5c, 0x32, 0x9b, 0xd3, 0xb8, 0xef, 0x62, 0x7b, 0x4b, 0x0e, 0x15, 0xae, 0x92, + 0xfb, 0x06, 0x36, 0xb9, 0x05, 0x72, 0x2f, 0x01, 0x55, 0x70, 0x2b, 0x09, 0x54, 0xe1, 0x70, 0x15, + 0xab, 0x24, 0xcb, 0x07, 0x4c, 0x7e, 0xde, 0x38, 0xb2, 0x03, 0x56, 0xdb, 0x2f, 0x8c, 0x3b, 0xe5, + 0x5e, 0x1a, 0xbb, 0x90, 0x08, 0x55, 0xb2, 0x3d, 0xd9, 0x6f, 0xe8, 0x81, 0x08, 0x04, 0x5e, 0x82, + 0x84, 0x7e, 0x9c, 0x3f, 0x5a, 0x66, 0x6f, 0x6c, 0xc6, 0x98, 0x82, 0x27, 0xb6, 0x49, 0x7b, 0x14, + 0x07, 0x9d, 0x20, 0x61, 0x9d, 0xd9, 0x3d, 0xd0, 0x71, 0x0c, 0x72, 0x82, 0x50, 0xac, 0x61, 0xcd, + 0xc5, 0xc6, 0xc9, 0x90, 0xe2, 0x92, 0x5b, 0x02, 0x73, 0xda, 0x98, 0x2e, 0x21, 0x1e, 0x66, 0x79, + 0x83, 0x2e, 0x1d, 0x66, 0x0e, 0x2b, 0x6d, 0x42, 0x7d, 0xf4, 0x0a, 0xd3, 0xa1, 0x9b, 0x7f, 0x61, + 0xa7, 0x13, 0x3a, 0xa4, 0x6e, 0x0d, 0x0b, 0xbf, 0x42, 0x32, 0xf7, 0xca, 0x0e, 0x96, 0x0a, 0xcb, + 0x9a, 0x0a, 0x6a, 0x24, 0x8c, 0x43, 0x76, 0x0e, 0xa8, 0x71, 0xcd, 0x3f, 0xc4, 0x85, 0x46, 0x50, + 0xb9, 0x65, 0x43, 0x49, 0xae, 0x31, 0x25, 0x76, 0x4b, 0xfb, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +#endif /* cms_hashagility_test_h */ diff --git a/OSX/libsecurity_cms/regressions/cms_regressions.h b/OSX/libsecurity_cms/regressions/cms_regressions.h new file mode 100644 index 00000000..30a2e4e6 --- /dev/null +++ b/OSX/libsecurity_cms/regressions/cms_regressions.h @@ -0,0 +1,28 @@ +/* + * 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 + +ONE_TEST(cms_hash_agility_test) \ No newline at end of file diff --git a/OSX/libsecurity_codesigning/lib/CSCommon.h b/OSX/libsecurity_codesigning/lib/CSCommon.h index 70058cf1..be1be0fd 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommon.h +++ b/OSX/libsecurity_codesigning/lib/CSCommon.h @@ -115,6 +115,9 @@ CF_ENUM(OSStatus) { errSecCSInvalidPlatform = -67005, /* invalid platform identifier or platform mismatch */ errSecCSTooBig = -67004, /* code is too big for current signing format */ errSecCSInvalidSymlink = -67003, /* invalid destination for symbolic link in bundle */ + 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 */ }; /* @@ -308,6 +311,27 @@ typedef CF_ENUM(uint32_t, SecRequirementType) { kSecInvalidRequirementType, /* invalid type of Requirement (must be last) */ kSecRequirementTypeCount = kSecInvalidRequirementType /* number of valid requirement types */ }; + + +/*! + Types of cryptographic digests (hashes) used to hold code signatures + together. + + Each combination of type, length, and other parameters is a separate + hash type; we don't understand "families" here. + + These type codes govern the digest links that connect a CodeDirectory + to its subordinate data structures (code pages, resources, etc.) + They do not directly control other uses of hashes (such as those used + within X.509 certificates and CMS blobs). + */ +typedef CF_ENUM(uint32_t, SecCSDigestAlgorithm) { + kSecCodeSignatureNoHash = 0, /* null value */ + kSecCodeSignatureHashSHA1 = 1, /* SHA-1 */ + kSecCodeSignatureHashSHA256 = 2, /* SHA-256 */ + kSecCodeSignatureHashSHA256Truncated = 3, /* SHA-256 truncated to first 20 bytes */ + kSecCodeSignatureHashSHA384 = 4, /* SHA-384 */ +}; CF_ASSUME_NONNULL_END diff --git a/OSX/libsecurity_codesigning/lib/CSCommonPriv.h b/OSX/libsecurity_codesigning/lib/CSCommonPriv.h index a03ac61d..29299cb8 100644 --- a/OSX/libsecurity_codesigning/lib/CSCommonPriv.h +++ b/OSX/libsecurity_codesigning/lib/CSCommonPriv.h @@ -86,28 +86,6 @@ enum { kSecCodeMagicByte = 0xfa /* shared first byte */ }; - - -/*! - Types of cryptographic digests (hashes) used to hold code signatures - together. - - Each combination of type, length, and other parameters is a separate - hash type; we don't understand "families" here. - - These type codes govern the digest links that connect a CodeDirectory - to its subordinate data structures (code pages, resources, etc.) - They do not directly control other uses of hashes (such as the - hash-of-CodeDirectory identifiers used in requirements). - */ -enum { - kSecCodeSignatureNoHash = 0, /* null value */ - kSecCodeSignatureHashSHA1 = 1, /* SHA-1 */ - kSecCodeSignatureHashSHA256 = 2, /* SHA-256 */ - kSecCodeSignatureHashSHA256Truncated = 3, /* SHA-256 truncated to first 20 bytes */ - - kSecCodeSignatureDefaultDigestAlgorithm = kSecCodeSignatureHashSHA1 -}; /* diff --git a/OSX/libsecurity_codesigning/lib/Code.cpp b/OSX/libsecurity_codesigning/lib/Code.cpp index 643c4f58..3194bf3d 100644 --- a/OSX/libsecurity_codesigning/lib/Code.cpp +++ b/OSX/libsecurity_codesigning/lib/Code.cpp @@ -205,7 +205,9 @@ void SecCode::checkValidity(SecCSFlags flags) SecStaticCode *hostDisk = this->host()->staticCode(); // check my static state - myDisk->validateDirectory(); + myDisk->validateNonResourceComponents(); // also validates the CodeDirectory + if (flags & kSecCSStrictValidate) + myDisk->diskRep()->strictValidate(myDisk->codeDirectory(), DiskRep::ToleratedErrors(), flags); // check my own dynamic state if (!(this->host()->getGuestStatus(this) & kSecCodeStatusValid)) diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp index 3d80482c..783262ba 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.cpp @@ -65,7 +65,7 @@ public: // Construct a SecCodeSigner // SecCodeSigner::SecCodeSigner(SecCSFlags flags) - : mOpFlags(flags), mDigestAlgorithm(kSecCodeSignatureDefaultDigestAlgorithm), mLimitedAsync(NULL) + : mOpFlags(flags), mLimitedAsync(NULL) { } @@ -172,30 +172,6 @@ void SecCodeSigner::returnDetachedSignature(BlobCore *blob, Signer &signer) } -// -// Our DiskRep::signingContext methods communicate with the signing subsystem -// in terms those callers can easily understand. -// -string SecCodeSigner::sdkPath(const std::string &path) const -{ - assert(path[0] == '/'); // need absolute path here - if (mSDKRoot) - return cfString(mSDKRoot) + path; - else - return path; -} - -bool SecCodeSigner::isAdhoc() const -{ - return mSigner == SecIdentityRef(kCFNull); -} - -SecCSFlags SecCodeSigner::signingFlags() const -{ - return mOpFlags; -} - - // // The actual parsing operation is done in the Parser class. // @@ -219,8 +195,11 @@ SecCodeSigner::Parser::Parser(SecCodeSigner &state, CFDictionaryRef parameters) state.mCdFlagsGiven = false; // digest algorithms are specified as a numeric code - if (CFNumberRef digestAlgorithm = get(kSecCodeSignerDigestAlgorithm)) - state.mDigestAlgorithm = cfNumber(digestAlgorithm); + if (CFCopyRef digestAlgorithms = get(kSecCodeSignerDigestAlgorithm)) { + CFRef array = cfArrayize(digestAlgorithms); + CFToVector > digests(array); + std::copy(digests.begin(), digests.end(), std::inserter(state.mDigestAlgorithms, state.mDigestAlgorithms.begin())); + } if (CFNumberRef cmsSize = get(CFSTR("cmssize"))) state.mCMSSize = cfNumber(cmsSize); diff --git a/OSX/libsecurity_codesigning/lib/CodeSigner.h b/OSX/libsecurity_codesigning/lib/CodeSigner.h index c17c5801..e9e41d28 100644 --- a/OSX/libsecurity_codesigning/lib/CodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/CodeSigner.h @@ -41,7 +41,7 @@ namespace CodeSigning { // A SecCode object represents running code in the system. It must be subclassed // to implement a particular notion of code. // -class SecCodeSigner : public SecCFObject, public DiskRep::SigningContext { +class SecCodeSigner : public SecCFObject { NOCOPY(SecCodeSigner) public: class Parser; @@ -62,13 +62,10 @@ public: void remove(SecStaticCode *code, SecCSFlags flags); void returnDetachedSignature(BlobCore *blob, Signer &signer); - -protected: - std::string sdkPath(const std::string &path) const; - bool isAdhoc() const; - SecCSFlags signingFlags() const; -private: + const CodeDirectory::HashAlgorithms &digestAlgorithms() const { return mDigestAlgorithms; } + +public: // parsed parameter set SecCSFlags mOpFlags; // operation flags CFRef mSigner; // signing identity @@ -83,7 +80,7 @@ private: uint32_t mCdFlags; // CodeDirectory flags uint32_t mPreserveMetadata; // metadata preservation options bool mCdFlagsGiven; // CodeDirectory flags were specified - CodeDirectory::HashAlgorithm mDigestAlgorithm; // interior digest (hash) algorithm + CodeDirectory::HashAlgorithms mDigestAlgorithms; // interior digest (hash) algorithm std::string mIdentifier; // unique identifier override std::string mIdentifierPrefix; // prefix for un-dotted default identifiers std::string mTeamID; // teamID diff --git a/OSX/libsecurity_codesigning/lib/SecCode.cpp b/OSX/libsecurity_codesigning/lib/SecCode.cpp index 2544d654..59587ce7 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCode.cpp @@ -209,6 +209,7 @@ OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags, checkFlags(flags, kSecCSConsiderExpiration + | kSecCSStrictValidate | kSecCSEnforceRevocationChecks); SecPointer code = SecCode::required(codeRef); code->checkValidity(flags); @@ -271,6 +272,7 @@ const CFStringRef kSecCodeInfoEntitlementsDict = CFSTR("entitlements-dict"); const CFStringRef kSecCodeInfoFlags = CFSTR("flags"); const CFStringRef kSecCodeInfoFormat = CFSTR("format"); const CFStringRef kSecCodeInfoDigestAlgorithm = CFSTR("digest-algorithm"); +const CFStringRef kSecCodeInfoDigestAlgorithms = CFSTR("digest-algorithms"); const CFStringRef kSecCodeInfoPlatformIdentifier = CFSTR("platform-identifier"); const CFStringRef kSecCodeInfoIdentifier = CFSTR("identifier"); const CFStringRef kSecCodeInfoImplicitDesignatedRequirement = CFSTR("implicit-requirement"); @@ -285,6 +287,8 @@ const CFStringRef kSecCodeInfoTime = CFSTR("signing-time"); const CFStringRef kSecCodeInfoTimestamp = CFSTR("signing-timestamp"); const CFStringRef kSecCodeInfoTrust = CFSTR("trust"); const CFStringRef kSecCodeInfoUnique = CFSTR("unique"); +const CFStringRef kSecCodeInfoCdHashes = CFSTR("cdhashes"); + const CFStringRef kSecCodeInfoCodeDirectory = CFSTR("CodeDirectory"); const CFStringRef kSecCodeInfoCodeOffset = CFSTR("CodeOffset"); diff --git a/OSX/libsecurity_codesigning/lib/SecCode.h b/OSX/libsecurity_codesigning/lib/SecCode.h index 415506b4..a5c7dd0e 100644 --- a/OSX/libsecurity_codesigning/lib/SecCode.h +++ b/OSX/libsecurity_codesigning/lib/SecCode.h @@ -340,7 +340,10 @@ 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 used within the signature to seal its pieces together. + hash function actually used to establish integrity of the signature. + @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. @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 @@ -406,6 +409,7 @@ extern const CFStringRef kSecCodeInfoEntitlementsDict; /* Requirement */ extern const CFStringRef kSecCodeInfoFlags; /* generic */ extern const CFStringRef kSecCodeInfoFormat; /* generic */ extern const CFStringRef kSecCodeInfoDigestAlgorithm; /* generic */ +extern const CFStringRef kSecCodeInfoDigestAlgorithms; /* generic */ extern const CFStringRef kSecCodeInfoPlatformIdentifier; /* generic */ extern const CFStringRef kSecCodeInfoIdentifier; /* generic */ extern const CFStringRef kSecCodeInfoImplicitDesignatedRequirement; /* Requirement */ @@ -420,6 +424,7 @@ extern const CFStringRef kSecCodeInfoTime; /* Signing */ extern const CFStringRef kSecCodeInfoTimestamp; /* Signing */ extern const CFStringRef kSecCodeInfoTrust; /* Signing */ extern const CFStringRef kSecCodeInfoUnique; /* generic */ +extern const CFStringRef kSecCodeInfoCdHashes; /* generic */ OSStatus SecCodeCopySigningInformation(SecStaticCodeRef code, SecCSFlags flags, CFDictionaryRef * __nonnull CF_RETURNS_RETAINED information); diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp b/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp index e9965556..bae22bd5 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp @@ -60,13 +60,6 @@ const CFStringRef kSecCodeSignerPreserveMetadata = CFSTR("preserve-metadata"); const CFStringRef kSecCodeSignerTeamIdentifier = CFSTR("teamidentifier"); const CFStringRef kSecCodeSignerPlatformIdentifier = CFSTR("platform-identifier"); -// temporary add-back to bridge B&I build dependencies -- remove soon -const CFStringRef kSecCodeSignerTSAUse = CFSTR("timestamp-required"); -const CFStringRef kSecCodeSignerTSAURL = CFSTR("timestamp-url"); -const CFStringRef kSecCodeSignerTSAClientAuth = CFSTR("timestamp-authentication"); -const CFStringRef kSecCodeSignerTSANoCerts = CFSTR("timestamp-omit-certificates"); - - // // CF-standard type code functions // diff --git a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h index 4dead60d..7b3704b2 100644 --- a/OSX/libsecurity_codesigning/lib/SecCodeSigner.h +++ b/OSX/libsecurity_codesigning/lib/SecCodeSigner.h @@ -164,7 +164,8 @@ enum { kSecCodeSignerPreserveEntitlements = 1 << 2, // preserve entitlements kSecCodeSignerPreserveResourceRules = 1 << 3, // preserve resource rules (and thus resources) kSecCodeSignerPreserveFlags = 1 << 4, // preserve signing flags - kSecCodeSignerPreserveTeamIdentifier = 1 << 5, // preserve team identifier flags + kSecCodeSignerPreserveTeamIdentifier = 1 << 5, // preserve team identifier flags + kSecCodeSignerPreserveDigestAlgorithm = 1 << 6, // preserve digest algorithms used }; diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp index 0d3ed8b1..18625c27 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.cpp @@ -120,6 +120,7 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se | kSecCSStrictValidate | kSecCSCheckGatekeeperArchitectures | kSecCSRestrictSymlinks + | kSecCSRestrictToAppLike ); if (errors) diff --git a/OSX/libsecurity_codesigning/lib/SecStaticCode.h b/OSX/libsecurity_codesigning/lib/SecStaticCode.h index a5e17ebb..c8f9d40e 100644 --- a/OSX/libsecurity_codesigning/lib/SecStaticCode.h +++ b/OSX/libsecurity_codesigning/lib/SecStaticCode.h @@ -151,6 +151,7 @@ CF_ENUM(uint32_t) { kSecCSFullReport = 1 << 5, kSecCSCheckGatekeeperArchitectures = (1 << 6) | kSecCSCheckAllArchitectures, kSecCSRestrictSymlinks = 1 << 7, + kSecCSRestrictToAppLike = 1 << 8, }; OSStatus SecStaticCodeCheckValidity(SecStaticCodeRef staticCode, SecCSFlags flags, diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.cpp b/OSX/libsecurity_codesigning/lib/StaticCode.cpp index 6bcfb500..0b993cc7 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.cpp +++ b/OSX/libsecurity_codesigning/lib/StaticCode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2006-2015 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -94,9 +94,6 @@ SecStaticCode::SecStaticCode(DiskRep *rep) mDesignatedReq(NULL), mGotResourceBase(false), mMonitor(NULL), mLimitedAsync(NULL), mEvalDetails(NULL) { CODESIGN_STATIC_CREATE(this, rep); - CFRef codeDirectory = rep->codeDirectory(); - if (codeDirectory && CFDataGetLength(codeDirectory) <= 0) - MacOSError::throwMe(errSecCSSignatureInvalid); checkForSystemSignature(); } @@ -377,14 +374,15 @@ CFDataRef SecStaticCode::component(CodeDirectory::SpecialSlot slot, OSStatus fai // Always throws if the CodeDirectory exists but is invalid. // NEVER validates against the signature. // -const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) +const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) const { if (!mDir) { - if (mDir.take(mRep->codeDirectory())) { - const CodeDirectory *dir = reinterpret_cast(CFDataGetBytePtr(mDir)); - if (!dir->validateBlob(CFDataGetLength(mDir))) - MacOSError::throwMe(errSecCSSignatureInvalid); - dir->checkIntegrity(); + // 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); } } if (mDir) @@ -395,6 +393,41 @@ const CodeDirectory *SecStaticCode::codeDirectory(bool check /* = true */) } +// +// Fetch an array of all available CodeDirectories. +// Returns false if unsigned (no classic CD slot), true otherwise. +// +bool SecStaticCode::loadCodeDirectories(CodeDirectoryMap& cdMap) const +{ + __block CodeDirectoryMap candidates; + auto add = ^bool (CodeDirectory::SpecialSlot slot){ + CFRef cdData = diskRep()->component(slot); + if (!cdData) + return false; + const CodeDirectory* cd = reinterpret_cast(CFDataGetBytePtr(cdData)); + if (!cd->validateBlob(CFDataGetLength(cdData))) + MacOSError::throwMe(errSecCSSignatureFailed); // no recovery - any suspect CD fails + 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); + if (slot == cdCodeDirectorySlot) + mBaseDir = cdData; + return true; + }; + if (!add(cdCodeDirectorySlot)) + return false; // no classic slot CodeDirectory -> unsigned + for (CodeDirectory::SpecialSlot slot = cdAlternateCodeDirectorySlots; slot < cdAlternateCodeDirectoryLimit; slot++) + if (!add(slot)) // no CodeDirectory at this slot -> end of alternates + break; + if (candidates.empty()) + MacOSError::throwMe(errSecCSSignatureFailed); // no viable CodeDirectory in sight + cdMap.swap(candidates); + return true; +} + + // // Get the hash of the CodeDirectory. // Returns NULL if there is none. @@ -409,6 +442,25 @@ CFDataRef SecStaticCode::cdHash() } return mCDHash; } + + +// +// Get an array of the cdhashes for all digest types in this signature +// The array is sorted by cd->hashType. +// +CFArrayRef SecStaticCode::cdHashes() +{ + if (!mCDHashes) { + CFRef cdList = makeCFMutableArray(0); + for (auto it = mCodeDirectories.begin(); it != mCodeDirectories.end(); ++it) { + const CodeDirectory *cd = (const CodeDirectory *)CFDataGetBytePtr(it->second); + if (CFRef hash = cd->cdhash()) + CFArrayAppendValue(cdList, hash); + } + mCDHashes = cdList.get(); + } + return mCDHashes; +} // @@ -484,6 +536,33 @@ void SecStaticCode::validateNonResourceComponents() break; } } + + +// +// Check that any "top index" sealed into the signature conforms to what's actually here. +// +void SecStaticCode::validateTopDirectory() +{ + assert(mDir); // must already have loaded CodeDirectories + if (CFDataRef topDirectory = component(cdTopDirectorySlot)) { + const auto topData = (const Endian *)CFDataGetBytePtr(topDirectory); + const auto topDataEnd = topData + CFDataGetLength(topDirectory) / sizeof(*topData); + std::vector signedVector(topData, topDataEnd); + + std::vector foundVector; + foundVector.push_back(cdCodeDirectorySlot); // mandatory + for (CodeDirectory::Slot slot = 1; slot <= cdSlotMax; ++slot) + if (component(slot)) + foundVector.push_back(slot); + int alternateCount = int(mCodeDirectories.size() - 1); // one will go into cdCodeDirectorySlot + for (unsigned n = 0; n < alternateCount; n++) + foundVector.push_back(cdAlternateCodeDirectorySlots + n); + foundVector.push_back(cdSignatureSlot); // mandatory (may be empty) + + if (signedVector != foundVector) + MacOSError::throwMe(errSecCSSignatureFailed); + } +} // @@ -508,7 +587,7 @@ CFAbsoluteTime SecStaticCode::signingTimestamp() // -// Verify the CMS signature on the CodeDirectory. +// Verify the CMS signature. // This performs the cryptographic tango. It returns if the signature is valid, // or throws if it is not. As a side effect, a successful return sets up the // cached certificate chain for future use. @@ -531,7 +610,7 @@ bool SecStaticCode::verifySignature() CFDataRef sig = this->signature(); MacOSError::check(CMSDecoderUpdateMessage(cms, CFDataGetBytePtr(sig), CFDataGetLength(sig))); this->codeDirectory(); // load CodeDirectory (sets mDir) - MacOSError::check(CMSDecoderSetDetachedContent(cms, mDir)); + MacOSError::check(CMSDecoderSetDetachedContent(cms, mBaseDir)); MacOSError::check(CMSDecoderFinalizeMessage(cms)); MacOSError::check(CMSDecoderSetSearchKeychain(cms, cfEmptyArray())); CFRef vf_policies = verificationPolicies(); @@ -554,6 +633,24 @@ 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())) { + case noErr: + if (hashBag) { + CFRef hashDict = makeCFDictionaryFrom(hashBag); + CFArrayRef cdList = CFArrayRef(CFDictionaryGetValue(hashDict, CFSTR("cdhashes"))); + CFArrayRef myCdList = this->cdHashes(); + if (cdList == NULL || !CFEqual(cdList, myCdList)) + MacOSError::throwMe(errSecCSSignatureFailed); + } + break; + case -1: /* CMS used to return this for "no attribute found", so tolerate it. Now returning noErr/NULL */ + break; + default: + MacOSError::throwMe(rc); + } // internal signing time (as specified by the signer; optional) mSigningTime = 0; // "not present" marker (nobody could code sign on Jan 1, 2001 :-) @@ -776,15 +873,24 @@ void SecStaticCode::validateExecutable() if (Universal *fat = mRep->mainExecutableImage()) fd.seek(fat->archOffset()); size_t pageSize = cd->pageSize ? (1 << cd->pageSize) : 0; - size_t remaining = cd->codeLimit; + size_t remaining = cd->signingLimit(); for (uint32_t slot = 0; slot < cd->nCodeSlots; ++slot) { - size_t size = min(remaining, pageSize); - if (!cd->validateSlot(fd, size, slot)) { + size_t thisPage = remaining; + if (pageSize) + thisPage = min(thisPage, pageSize); + __block bool good = true; + CodeDirectory::multipleHashFileData(fd, thisPage, hashAlgorithms(), ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { + const CodeDirectory* cd = (const CodeDirectory*)CFDataGetBytePtr(mCodeDirectories[type]); + if (!hasher->verify((*cd)[slot])) + good = false; + }); + if (!good) { CODESIGN_EVAL_STATIC_EXECUTABLE_FAIL(this, (int)slot); MacOSError::throwMe(errSecCSSignatureFailed); } - remaining -= size; + remaining -= thisPage; } + assert(remaining == 0); mExecutableValidated = true; mExecutableValidResult = errSecSuccess; } catch (const CommonError &err) { @@ -889,7 +995,7 @@ void SecStaticCode::validateResources(SecCSFlags flags) // scan through the resources on disk, checking each against the resourceDirectory __block CFRef resourceMap = makeCFMutableDictionary(files); string base = cfString(this->resourceBase()); - ResourceBuilder resources(base, base, rules, codeDirectory()->hashType, strict, mTolerateErrors); + ResourceBuilder resources(base, base, rules, strict, mTolerateErrors); this->mResourceScope = &resources; diskRep()->adjustResources(resources); @@ -1096,7 +1202,7 @@ CFDataRef SecStaticCode::resource(string path, ValidationContext &ctx) { if (CFDictionaryRef rdict = resourceDictionary()) { if (CFTypeRef file = cfget(rdict, "files.%s", path.c_str())) { - ResourceSeal seal = file; + ResourceSeal seal(file); if (!resourceBase()) // no resources in DiskRep MacOSError::throwMe(errSecCSResourcesNotFound); if (seal.nested()) @@ -1105,7 +1211,7 @@ CFDataRef SecStaticCode::resource(string path, ValidationContext &ctx) if (CFRef data = cfLoadFile(fullpath)) { MakeHash hasher(this->codeDirectory()); hasher->update(CFDataGetBytePtr(data), CFDataGetLength(data)); - if (hasher->verify(seal.hash())) + if (hasher->verify(seal.hash(hashAlgorithm()))) return data.yield(); // good else ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // altered @@ -1134,7 +1240,8 @@ void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool is MacOSError::throwMe(errSecCSResourcesNotFound); CFRef fullpath = makeCFURL(path, false, resourceBase()); if (CFTypeRef file = CFDictionaryGetValue(files, CFTempString(path))) { - ResourceSeal seal = file; + ResourceSeal seal(file); + const ResourceSeal& rseal = seal; if (seal.nested()) { if (isSymlink) return ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type @@ -1146,16 +1253,17 @@ void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool is if (!isSymlink) return ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type validateSymlinkResource(cfString(fullpath), cfString(seal.link()), ctx, flags); - } else if (seal.hash()) { // genuine file + } else if (seal.hash(hashAlgorithm())) { // genuine file if (isSymlink) return ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // changed type AutoFileDesc fd(cfString(fullpath), O_RDONLY, FileDesc::modeMissingOk); // open optional file if (fd) { - MakeHash hasher(this->codeDirectory()); - hashFileData(fd, hasher.get()); - if (hasher->verify(seal.hash())) - return; // verify good - else + __block bool good = true; + CodeDirectory::multipleHashFileData(fd, 0, hashAlgorithms(), ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { + if (!hasher->verify(rseal.hash(type))) + good = false; + }); + if (!good) ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAltered, fullpath); // altered } else { if (!seal.optional()) @@ -1174,7 +1282,7 @@ void SecStaticCode::validateResource(CFDictionaryRef files, string path, bool is } ctx.reportProblem(errSecCSBadResource, kSecCFErrorResourceAdded, CFTempURL(path, false, resourceBase())); } - + void SecStaticCode::validateSymlinkResource(std::string fullpath, std::string seal, ValidationContext &ctx, SecCSFlags flags) { static const char* const allowedDestinations[] = { @@ -1239,7 +1347,7 @@ void SecStaticCode::validateNestedCode(CFURLRef path, const ResourceSeal &seal, flags |= kSecCSBasicValidateOnly; SecPointer code = new SecStaticCode(DiskRep::bestGuess(cfString(path))); code->initializeFromParent(*this); - code->staticValidate(flags, SecRequirement::required(req)); + code->staticValidate(flags & ~kSecCSRestrictToAppLike, SecRequirement::required(req)); if (isFramework && (flags & kSecCSStrictValidate)) try { @@ -1384,14 +1492,16 @@ const Requirement *SecStaticCode::defaultDesignatedRequirement() Requirement::Maker::Chain chain(maker, opOr); // insert cdhash requirement for all architectures - chain.add(); - maker.cdhash(this->cdHash()); - handleOtherArchitectures(^(SecStaticCode *subcode) { - if (CFDataRef cdhash = subcode->cdHash()) { - chain.add(); - maker.cdhash(cdhash); - } + __block CFRef allHashes = CFArrayCreateMutableCopy(NULL, 0, this->cdHashes()); + handleOtherArchitectures(^(SecStaticCode *other) { + CFArrayRef hashes = other->cdHashes(); + CFArrayAppendArray(allHashes, hashes, CFRangeMake(0, CFArrayGetCount(hashes))); }); + CFIndex count = CFArrayGetCount(allHashes); + for (CFIndex n = 0; n < count; ++n) { + chain.add(); + maker.cdhash(CFDataRef(CFArrayGetValueAtIndex(allHashes, n))); + } return maker.make(); } else { // full signature: Gin up full context and let DRMaker do its thing @@ -1529,8 +1639,11 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) CFDictionaryAddValue(dict, kSecCodeInfoFormat, CFTempString(this->format())); CFDictionaryAddValue(dict, kSecCodeInfoSource, CFTempString(this->signatureSource())); CFDictionaryAddValue(dict, kSecCodeInfoUnique, this->cdHash()); + CFDictionaryAddValue(dict, kSecCodeInfoCdHashes, this->cdHashes()); const CodeDirectory* cd = this->codeDirectory(false); CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithm, CFTempNumber(cd->hashType)); + CFRef digests = makeCFArrayFrom(^CFTypeRef(CodeDirectory::HashAlgorithm type) { return CFTempNumber(type); }, hashAlgorithms()); + CFDictionaryAddValue(dict, kSecCodeInfoDigestAlgorithms, digests); if (cd->platform) CFDictionaryAddValue(dict, kSecCodeInfoPlatformIdentifier, CFTempNumber(cd->platform)); @@ -1547,20 +1660,20 @@ CFDictionaryRef SecStaticCode::signingInformation(SecCSFlags flags) // if (flags & kSecCSSigningInformation) try { - if (CFArrayRef certs = this->certificates()) - CFDictionaryAddValue(dict, kSecCodeInfoCertificates, certs); if (CFDataRef sig = this->signature()) CFDictionaryAddValue(dict, kSecCodeInfoCMS, sig); + if (const char *teamID = this->teamID()) + CFDictionaryAddValue(dict, kSecCodeInfoTeamIdentifier, CFTempString(teamID)); if (mTrust) CFDictionaryAddValue(dict, kSecCodeInfoTrust, mTrust); + if (CFArrayRef certs = this->certificates()) + CFDictionaryAddValue(dict, kSecCodeInfoCertificates, certs); if (CFAbsoluteTime time = this->signingTime()) if (CFRef date = CFDateCreate(NULL, time)) CFDictionaryAddValue(dict, kSecCodeInfoTime, date); if (CFAbsoluteTime time = this->signingTimestamp()) if (CFRef date = CFDateCreate(NULL, time)) CFDictionaryAddValue(dict, kSecCodeInfoTimestamp, date); - if (const char *teamID = this->teamID()) - CFDictionaryAddValue(dict, kSecCodeInfoTeamIdentifier, CFTempString(teamID)); } catch (...) { } // @@ -1667,8 +1780,8 @@ void SecStaticCode::CollectingContext::throwMe() // // SecStaticCode exposes an a la carte menu of topical validators applying // to a given object. The static validation API pulls them together reliably, -// but it also adds two matrix dimensions: architecture (for "fat" Mach-O binaries) -// and nested code. This function will crawl a suitable cross-section of this +// but it also adds three matrix dimensions: architecture (for "fat" Mach-O binaries), +// nested code, and multiple digests. This function will crawl a suitable cross-section of this // validation matrix based on which options it is given, creating temporary // SecStaticCode objects on the fly to complete the task. // (The point, of course, is to do as little duplicate work as possible.) @@ -1692,7 +1805,7 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) if ((arch.cpuType() & ~CPU_ARCH_MASK) == CPU_TYPE_POWERPC) return; // irrelevant to Gatekeeper } - subcode->detachedSignature(this->mDetachedSig); // carry over explicit (but not implicit) architecture + subcode->detachedSignature(this->mDetachedSig); // carry over explicit (but not implicit) detached signature subcode->staticValidateCore(flags, req); }); reportProgress(); @@ -1706,7 +1819,7 @@ void SecStaticCode::staticValidate(SecCSFlags flags, const SecRequirement *req) // perform strict validation if desired if (flags & kSecCSStrictValidate) - mRep->strictValidate(codeDirectory(), mTolerateErrors); + mRep->strictValidate(codeDirectory(), mTolerateErrors, mValidationFlags); reportProgress(); // allow monitor intervention @@ -1722,6 +1835,7 @@ void SecStaticCode::staticValidateCore(SecCSFlags flags, const SecRequirement *r { try { this->validateNonResourceComponents(); // also validates the CodeDirectory + this->validateTopDirectory(); if (!(flags & kSecCSDoNotValidateExecutable)) this->validateExecutable(); if (req) diff --git a/OSX/libsecurity_codesigning/lib/StaticCode.h b/OSX/libsecurity_codesigning/lib/StaticCode.h index c74ae3e7..bb73341a 100644 --- a/OSX/libsecurity_codesigning/lib/StaticCode.h +++ b/OSX/libsecurity_codesigning/lib/StaticCode.h @@ -117,13 +117,16 @@ public: void detachedSignature(CFDataRef sig); // attach an explicitly given detached signature void checkForSystemSignature(); // check for and attach system-supplied detached signature - const CodeDirectory *codeDirectory(bool check = true); + const CodeDirectory *codeDirectory(bool check = true) const; + CodeDirectory::HashAlgorithm hashAlgorithm() const { return codeDirectory()->hashType; } + CodeDirectory::HashAlgorithms hashAlgorithms() const { return mHashAlgorithms; } CFDataRef cdHash(); + CFArrayRef cdHashes(); CFDataRef signature(); CFAbsoluteTime signingTime(); CFAbsoluteTime signingTimestamp(); bool isSigned() { return codeDirectory(false) != NULL; } - DiskRep *diskRep() { return mRep; } + DiskRep *diskRep() const { return mRep; } bool isDetached() const { return mRep->base() != mRep; } std::string mainExecutablePath() { return mRep->mainExecutablePath(); } CFURLRef copyCanonicalPath() const { return mRep->copyCanonicalPath(); } @@ -142,7 +145,7 @@ public: 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); - + bool flag(uint32_t tested); SecCodeCallback monitor() const { return mMonitor; } @@ -161,13 +164,14 @@ public: { assert(validated()); return mValidated && (mValidationResult == errSecSuccess); } bool validatedExecutable() const { return mExecutableValidated; } bool validatedResources() const { return mResourcesValidated; } - + void prepareProgress(unsigned workload); void cancelValidation(); void validateDirectory(); virtual void validateComponent(CodeDirectory::SpecialSlot slot, OSStatus fail = errSecCSSignatureFailed); void validateNonResourceComponents(); + void validateTopDirectory(); unsigned estimateResourceWorkload(); void validateResources(SecCSFlags flags); void validateExecutable(); @@ -195,6 +199,10 @@ public: void staticValidate(SecCSFlags flags, const SecRequirement *req); void staticValidateCore(SecCSFlags flags, const SecRequirement *req); +protected: + typedef std::map > CodeDirectoryMap; + bool loadCodeDirectories(CodeDirectoryMap& cdMap) const; + protected: CFDictionaryRef getDictionary(CodeDirectory::SpecialSlot slot, bool check = true); // component value as a dictionary bool verifySignature(); @@ -210,6 +218,8 @@ private: private: RefPointer mRep; // on-disk representation + mutable CodeDirectoryMap mCodeDirectories; // available CodeDirectory blobs by digest type + mutable CFRef mBaseDir; // the primary CodeDirectory blob (whether it's chosen or not) CFRef mDetachedSig; // currently applied explicit detached signature // private validation modifiers (only used by Gatekeeper checkfixes) @@ -243,9 +253,9 @@ private: const SecStaticCode *mOuterScope; // containing code (if this is a nested validation; weak) ResourceBuilder *mResourceScope; // current Resource validation stack (while validating; weak) - // cached contents - CFRef mDir; // code directory data + mutable CFRef mDir; // code directory data + mutable CodeDirectory::HashAlgorithms mHashAlgorithms; // available hash algorithms CFRef mSignature; // CMS signature data CFAbsoluteTime mSigningTime; // (signed) signing time CFAbsoluteTime mSigningTimestamp; // Timestamp time (from timestamping authority) @@ -256,7 +266,8 @@ private: CFRef mEntitlements; // derived from mCache slot CFRef mResourceDict; // derived from mCache slot const Requirement *mDesignatedReq; // cached designated req if we made one up - CFRef mCDHash; // hash of CodeDirectory + CFRef mCDHash; // hash of chosen CodeDirectory + CFRef mCDHashes; // hashes of all CodeDirectories (in digest type code order) bool mGotResourceBase; // asked mRep for resourceBasePath CFRef mResourceBase; // URL form of resource base directory diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp index cf3a41d8..571c33e1 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.cpp @@ -84,6 +84,8 @@ void BundleDiskRep::checkMoved(CFURLRef oldPath, CFURLRef newPath) void BundleDiskRep::setup(const Context *ctx) { 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); @@ -107,11 +109,13 @@ void BundleDiskRep::setup(const Context *ctx) } } else if (::access(supportFiles.c_str(), F_OK) == 0) { // ancient legacy boondoggle bundle // 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))) mBundle.take(versionBundle); // replace top bundle ref else MacOSError::throwMe(errSecCSStaticCodeNotFound); + appDisqualified = true; validateFrameworkRoot(root); } else { if (ctx && ctx->version) // explicitly specified @@ -143,7 +147,16 @@ void BundleDiskRep::setup(const Context *ctx) mExecRep = DiskRep::bestFileGuess(this->mainExecutablePath(), ctx); if (!mExecRep->fd().isPlainFile(this->mainExecutablePath())) recordStrictError(errSecCSRegularFile); + CFDictionaryRef infoDict = CFBundleGetInfoDictionary(mBundle); + bool isAppBundle = false; + if (infoDict) + if (CFTypeRef packageType = CFDictionaryGetValue(infoDict, CFSTR("CFBundlePackageType"))) + if (CFEqual(packageType, CFSTR("APPL"))) + isAppBundle = true; mFormat = "bundle with " + mExecRep->format(); + if (isAppBundle) + mFormat = "app " + mFormat; + mAppLike = isAppBundle && !appDisqualified; return; } @@ -159,6 +172,7 @@ void BundleDiskRep::setup(const Context *ctx) if (!mExecRep->fd().isPlainFile(this->mainExecutablePath())) recordStrictError(errSecCSRegularFile); mFormat = "widget bundle"; + mAppLike = true; return; } @@ -382,6 +396,11 @@ Universal *BundleDiskRep::mainExecutableImage() return mExecRep->mainExecutableImage(); } +void BundleDiskRep::prepareForSigning(SigningContext &context) +{ + return mExecRep->prepareForSigning(context); +} + size_t BundleDiskRep::signingBase() { return mExecRep->signingBase(); @@ -403,7 +422,11 @@ CFArrayRef BundleDiskRep::modifiedFiles() checkModifiedFile(files, cdCodeDirectorySlot); checkModifiedFile(files, cdSignatureSlot); checkModifiedFile(files, cdResourceDirSlot); + checkModifiedFile(files, cdTopDirectorySlot); checkModifiedFile(files, cdEntitlementSlot); + checkModifiedFile(files, cdRepSpecificSlot); + for (CodeDirectory::Slot slot = cdAlternateCodeDirectorySlots; slot < cdAlternateCodeDirectoryLimit; ++slot) + checkModifiedFile(files, slot); return files; } @@ -563,13 +586,21 @@ size_t BundleDiskRep::pageSize(const SigningContext &ctx) // Strict validation. // Takes an array of CFNumbers of errors to tolerate. // -void BundleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated) +void BundleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { std::vector fatalErrors; set_difference(mStrictErrors.begin(), mStrictErrors.end(), tolerated.begin(), tolerated.end(), back_inserter(fatalErrors)); if (!fatalErrors.empty()) MacOSError::throwMe(fatalErrors[0]); - mExecRep->strictValidate(cd, tolerated); + + // if app focus is requested and this doesn't look like an app, fail - but allow whitelist overrides + if (flags & kSecCSRestrictToAppLike) + if (!mAppLike) + if (tolerated.find(kSecCSRestrictToAppLike) == tolerated.end()) + MacOSError::throwMe(errSecCSNotAppLike); + + // now strict-check the main executable (which won't be an app-like object) + mExecRep->strictValidate(cd, tolerated, flags & ~kSecCSRestrictToAppLike); } void BundleDiskRep::recordStrictError(OSStatus error) diff --git a/OSX/libsecurity_codesigning/lib/bundlediskrep.h b/OSX/libsecurity_codesigning/lib/bundlediskrep.h index b1b4db4b..d0c5ee65 100644 --- a/OSX/libsecurity_codesigning/lib/bundlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/bundlediskrep.h @@ -61,6 +61,7 @@ public: std::string resourcesRelativePath(); void adjustResources(ResourceBuilder &builder); Universal *mainExecutableImage(); + void prepareForSigning(SigningContext &context); size_t signingBase(); size_t signingLimit(); std::string format(); @@ -73,7 +74,7 @@ public: const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); size_t pageSize(const SigningContext &ctx); - void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated); + void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); CFArrayRef allowedResourceOmissions(); CFBundleRef bundle() const { return mBundle; } @@ -102,6 +103,7 @@ private: bool mMetaExists; // separate meta-file directory exists CFRef mMainExecutableURL; // chosen main executable URL bool mInstallerPackage; // is an installer (not executable) bundle + bool mAppLike; // is some form of app string mFormat; // format description string RefPointer mExecRep; // DiskRep for main executable file std::set mStrictErrors; // strict validation errors encountered diff --git a/OSX/libsecurity_codesigning/lib/cdbuilder.cpp b/OSX/libsecurity_codesigning/lib/cdbuilder.cpp index 719a01b3..c4e75a2e 100644 --- a/OSX/libsecurity_codesigning/lib/cdbuilder.cpp +++ b/OSX/libsecurity_codesigning/lib/cdbuilder.cpp @@ -92,6 +92,7 @@ void CodeDirectory::Builder::specialSlot(SpecialSlot slot, CFDataRef data) MakeHash hash(this); hash->update(CFDataGetBytePtr(data), CFDataGetLength(data)); hash->finish(specialSlot(slot)); + mFilledSpecialSlots.insert(slot); if (slot >= mSpecialSlots) mSpecialSlots = slot; } @@ -109,14 +110,16 @@ CodeDirectory::Scatter *CodeDirectory::Builder::scatter(unsigned count) return mScatter; } -// This calculates the fixed size of the code directory -// Because of , if the team ID -// field is not used, we leave out the team ID offset -// as well, to keep cd hashes consistent between -// versions. +// +// Keep the allocated size of the (static) CodeDirectory consistent with +// the version chosen. We dynamically picked the least-needed version +// to provide stability of virtual signatures. +// const size_t CodeDirectory::Builder::fixedSize(const uint32_t version) { size_t cdSize = sizeof(CodeDirectory); + if (version < supportsCodeLimit64) + cdSize -= sizeof(mDir->spare3) + sizeof(mDir->codeLimit64); if (version < supportsTeamID) cdSize -= sizeof(mDir->teamIDOffset); @@ -179,26 +182,33 @@ CodeDirectory *CodeDirectory::Builder::build() size_t teamIDLength = mTeamID.size() + 1; // Determine the version - if (mTeamID.size()) { + if (mExecLength > UINT32_MAX) { version = currentVersion; + } else if (mTeamID.size()) { + version = supportsTeamID; } else { version = supportsScatter; } + if (mCodeSlots > UINT32_MAX) // (still limited to 32 bits) + MacOSError::throwMe(errSecCSTooBig); + size_t total = size(version); if (!(mDir = (CodeDirectory *)calloc(1, total))) // initialize to zero UnixError::throwMe(ENOMEM); - - if (mExecLength > UINT32_MAX) - MacOSError::throwMe(errSecCSTooBig); - + // fill header mDir->initialize(total); mDir->version = version; mDir->flags = mFlags; mDir->nSpecialSlots = (uint32_t)mSpecialSlots; mDir->nCodeSlots = (uint32_t)mCodeSlots; - mDir->codeLimit = (uint32_t)mExecLength; + if (mExecLength > UINT32_MAX) { + mDir->codeLimit = UINT32_MAX; + mDir->codeLimit64 = mExecLength; + } else { + mDir->codeLimit = uint32_t(mExecLength); + } mDir->hashType = mHashType; mDir->platform = mPlatform; mDir->hashSize = mDigestLength; @@ -244,11 +254,14 @@ CodeDirectory *CodeDirectory::Builder::build() mExec.seek(mExecOffset); size_t remaining = mExecLength; for (unsigned int slot = 0; slot < mCodeSlots; ++slot) { - size_t thisPage = min(mPageSize, remaining); + size_t thisPage = remaining; + if (mPageSize) + thisPage = min(thisPage, mPageSize); MakeHash hasher(this); generateHash(hasher, mExec, (*mDir)[slot], thisPage); remaining -= thisPage; } + assert(remaining == 0); // all done. Pass ownership to caller return mDir; diff --git a/OSX/libsecurity_codesigning/lib/cdbuilder.h b/OSX/libsecurity_codesigning/lib/cdbuilder.h index 21f92405..c4de2bec 100644 --- a/OSX/libsecurity_codesigning/lib/cdbuilder.h +++ b/OSX/libsecurity_codesigning/lib/cdbuilder.h @@ -41,7 +41,8 @@ namespace CodeSigning { // CodeDirectory *result = builder.build(); // Builder is not reusable. // -class CodeDirectory::Builder { +class CodeDirectory::Builder : public RefCount { + NOCOPY(Builder) public: Builder(HashAlgorithm digestAlgorithm); ~Builder(); @@ -54,6 +55,7 @@ public: void teamID(const std::string &team) { mTeamID = team; } void flags(uint32_t f) { mFlags = f; } void platform(uint8_t p) { mPlatform = p; } + std::set filledSpecialSlots() const { return mFilledSpecialSlots; } Scatter *scatter(unsigned count); // allocate that many scatter elements (w/o sentinel) Scatter *scatter() { return mScatter; } // return already allocated scatter vector @@ -72,6 +74,7 @@ private: private: Hashing::Byte *mSpecial; // array of special slot hashes + std::set mFilledSpecialSlots; // special slots filled with values UnixPlusPlus::AutoFileDesc mExec; // main executable file size_t mExecOffset; // starting offset in mExec size_t mExecLength; // total bytes of file to sign diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.cpp b/OSX/libsecurity_codesigning/lib/codedirectory.cpp index 7697e273..f675c4b8 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.cpp +++ b/OSX/libsecurity_codesigning/lib/codedirectory.cpp @@ -27,6 +27,7 @@ #include "codedirectory.h" #include "csutilities.h" #include "CSCommonPriv.h" +#include using namespace UnixPlusPlus; @@ -58,16 +59,28 @@ const char *CodeDirectory::canonicalSlotName(SpecialSlot slot) switch (slot) { case cdRequirementsSlot: return kSecCS_REQUIREMENTSFILE; + case cdAlternateCodeDirectorySlots: + return kSecCS_REQUIREMENTSFILE "-1"; + case cdAlternateCodeDirectorySlots+1: + return kSecCS_REQUIREMENTSFILE "-2"; + case cdAlternateCodeDirectorySlots+2: + return kSecCS_REQUIREMENTSFILE "-3"; + case cdAlternateCodeDirectorySlots+3: + return kSecCS_REQUIREMENTSFILE "-4"; + case cdAlternateCodeDirectorySlots+4: + return kSecCS_REQUIREMENTSFILE "-5"; case cdResourceDirSlot: return kSecCS_RESOURCEDIRFILE; case cdCodeDirectorySlot: return kSecCS_CODEDIRECTORYFILE; case cdSignatureSlot: return kSecCS_SIGNATUREFILE; - case cdApplicationSlot: - return kSecCS_APPLICATIONFILE; + case cdTopDirectorySlot: + return kSecCS_TOPDIRECTORYFILE; case cdEntitlementSlot: return kSecCS_ENTITLEMENTFILE; + case cdRepSpecificSlot: + return kSecCS_REPSPECIFICFILE; default: return NULL; } @@ -83,7 +96,12 @@ unsigned CodeDirectory::slotAttributes(SpecialSlot slot) case cdRequirementsSlot: return cdComponentIsBlob; // global case cdCodeDirectorySlot: - return cdComponentPerArchitecture | cdComponentIsBlob; + case cdAlternateCodeDirectorySlots: + case cdAlternateCodeDirectorySlots+1: + case cdAlternateCodeDirectorySlots+2: + case cdAlternateCodeDirectorySlots+3: + case cdAlternateCodeDirectorySlots+4: + return cdComponentPerArchitecture | cdComponentIsBlob; case cdSignatureSlot: return cdComponentPerArchitecture; // raw case cdEntitlementSlot: @@ -162,14 +180,15 @@ void CodeDirectory::checkIntegrity() const } // check consistency between the page-coverage fields + size_t limit = signingLimit(); if (pageSize) { - if (codeLimit == 0) // can't have paged signatures with no covered data + if (limit == 0) // can't have paged signatures with no covered data MacOSError::throwMe(errSecCSSignatureFailed); - size_t coveredPages = ((codeLimit-1) >> pageSize) + 1; // page slots required to cover codeLimit + size_t coveredPages = ((limit-1) >> pageSize) + 1; // page slots required to cover signingLimit if (coveredPages != nCodeSlots) MacOSError::throwMe(errSecCSSignatureFailed); } else { - if ((codeLimit > 0) != nCodeSlots) // must have one code slot, or none if no code + if ((limit > 0) != nCodeSlots) // must have one code slot, or none if no code MacOSError::throwMe(errSecCSSignatureFailed); } } @@ -229,6 +248,7 @@ DynamicHash *CodeDirectory::hashFor(HashAlgorithm hashType) switch (hashType) { case kSecCodeSignatureHashSHA1: return new CCHashInstance(kCCDigestSHA1); case kSecCodeSignatureHashSHA256: return new CCHashInstance(kCCDigestSHA256); + case kSecCodeSignatureHashSHA384: return new CCHashInstance(kCCDigestSHA384); case kSecCodeSignatureHashSHA256Truncated: return new CCHashInstance(kCCDigestSHA256, SHA1::digestLength); default: MacOSError::throwMe(errSecCSSignatureUnsupported); @@ -236,6 +256,61 @@ DynamicHash *CodeDirectory::hashFor(HashAlgorithm hashType) } +// +// Determine which of a set of possible digest types should be chosen as the "best" one +// +static const CodeDirectory::HashAlgorithm hashPriorities[] = { + kSecCodeSignatureHashSHA384, + kSecCodeSignatureHashSHA256, + kSecCodeSignatureHashSHA256Truncated, + kSecCodeSignatureHashSHA1, + kSecCodeSignatureNoHash // sentinel +}; + +bool CodeDirectory::viableHash(HashAlgorithm type) +{ + for (const HashAlgorithm* tp = hashPriorities; *tp != kSecCodeSignatureNoHash; tp++) + if (*tp == type) + return true; + return false; + +} + +CodeDirectory::HashAlgorithm CodeDirectory::bestHashOf(const HashAlgorithms &types) +{ + for (const HashAlgorithm* type = hashPriorities; *type != kSecCodeSignatureNoHash; type++) + if (types.find(*type) != types.end()) + return *type; + MacOSError::throwMe(errSecCSUnsupportedDigestAlgorithm); +} + + +// +// Hash a file range with multiple digest algorithms and then pass the resulting +// digests to a per-algorithm block. +// +void CodeDirectory::multipleHashFileData(FileDesc fd, size_t limit, CodeDirectory::HashAlgorithms types, void (^action)(HashAlgorithm type, DynamicHash* hasher)) +{ + assert(!types.empty()); + vector > hashers; + for (auto it = types.begin(); it != types.end(); ++it) { + if (CodeDirectory::viableHash(*it)) + hashers.push_back(CodeDirectory::hashFor(*it)); + } + scanFileData(fd, limit, ^(const void *buffer, size_t size) { + unsigned n = 0; + for (auto it = types.begin(); it != types.end(); ++it, ++n) { + hashers[n]->update(buffer, size); + } + }); + CFRef result = makeCFMutableDictionary(); + unsigned n = 0; + for (auto it = types.begin(); it != types.end(); ++it, ++n) { + action(*it, hashers[n]); + } +} + + // // Generate the canonical cdhash - the internal hash of the CodeDirectory itself. // We currently truncate to 20 bytes because that's what the kernel can deal with. @@ -297,6 +372,8 @@ std::string CodeDirectory::screeningCode() const { if (slotIsPresent(-cdInfoSlot)) // has Info.plist return "I" + hexHash((*this)[-cdInfoSlot]); // use Info.plist hash + if (slotIsPresent(-cdRepSpecificSlot)) // has Info.plist + return "R" + hexHash((*this)[-cdRepSpecificSlot]); // use Info.plist hash if (pageSize == 0) // good-enough proxy for "not a Mach-O file" return "M" + hexHash((*this)[0]); // use hash of main executable return "N"; // no suitable screening code diff --git a/OSX/libsecurity_codesigning/lib/codedirectory.h b/OSX/libsecurity_codesigning/lib/codedirectory.h index 9e074099..4b0bbbd9 100644 --- a/OSX/libsecurity_codesigning/lib/codedirectory.h +++ b/OSX/libsecurity_codesigning/lib/codedirectory.h @@ -47,6 +47,7 @@ #include #include #include +#include namespace Security { @@ -61,8 +62,9 @@ namespace CodeSigning { #define kSecCS_SIGNATUREFILE "CodeSignature" // CMS Signature #define kSecCS_REQUIREMENTSFILE "CodeRequirements" // internal requirements #define kSecCS_RESOURCEDIRFILE "CodeResources" // resource directory -#define kSecCS_APPLICATIONFILE "CodeApplication" // application-specific resource #define kSecCS_ENTITLEMENTFILE "CodeEntitlements" // entitlement configuration +#define kSecCS_REPSPECIFICFILE "CodeRepSpecific" // DiskRep-specific use slot +#define kSecCS_TOPDIRECTORYFILE "CodeTopDirectory" // Top-level directory list // @@ -88,8 +90,9 @@ enum { cdInfoSlot = 1, // Info.plist cdRequirementsSlot = 2, // internal requirements cdResourceDirSlot = 3, // resource directory - cdApplicationSlot = 4, // Application specific slot + cdTopDirectorySlot = 4, // Application specific slot cdEntitlementSlot = 5, // embedded entitlement configuration + cdRepSpecificSlot = 6, // for use by disk rep // (add further primary slot numbers here) cdSlotCount, // total number of special slots (+1 for slot 0) @@ -105,8 +108,10 @@ enum { // It's okay to have large gaps in these assignments. // cdCodeDirectorySlot = 0, // CodeDirectory + cdAlternateCodeDirectorySlots = 0x1000, // alternate CodeDirectory array + cdAlternateCodeDirectoryLimit = 0x1005, // 5+1 hashes should be enough for everyone... cdSignatureSlot = 0x10000, // CMS signature - cdIdentificationSlot, // identification blob + cdIdentificationSlot, // identification blob (detached signatures only) // (add further virtual slot numbers here) }; @@ -191,23 +196,30 @@ public: Endian spare2; // unused (must be zero) Endian scatterOffset; // offset of optional scatter vector (zero if absent) Endian teamIDOffset; // offset of optional teamID string + Endian spare3; // unused (most be zero) + Endian codeLimit64; // limit to main image signature range, 64 bits // works with the version field; see comments above - static const uint32_t currentVersion = 0x20200; // "version 2.2" + static const uint32_t currentVersion = 0x20300; // "version 2.3" static const uint32_t compatibilityLimit = 0x2F000; // "version 3 with wiggle room" static const uint32_t earliestVersion = 0x20001; // earliest supported version static const uint32_t supportsScatter = 0x20100; // first version to support scatter option - static const uint32_t supportsTeamID = 0x20200; // first version to support team ID option + static const uint32_t supportsTeamID = 0x20200; // first version to support team ID option + static const uint32_t supportsCodeLimit64 = 0x20300; // first version to support codeLimit64 void checkIntegrity() const; // throws if inconsistent or unsupported version typedef uint32_t HashAlgorithm; // types of internal glue hashes + typedef std::set HashAlgorithms; typedef int Slot; // slot index (negative for special slots) typedef unsigned int SpecialSlot; // positive special slot index (not for code slots) const char *identifier() const { return at(identOffset); } char *identifier() { return at(identOffset); } + + size_t signingLimit() const + { return (version >= supportsCodeLimit64 && codeLimit64) ? size_t(codeLimit64) : size_t(codeLimit); } // main hash array access SpecialSlot maxSpecialSlot() const; @@ -257,6 +269,11 @@ public: static DynamicHash *hashFor(HashAlgorithm hashType); // create a DynamicHash subclass for (hashType) digests DynamicHash *getHash() const { return hashFor(this->hashType); } // make one for me CFDataRef cdhash() const; + + static void multipleHashFileData(UnixPlusPlus::FileDesc fd, size_t limit, HashAlgorithms types, void (^action)(HashAlgorithm type, DynamicHash* hasher)); + + static bool viableHash(HashAlgorithm type); + static HashAlgorithm bestHashOf(const HashAlgorithms& types); std::string hexHash(const unsigned char *hash) const; // encode any canonical-type hash as a hex string diff --git a/OSX/libsecurity_codesigning/lib/csutilities.h b/OSX/libsecurity_codesigning/lib/csutilities.h index 1de14505..0cc63cb4 100644 --- a/OSX/libsecurity_codesigning/lib/csutilities.h +++ b/OSX/libsecurity_codesigning/lib/csutilities.h @@ -57,15 +57,8 @@ void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest dig void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest); bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest); - -// -// Calculate hashes of (a section of) a file. -// Starts at the current file position. -// Extends to end of file, or (if limit > 0) at most limit bytes. -// Returns number of bytes digested. -// -template -size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) + +inline size_t scanFileData(UnixPlusPlus::FileDesc fd, size_t limit, void (^handle)(const void *buffer, size_t size)) { unsigned char buffer[4096]; size_t total = 0; @@ -77,20 +70,35 @@ size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) total += got; if (fd.atEnd()) break; - hasher->update(buffer, got); + handle(buffer, got); if (limit && (limit -= got) == 0) break; } return total; } + +// +// Calculate hashes of (a section of) a file. +// Starts at the current file position. +// Extends to end of file, or (if limit > 0) at most limit bytes. +// Returns number of bytes digested. +// +template +size_t hashFileData(UnixPlusPlus::FileDesc fd, _Hash *hasher, size_t limit = 0) +{ + return scanFileData(fd, limit, ^(const void *buffer, size_t size) { + hasher->update(buffer, size); + }); +} + template size_t hashFileData(const char *path, _Hash *hasher) { UnixPlusPlus::AutoFileDesc fd(path); return hashFileData(fd, hasher); } - + // // Check to see if a certificate contains a particular field, by OID. This works for extensions, diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.cpp b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp new file mode 100644 index 00000000..7bc89b48 --- /dev/null +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.cpp @@ -0,0 +1,255 @@ +/* + * 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@ + */ + +// +// diskimagerep - DiskRep representing a single read-only compressed disk image file +// +#include "diskimagerep.h" +#include "sigblob.h" +#include "CodeSigner.h" +#include +#include + + +namespace Security { +namespace CodeSigning { + +using Security::n2h; +using Security::h2n; +using namespace UnixPlusPlus; + + +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 + static const size_t headerLength = sizeof(header); + size_t length = fd.fileSize(); + if (length < sizeof(UDIFFileHeader) + sizeof(BlobCore)) + return false; + size_t headerOffset = length - sizeof(UDIFFileHeader); + if (fd.read(&header, headerLength, headerOffset) != headerLength) + return false; + if (n2h(header.fUDIFSignature) != kUDIFSignature) + return false; + if (n2h(header.fUDIFVersion) != udifVersion) // current as of this writing + return false; + + return true; +} + + +// +// Object management. +// +DiskImageRep::DiskImageRep(const char *path) + : SingleDiskRep(path) +{ + this->setup(); +} + +void DiskImageRep::setup() +{ + mSigningData = NULL; + + // the UDIF "header" is in fact the last 512 bytes of the file, with no particular alignment + if (!readHeader(fd(), this->mHeader)) + 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) + if (signatureOffset == 0) { + mEndOfDataOffset = mHeaderOffset; + sigFields(mHeader).fCodeSignatureOffset = h2n(mHeaderOffset); + return; // unsigned, header prepared for possible signing + } else { + mEndOfDataOffset = signatureOffset; + } + + // 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) { + free(blob); + MacOSError::throwMe(errSecCSBadDiskImageFormat); + } + mSigningData = blob; + } +} + + +// +// The default binary identification of a SingleDiskRep is the (SHA-1) hash +// of the entire file itself. +// +CFDataRef DiskImageRep::identification() +{ + SHA1 hash; // not security sensitive + hash(&mHeader, sizeof(mHeader)); + SHA1::Digest digest; + hash.finish(digest); + return makeCFData(digest, sizeof(digest)); +} + + +// +// Sniffer function for UDIF disk image files. +// This just looks for the trailing "header" and its magic number. +// +bool DiskImageRep::candidate(FileDesc &fd) +{ + UDIFFileHeader header; + return readHeader(fd, header) == true; +} + + +// +// Signing limit is the start of the (trailing) signature +// +size_t DiskImageRep::signingLimit() +{ + return mEndOfDataOffset; +} + +void DiskImageRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) +{ + DiskRep::strictValidate(cd, tolerated, flags); + + if (cd) { + size_t cd_limit = cd->signingLimit(); + size_t dr_limit = signingLimit(); + if (cd_limit != dr_limit && // must cover exactly the entire data + cd_limit != fd().fileSize()) // or, for legacy detached sigs, the entire file + MacOSError::throwMe(errSecCSSignatureInvalid); + } +} + + +// +// Retrieve a component from the executable. +// Our mCache has mapped the entire file, so we just fish the contents out of +// the mapped area as needed. +// +CFDataRef DiskImageRep::component(CodeDirectory::SpecialSlot slot) +{ + switch (slot) { + case cdRepSpecificSlot: + return makeCFData(&mHeader, sizeof(mHeader)); + default: + return mSigningData ? mSigningData->component(slot) : NULL; + } +} + + +// +// Provide a (vaguely) human readable characterization of this code +// +string DiskImageRep::format() +{ + return "disk image"; +} + +void DiskImageRep::prepareForSigning(SigningContext& context) +{ + // default to SHA256 unconditionally - we have no legacy issues to worry about + if (context.digestAlgorithms().empty()) + context.setDigestAlgorithm(kSecCodeSignatureHashSHA256); +} + + +// +// DiskImageRep::Writers +// +DiskRep::Writer *DiskImageRep::writer() +{ + return new Writer(this); +} + + +// +// Write a component. +// +void DiskImageRep::Writer::component(CodeDirectory::SpecialSlot slot, CFDataRef data) +{ + assert(slot != cdRepSpecificSlot); + EmbeddedSignatureBlob::Maker::component(slot, data); +} + + +// +// Append the superblob we built to the cache file. +// +void DiskImageRep::Writer::flush() +{ + delete mSigningData; // ditch previous blob just in case + mSigningData = Maker::make(); // assemble new signature SuperBlob + + // write signature superblob + size_t location = rep->mEndOfDataOffset; + assert(location); + fd().seek(location); + fd().writeAll(*mSigningData); // write signature + + // now (re)write disk image header after it + UDIFFileHeader fullHeader = rep->mHeader; + sigFields(fullHeader).fCodeSignatureOffset = h2n(location); + sigFields(fullHeader).fCodeSignatureLength = h2n(mSigningData->length()); + fd().writeAll(&fullHeader, sizeof(rep->mHeader)); +} + + +// +// Discretionary manipulations +// +void DiskImageRep::Writer::addDiscretionary(CodeDirectory::Builder &builder) +{ +} + + +} // end namespace CodeSigning +} // end namespace Security diff --git a/OSX/libsecurity_codesigning/lib/diskimagerep.h b/OSX/libsecurity_codesigning/lib/diskimagerep.h new file mode 100644 index 00000000..96a63a2a --- /dev/null +++ b/OSX/libsecurity_codesigning/lib/diskimagerep.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 20015 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@ + */ + +// +// diskimagerep - DiskRep representing a single read-only compressed disk image file +// +#ifndef _H_DISKIMAGEREP +#define _H_DISKIMAGEREP + +#include "singlediskrep.h" +#include "sigblob.h" +#include +#undef check // sadness is having to live with C #defines of this kind... +#include + +namespace Security { +namespace CodeSigning { + + +// +// DiskImageRep implements a single read-only compressed disk image file. +// +class DiskImageRep : public SingleDiskRep { +public: + DiskImageRep(const char *path); + + CFDataRef identification(); + CFDataRef component(CodeDirectory::SpecialSlot slot); + size_t signingLimit(); + void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); + std::string format(); + void prepareForSigning(SigningContext& state); + + static bool candidate(UnixPlusPlus::FileDesc &fd); + +public: + static CFDataRef identificationFor(MachO *macho); + +public: + DiskRep::Writer *writer(); + class Writer; + friend class Writer; + +private: + void setup(); + static bool readHeader(UnixPlusPlus::FileDesc& fd, UDIFFileHeader& header); + +private: + UDIFFileHeader mHeader; // disk image header (all fields NBO) + size_t mEndOfDataOffset; // end of payload data (data fork + XML) + size_t mHeaderOffset; // trailing header offset + const EmbeddedSignatureBlob *mSigningData; // pointer to signature SuperBlob (in mapped memory) +}; + + +// +// The write side of a FileDiskRep +// +class DiskImageRep::Writer : public SingleDiskRep::Writer, private EmbeddedSignatureBlob::Maker { + friend class FileDiskRep; +public: + Writer(DiskImageRep *r) : SingleDiskRep::Writer(r, writerNoGlobal), rep(r), mSigningData(NULL) { } + void component(CodeDirectory::SpecialSlot slot, CFDataRef data); + void flush(); + void addDiscretionary(CodeDirectory::Builder &builder); + +private: + DiskImageRep *rep; + EmbeddedSignatureBlob *mSigningData; +}; + + +} // end namespace CodeSigning +} // end namespace Security + +#endif // !_H_DISKIMAGEREP diff --git a/OSX/libsecurity_codesigning/lib/diskrep.cpp b/OSX/libsecurity_codesigning/lib/diskrep.cpp index af0a336b..0501e377 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/diskrep.cpp @@ -32,6 +32,7 @@ #include "filediskrep.h" #include "bundlediskrep.h" #include "slcrep.h" +#include "diskimagerep.h" namespace Security { @@ -109,6 +110,8 @@ DiskRep *DiskRep::bestGuess(const char *path, const Context *ctx) AutoFileDesc fd(path, O_RDONLY); if (MachORep::candidate(fd)) return new MachORep(path, ctx); + if (DiskImageRep::candidate(fd)) + return new DiskImageRep(path); if (DYLDCacheRep::candidate(fd)) return new DYLDCacheRep(path); @@ -178,6 +181,11 @@ void DiskRep::adjustResources(ResourceBuilder &builder) { // do nothing } + +void DiskRep::prepareForSigning(SigningContext &state) +{ + // do nothing +} Universal *DiskRep::mainExecutableImage() { @@ -218,9 +226,11 @@ size_t DiskRep::pageSize(const SigningContext &) } -void DiskRep::strictValidate(const CodeDirectory*, const ToleratedErrors&) +void DiskRep::strictValidate(const CodeDirectory*, const ToleratedErrors& tolerated, SecCSFlags flags) { - // do nothing + if (flags & kSecCSRestrictToAppLike) + if (tolerated.find(errSecCSNotAppLike) == tolerated.end()) + MacOSError::throwMe(errSecCSNotAppLike); } CFArrayRef DiskRep::allowedResourceOmissions() diff --git a/OSX/libsecurity_codesigning/lib/diskrep.h b/OSX/libsecurity_codesigning/lib/diskrep.h index b9219521..21d2d5a8 100644 --- a/OSX/libsecurity_codesigning/lib/diskrep.h +++ b/OSX/libsecurity_codesigning/lib/diskrep.h @@ -41,6 +41,7 @@ namespace Security { namespace CodeSigning { class ResourceBuilder; +class SecCodeSigner; // @@ -65,6 +66,7 @@ public: virtual CFURLRef copyCanonicalPath() = 0; // path to whole code virtual std::string resourcesRootPath(); // resource directory if any [none] virtual void adjustResources(ResourceBuilder &builder); // adjust resource rule set [no change] + virtual void prepareForSigning(SigningContext& context); // pre-adjust signing defaults before argument preparation [none] virtual Universal *mainExecutableImage(); // Mach-O image if Mach-O based [null] virtual size_t signingBase(); // start offset of signed area in main executable [zero] virtual size_t signingLimit() = 0; // size of signed area in main executable @@ -80,13 +82,12 @@ public: const SigningContext &ctx); // default internal requirements [none] virtual size_t pageSize(const SigningContext &ctx); // default main executable page size [infinite, i.e. no paging] - virtual void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated); // perform strict validation + virtual void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); // perform strict validation virtual CFArrayRef allowedResourceOmissions(); // allowed (default) resource omission rules bool mainExecutableIsMachO() { return mainExecutableImage() != NULL; } // shorthands - CFDataRef codeDirectory() { return component(cdCodeDirectorySlot); } CFDataRef signature() { return component(cdSignatureSlot); } public: @@ -125,6 +126,16 @@ public: virtual std::string sdkPath(const std::string &path) const = 0; virtual bool isAdhoc() const = 0; virtual SecCSFlags signingFlags() const = 0; + + virtual const CodeDirectory::HashAlgorithms &digestAlgorithms() const = 0; + virtual void setDigestAlgorithms(CodeDirectory::HashAlgorithms types) = 0; + + void setDigestAlgorithm(CodeDirectory::HashAlgorithm type) + { + CodeDirectory::HashAlgorithms types; + types.insert(type); + setDigestAlgorithms(types); + } }; protected: @@ -166,8 +177,8 @@ public: bool attribute(uint32_t attr) const { return mAttributes & attr; } void signature(CFDataRef data) { component(cdSignatureSlot, data); } - void codeDirectory(const CodeDirectory *cd) - { component(cdCodeDirectorySlot, CFTempData(cd->data(), cd->length())); } + void codeDirectory(const CodeDirectory *cd, CodeDirectory::SpecialSlot slot) + { component(slot, CFTempData(cd->data(), cd->length())); } private: Architecture mArch; @@ -220,7 +231,7 @@ public: { return mOriginal->defaultRequirements(arch, ctx); } size_t pageSize(const SigningContext &ctx) { return mOriginal->pageSize(ctx); } - void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated) { mOriginal->strictValidate(cd, tolerated); } + void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { mOriginal->strictValidate(cd, tolerated, flags); } CFArrayRef allowedResourceOmissions() { return mOriginal->allowedResourceOmissions(); } private: diff --git a/OSX/libsecurity_codesigning/lib/machorep.cpp b/OSX/libsecurity_codesigning/lib/machorep.cpp index d362b5ab..de4b43a4 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.cpp +++ b/OSX/libsecurity_codesigning/lib/machorep.cpp @@ -97,6 +97,50 @@ Universal *MachORep::mainExecutableImage() return mExecutable; } + +// +// Explicitly default to SHA256 (only) digests if the minimum deployment +// target is young enough. +// +void MachORep::prepareForSigning(SigningContext &context) +{ + if (context.digestAlgorithms().empty()) { + MachO *macho = mainExecutableImage()->architecture(); + if (const version_min_command *version = macho->findMinVersion()) { + uint32_t limit = 0; + switch (macho->flip(version->cmd)) { + case LC_VERSION_MIN_MACOSX: + limit = (10 << 16 | 11 << 8 | 4 << 0); + break; +#if 0 /* need updated libMIS before we can do this switch */ + case LC_VERSION_MIN_IPHONEOS: + limit = (9 << 16 | 3 << 8); + break; + case LC_VERSION_MIN_WATCHOS: + limit = (2 << 16 | 2 << 8); + break; + case LC_VERSION_MIN_TVOS: + limit = (9 << 16 | 2 << 8); + break; + default: + break; +#else + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_WATCHOS: + case LC_VERSION_MIN_TVOS: + return; + default: + break; +#endif + } + if (macho->flip(version->version) >= limit) { + // young enough not to need SHA-1 legacy support + context.setDigestAlgorithm(kSecCodeSignatureHashSHA256); + } + } + } +} + // // Signing base is the start of the Mach-O architecture we're using @@ -368,8 +412,10 @@ size_t MachORep::pageSize(const SigningContext &) // // Strict validation // -void MachORep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated) +void MachORep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { + DiskRep::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); @@ -377,7 +423,7 @@ void MachORep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& to // 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->codeLimit != macho->signingExtent()) + if (cd->signingLimit() != macho->signingExtent()) MacOSError::throwMe(errSecCSSignatureInvalid); } } diff --git a/OSX/libsecurity_codesigning/lib/machorep.h b/OSX/libsecurity_codesigning/lib/machorep.h index 07bba9e4..214efb6a 100644 --- a/OSX/libsecurity_codesigning/lib/machorep.h +++ b/OSX/libsecurity_codesigning/lib/machorep.h @@ -53,6 +53,7 @@ public: CFDataRef component(CodeDirectory::SpecialSlot slot); CFDataRef identification(); Universal *mainExecutableImage(); + void prepareForSigning(SigningContext &context); size_t signingBase(); std::string format(); @@ -60,7 +61,7 @@ public: const Requirements *defaultRequirements(const Architecture *arch, const SigningContext &ctx); size_t pageSize(const SigningContext &ctx); - void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated); + void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); void flush(); // flush cache diff --git a/OSX/libsecurity_codesigning/lib/opaquewhitelist.cpp b/OSX/libsecurity_codesigning/lib/opaquewhitelist.cpp index 7fbde5fc..483ca40c 100644 --- a/OSX/libsecurity_codesigning/lib/opaquewhitelist.cpp +++ b/OSX/libsecurity_codesigning/lib/opaquewhitelist.cpp @@ -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@ * @@ -107,20 +107,22 @@ bool OpaqueWhitelist::contains(SecStaticCodeRef codeRef, SecAssessmentFeedback f opaque = code->cdHash(); // lookup current cdhash in whitelist - SQLite::Statement lookup(*this, "SELECT opaque FROM whitelist WHERE current=:current" - " AND opaque != 'disable override'"); - lookup.bind(":current") = current.get(); - while (lookup.nextRow()) { - CFRef expected = lookup[0].data(); - if (CFEqual(opaque, expected)) { - match = true; // actual opaque cdhash matches expected - break; + if (opaque) { + SQLite::Statement lookup(*this, "SELECT opaque FROM whitelist WHERE current=:current" + " AND opaque != 'disable override'"); + lookup.bind(":current") = current.get(); + while (lookup.nextRow()) { + CFRef expected = lookup[0].data(); + if (CFEqual(opaque, expected)) { + match = true; // actual opaque cdhash matches expected + break; + } } } // prepare strings for use inside block std::string currentHash = hashString(current); - std::string opaqueHash = hashString(opaque); + std::string opaqueHash = opaque ? hashString(opaque) : "none"; // send a trace indicating the result MessageTrace trace("com.apple.security.assessment.whitelist2", code->identifier().c_str()); @@ -224,6 +226,7 @@ void OpaqueWhitelist::add(SecStaticCodeRef codeRef) // // Generate and attach an ad-hoc opaque signature +// Use SHA-1 digests because that's what the whitelist is made with // static void attachOpaque(SecStaticCodeRef code, SecAssessmentFeedback feedback) { @@ -240,9 +243,10 @@ static void attachOpaque(SecStaticCodeRef code, SecAssessmentFeedback feedback) "}"); CFRef signature = CFDataCreateMutable(NULL, 0); - CFTemp arguments("{%O=%O, %O=#N, %O=%O}", + CFTemp arguments("{%O=%O, %O=#N, %O=%d, %O=%O}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity, /* kCFNull, */ + kSecCodeSignerDigestAlgorithm, kSecCodeSignatureHashSHA1, kSecCodeSignerResourceRules, rules.get()); CFRef signer; SecCSFlags creationFlags = kSecCSSignOpaque | kSecCSSignNoV1 | kSecCSSignBundleRoot; diff --git a/OSX/libsecurity_codesigning/lib/policydb.h b/OSX/libsecurity_codesigning/lib/policydb.h index b26c7e6c..65dded83 100644 --- a/OSX/libsecurity_codesigning/lib/policydb.h +++ b/OSX/libsecurity_codesigning/lib/policydb.h @@ -82,6 +82,7 @@ enum { kAuthorityFlagInhibitCache = 0x0004, // never cache outcome of this rule kAuthorityFlagWhitelist = 0x1000, // whitelist override kAuthorityFlagWhitelistV2 = 0x2000, // apply "deep" signature to this record + kAuthorityFlagWhitelistSHA256 = 0x4000, // use SHA256 signature }; diff --git a/OSX/libsecurity_codesigning/lib/policyengine.cpp b/OSX/libsecurity_codesigning/lib/policyengine.cpp index 08239439..cba2bdc4 100644 --- a/OSX/libsecurity_codesigning/lib/policyengine.cpp +++ b/OSX/libsecurity_codesigning/lib/policyengine.cpp @@ -100,12 +100,11 @@ void PolicyEngine::evaluate(CFURLRef path, AuthorityType type, SecAssessmentFlag } -static std::string createWhitelistScreen(char type, SHA1 &hash) +static std::string createWhitelistScreen(char type, const Byte *digest, size_t length) { - SHA1::Digest digest; - hash.finish(digest); - char buffer[2*SHA1::digestLength + 2] = { type }; - for (size_t n = 0; n < SHA1::digestLength; n++) + char buffer[2*length + 2]; + buffer[0] = type; + for (size_t n = 0; n < length; n++) sprintf(buffer + 1 + 2*n, "%02.2x", digest[n]); return buffer; } @@ -235,13 +234,24 @@ bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, C if (CFRef info = rep->component(cdInfoSlot)) { SHA1 hash; hash.update(CFDataGetBytePtr(info), CFDataGetLength(info)); - screen = createWhitelistScreen('I', hash); + 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); - screen = createWhitelistScreen('M', hash); + SHA1::Digest digest; + hash.finish(digest); + screen = createWhitelistScreen('M', digest, sizeof(digest)); } SQLite::Statement query(*this, "SELECT flags FROM authority " @@ -260,7 +270,8 @@ bool PolicyEngine::temporarySigning(SecStaticCodeRef code, AuthorityType type, C try { // ad-hoc sign the code and attach the signature CFRef signature = CFDataCreateMutable(NULL, 0); - CFTemp arguments("{%O=%O, %O=#N}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity); + CFTemp arguments("{%O=%O, %O=#N, %O=%d}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity, + kSecCodeSignerDigestAlgorithm, (matchFlags & kAuthorityFlagWhitelistSHA256) ? kSecCodeSignatureHashSHA256 : kSecCodeSignatureHashSHA1); CFRef signer; MacOSError::check(SecCodeSignerCreate(arguments, (matchFlags & kAuthorityFlagWhitelistV2) ? kSecCSSignOpaque : kSecCSSignV1, &signer.aref())); MacOSError::check(SecCodeSignerAddSignature(signer, code, kSecCSDefaultFlags)); @@ -365,7 +376,10 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment })); // go for it! - switch (rc = SecStaticCodeCheckValidity(code, validationFlags | kSecCSCheckNestedCode | kSecCSRestrictSymlinks | kSecCSReportProgress, NULL)) { + SecCSFlags topFlags = validationFlags | kSecCSCheckNestedCode | kSecCSRestrictSymlinks | kSecCSReportProgress; + if (type == kAuthorityExecute) + topFlags |= kSecCSRestrictToAppLike; + switch (rc = SecStaticCodeCheckValidity(code, topFlags, NULL)) { case errSecSuccess: // continue below break; case errSecCSUnsigned: @@ -385,6 +399,7 @@ void PolicyEngine::evaluateCode(CFURLRef path, AuthorityType type, SecAssessment case errSecCSUnsealedAppRoot: case errSecCSUnsealedFrameworkRoot: case errSecCSInvalidSymlink: + case errSecCSNotAppLike: { // consult the whitelist bool allow = false; @@ -604,7 +619,7 @@ void PolicyEngine::evaluateDocOpen(CFURLRef path, SecAssessmentFlags flags, CFDi addAuthority(flags, result, "Prior Assessment"); } else if (!overrideAssessment(flags)) { // no need to do more work if we're off try { - evaluateCode(path, kAuthorityExecute, flags, context, result, false); + evaluateCode(path, kAuthorityOpenDoc, flags, context, result, true); } catch (...) { // some documents can't be code signed, so this may be quite benign } @@ -715,7 +730,7 @@ CFDictionaryRef PolicyEngine::add(CFTypeRef inTarget, AuthorityType type, SecAss bool allow = true; double expires = never; string remarks; - SQLite::uint64 dbFlags = kAuthorityFlagWhitelistV2; + SQLite::uint64 dbFlags = kAuthorityFlagWhitelistV2 | kAuthorityFlagWhitelistSHA256; if (CFNumberRef pri = ctx.get(kSecAssessmentUpdateKeyPriority)) CFNumberGetValue(pri, kCFNumberDoubleType, &priority); @@ -1036,7 +1051,7 @@ void PolicyEngine::normalizeTarget(CFRef &target, AuthorityType type, } break; case errSecCSUnsigned: - if (signUnsigned && temporarySigning(code, type, path, kAuthorityFlagWhitelistV2)) { // ad-hoc signed the code temporarily + 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())); diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.cpp b/OSX/libsecurity_codesigning/lib/reqinterp.cpp index effd233e..3837d426 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.cpp +++ b/OSX/libsecurity_codesigning/lib/reqinterp.cpp @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #include "csutilities.h" namespace Security { @@ -303,23 +306,91 @@ bool Requirement::Interpreter::certFieldPolicy(const CssmOid &oid, const Match & bool Requirement::Interpreter::appleAnchored() { if (SecCertificateRef cert = mContext->cert(anchorCert)) - if (isAppleCA(cert) -#if defined(TEST_APPLE_ANCHOR) - || verifyAnchor(cert, testAppleAnchorHash()) -#endif - ) + if (isAppleCA(cert)) return true; return false; } +static CFStringRef kAMFINVRAMTrustedKeys = CFSTR("AMFITrustedKeys"); + +CFArrayRef Requirement::Interpreter::getAdditionalTrustedAnchors() +{ + __block CFRef keys = makeCFMutableArray(0); + + try { + io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options"); + if (entry == IO_OBJECT_NULL) + return NULL; + + CFRef configData = (CFDataRef)IORegistryEntryCreateCFProperty(entry, kAMFINVRAMTrustedKeys, kCFAllocatorDefault, 0); + IOObjectRelease(entry); + if (!configData) + return NULL; + + CFRef configDict = CFDictionaryRef(IOCFUnserialize((const char *)CFDataGetBytePtr(configData), kCFAllocatorDefault, 0, NULL)); + if (!configDict) + return NULL; + + CFArrayRef trustedKeys = CFArrayRef(CFDictionaryGetValue(configDict, CFSTR("trustedKeys"))); + if (!trustedKeys && CFGetTypeID(trustedKeys) != CFArrayGetTypeID()) + return NULL; + + cfArrayApplyBlock(trustedKeys, ^(const void *value) { + CFDictionaryRef key = CFDictionaryRef(value); + if (!key && CFGetTypeID(key) != CFDictionaryGetTypeID()) + return; + + CFDataRef hash = CFDataRef(CFDictionaryGetValue(key, CFSTR("certDigest"))); + if (!hash && CFGetTypeID(hash) != CFDataGetTypeID()) + return; + CFArrayAppendValue(keys, hash); + }); + + } catch (...) { + } + + if (CFArrayGetCount(keys) == 0) + return NULL; + + return keys.yield(); +} + +bool Requirement::Interpreter::appleLocalAnchored() +{ + static CFArrayRef additionalTrustedCertificates = NULL; + + if (csr_check(CSR_ALLOW_APPLE_INTERNAL)) + return false; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + additionalTrustedCertificates = getAdditionalTrustedAnchors(); + }); + + if (additionalTrustedCertificates == NULL) + return false; + + CFRef hash = SecCertificateCopySHA256Digest(mContext->cert(leafCert)); + if (!hash) + return false; + + if (CFArrayContainsValue(additionalTrustedCertificates, CFRangeMake(0, CFArrayGetCount(additionalTrustedCertificates)), hash)) + return true; + + return false; +} + bool Requirement::Interpreter::appleSigned() { - if (appleAnchored()) + if (appleAnchored()) { if (SecCertificateRef intermed = mContext->cert(-2)) // first intermediate // first intermediate common name match (exact) if (certFieldValue("subject.CN", Match(appleIntermediateCN, matchEqual), intermed) && certFieldValue("subject.O", Match(appleIntermediateO, matchEqual), intermed)) return true; + } else if (appleLocalAnchored()) { + return true; + } return false; } diff --git a/OSX/libsecurity_codesigning/lib/reqinterp.h b/OSX/libsecurity_codesigning/lib/reqinterp.h index a221f96d..fd0188d3 100644 --- a/OSX/libsecurity_codesigning/lib/reqinterp.h +++ b/OSX/libsecurity_codesigning/lib/reqinterp.h @@ -76,12 +76,15 @@ protected: bool verifyAnchor(SecCertificateRef cert, const unsigned char *digest); bool appleSigned(); bool appleAnchored(); + bool trustedCerts(); bool trustedCert(int slot); static SecTrustSettingsResult trustSetting(SecCertificateRef cert, bool isAnchor); private: + CFArrayRef getAdditionalTrustedAnchors(); + bool appleLocalAnchored(); const Context * const mContext; }; diff --git a/OSX/libsecurity_codesigning/lib/resources.cpp b/OSX/libsecurity_codesigning/lib/resources.cpp index 5695800e..490b1e07 100644 --- a/OSX/libsecurity_codesigning/lib/resources.cpp +++ b/OSX/libsecurity_codesigning/lib/resources.cpp @@ -61,9 +61,8 @@ static string removeTrailingSlash(string path) // Construction and maintainance // ResourceBuilder::ResourceBuilder(const std::string &root, const std::string &relBase, - CFDictionaryRef rulesDict, CodeDirectory::HashAlgorithm hashType, bool strict, const MacOSErrorSet& toleratedErrors) - : mHashType(hashType), - mCheckUnreadable(strict && toleratedErrors.find(errSecCSSignatureNotVerifiable) == toleratedErrors.end()), + CFDictionaryRef rulesDict, bool strict, const MacOSErrorSet& toleratedErrors) + : mCheckUnreadable(strict && toleratedErrors.find(errSecCSSignatureNotVerifiable) == toleratedErrors.end()), mCheckUnknownType(strict && toleratedErrors.find(errSecCSResourceNotSupported) == toleratedErrors.end()) { assert(!root.empty()); @@ -274,11 +273,11 @@ ResourceBuilder::Rule *ResourceBuilder::findRule(string path) const // // Hash a file and return a CFDataRef with the hash // -CFDataRef ResourceBuilder::hashFile(const char *path) const +CFDataRef ResourceBuilder::hashFile(const char *path, CodeDirectory::HashAlgorithm type) { UnixPlusPlus::AutoFileDesc fd(path); fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) - MakeHash hasher(this); + RefPointer hasher(CodeDirectory::hashFor(type)); hashFileData(fd, hasher.get()); Hashing::Byte digest[hasher->digestLength()]; hasher->finish(digest); @@ -286,6 +285,38 @@ CFDataRef ResourceBuilder::hashFile(const char *path) const } +// +// 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) +{ + UnixPlusPlus::AutoFileDesc fd(path); + fd.fcntl(F_NOCACHE, true); // turn off page caching (one-pass) + CFRef result = makeCFMutableDictionary(); + CFMutableDictionaryRef resultRef = result; + CodeDirectory::multipleHashFileData(fd, 0, types, ^(CodeDirectory::HashAlgorithm type, Security::DynamicHash *hasher) { + size_t length = hasher->digestLength(); + Hashing::Byte digest[length]; + hasher->finish(digest); + CFDictionaryAddValue(resultRef, CFTempString(hashName(type)), CFTempData(digest, length)); + }); + return result.yield(); +} + + +std::string ResourceBuilder::hashName(CodeDirectory::HashAlgorithm type) +{ + switch (type) { + case kSecCodeSignatureHashSHA1: + return "hash"; + default: + char name[20]; + snprintf(name, sizeof(name), "hash%d", int(type)); + return name; + } +} + + // // Regex matching objects // @@ -333,29 +364,41 @@ std::string ResourceBuilder::escapeRE(const std::string &s) // Resource Seals // ResourceSeal::ResourceSeal(CFTypeRef it) - : mDict(NULL), mHash(NULL), mRequirement(NULL), mLink(NULL), mFlags(0) + : mDict(NULL), mRequirement(NULL), mLink(NULL), mFlags(0) { if (it == NULL) MacOSError::throwMe(errSecCSResourcesInvalid); - if (CFGetTypeID(it) == CFDataGetTypeID()) { - mHash = CFDataRef(it); - } else { - int optional = 0; + if (CFGetTypeID(it) == CFDataGetTypeID()) // old-style form with just a hash + mDict.take(cfmake("{hash=%O}", it)); + else if (CFGetTypeID(it) == CFDictionaryGetTypeID()) mDict = CFDictionaryRef(it); - bool err; - if (CFDictionaryGetValue(mDict, CFSTR("requirement"))) - err = !cfscan(mDict, "{requirement=%SO,?optional=%B}", &mRequirement, &optional); - else if (CFDictionaryGetValue(mDict, CFSTR("symlink"))) - err = !cfscan(mDict, "{symlink=%SO,?optional=%B}", &mLink, &optional); - else - err = !cfscan(mDict, "{hash=%XO,?optional=%B}", &mHash, &optional); - if (err) - MacOSError::throwMe(errSecCSResourcesInvalid); - if (optional) - mFlags |= ResourceBuilder::optional; - if (mRequirement) - mFlags |= ResourceBuilder::nested; - } + else + MacOSError::throwMe(errSecCSResourcesInvalid); + + int optional = 0; + bool err; + if (CFDictionaryGetValue(mDict, CFSTR("requirement"))) + err = !cfscan(mDict, "{requirement=%SO,?optional=%B}", &mRequirement, &optional); + else if (CFDictionaryGetValue(mDict, CFSTR("symlink"))) + err = !cfscan(mDict, "{symlink=%SO,?optional=%B}", &mLink, &optional); + else + err = !cfscan(mDict, "{?optional=%B}", &optional); + if (err) + MacOSError::throwMe(errSecCSResourcesInvalid); + if (optional) + mFlags |= ResourceBuilder::optional; + if (mRequirement) + mFlags |= ResourceBuilder::nested; +} + + +const Hashing::Byte *ResourceSeal::hash(CodeDirectory::HashAlgorithm type) const +{ + std::string name = ResourceBuilder::hashName(type); + CFTypeRef hash = CFDictionaryGetValue(mDict, CFTempString(name)); + if (hash == NULL || CFGetTypeID(hash) != CFDataGetTypeID()) + MacOSError::throwMe(errSecCSResourcesInvalid); + return CFDataGetBytePtr(CFDataRef(hash)); } diff --git a/OSX/libsecurity_codesigning/lib/resources.h b/OSX/libsecurity_codesigning/lib/resources.h index 4bdcc7e6..8d68314b 100644 --- a/OSX/libsecurity_codesigning/lib/resources.h +++ b/OSX/libsecurity_codesigning/lib/resources.h @@ -50,7 +50,7 @@ class ResourceBuilder { NOCOPY(ResourceBuilder) public: ResourceBuilder(const std::string &root, const std::string &relBase, - CFDictionaryRef rulesDict, CodeDirectory::HashAlgorithm hashType, bool strict, const MacOSErrorSet& toleratedErrors); + CFDictionaryRef rulesDict, bool strict, const MacOSErrorSet& toleratedErrors); ~ResourceBuilder(); std::string root() const { return mRoot; } @@ -87,8 +87,10 @@ public: bool includes(string path) const; Rule *findRule(string path) const; - DynamicHash *getHash() const { return CodeDirectory::hashFor(this->mHashType); } - CFDataRef hashFile(const char *path) const; + static CFDataRef hashFile(const char *path, CodeDirectory::HashAlgorithm type); + static CFMutableDictionaryRef hashFile(const char *path, CodeDirectory::HashAlgorithms types); + + static std::string hashName(CodeDirectory::HashAlgorithm type); CFDictionaryRef rules() const { return mRawRules; } @@ -101,7 +103,6 @@ private: CFCopyRef mRawRules; typedef std::vector Rules; Rules mRules; - CodeDirectory::HashAlgorithm mHashType; bool mCheckUnreadable; bool mCheckUnknownType; }; @@ -111,14 +112,12 @@ private: // The "seal" on a single resource. // class ResourceSeal { + NOCOPY(ResourceSeal) public: ResourceSeal(CFTypeRef ref); public: - operator bool () const { return mHash; } - bool operator ! () const { return mHash == NULL; } - - const Hashing::Byte *hash() const { return CFDataGetBytePtr(mHash); } + const Hashing::Byte *hash(CodeDirectory::HashAlgorithm type) const; bool nested() const { return mFlags & ResourceBuilder::nested; } bool optional() const { return mFlags & ResourceBuilder::optional; } CFDictionaryRef dict() const { return mDict; } @@ -126,8 +125,7 @@ public: CFStringRef link() const { return mLink; } private: - CFDictionaryRef mDict; - CFDataRef mHash; + CFRef mDict; CFStringRef mRequirement; CFStringRef mLink; uint32_t mFlags; diff --git a/OSX/libsecurity_codesigning/lib/security_codesigning.exp b/OSX/libsecurity_codesigning/lib/security_codesigning.exp index 7a907d31..160559fa 100644 --- a/OSX/libsecurity_codesigning/lib/security_codesigning.exp +++ b/OSX/libsecurity_codesigning/lib/security_codesigning.exp @@ -97,6 +97,7 @@ _kSecCodeInfoEntitlementsDict _kSecCodeInfoFlags _kSecCodeInfoFormat _kSecCodeInfoDigestAlgorithm +_kSecCodeInfoDigestAlgorithms _kSecCodeInfoIdentifier _kSecCodeInfoImplicitDesignatedRequirement _kSecCodeInfoMainExecutable @@ -107,6 +108,7 @@ _kSecCodeInfoSource _kSecCodeInfoStatus _kSecCodeInfoTrust _kSecCodeInfoUnique +_kSecCodeInfoCdHashes _kSecCodeInfoCodeDirectory _kSecCodeInfoCodeOffset _kSecCodeInfoResourceDirectory diff --git a/OSX/libsecurity_codesigning/lib/signer.cpp b/OSX/libsecurity_codesigning/lib/signer.cpp index daa2dac7..387f68b5 100644 --- a/OSX/libsecurity_codesigning/lib/signer.cpp +++ b/OSX/libsecurity_codesigning/lib/signer.cpp @@ -58,10 +58,22 @@ void SecCodeSigner::Signer::sign(SecCSFlags flags) PreSigningContext context(*this); + considerTeamID(context); + + if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) { + signMachO(fat, context); + } else { + signArchitectureAgnostic(context); + } +} + + +void SecCodeSigner::Signer::considerTeamID(const PreSigningContext& context) +{ /* If an explicit teamID was passed in it must be the same as what came from the cert */ std::string teamIDFromCert = state.getTeamIDFromSigner(context.certs); - + if (state.mPreserveMetadata & kSecCodeSignerPreserveTeamIdentifier) { /* If preserving the team identifier, teamID is set previously when the code object is still available */ @@ -81,14 +93,8 @@ void SecCodeSigner::Signer::sign(SecCSFlags flags) MacOSError::throwMe(errSecCSInvalidFlags); } } - - if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) { - signMachO(fat, context); - } else { - signArchitectureAgnostic(context); - } } - + // // Remove any existing code signature from code @@ -102,7 +108,7 @@ void SecCodeSigner::Signer::remove(SecCSFlags flags) rep = code->diskRep(); if (Universal *fat = state.mNoMachO ? NULL : rep->mainExecutableImage()) { // architecture-sensitive removal - MachOEditor editor(rep->writer(), *fat, kSecCodeSignatureNoHash, rep->mainExecutablePath()); + MachOEditor editor(rep->writer(), *fat, digestAlgorithms(), rep->mainExecutablePath()); editor.allocate(); // create copy editor.commit(); // commit change } else { @@ -121,7 +127,7 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) { // make sure the rep passes strict validation if (strict) - rep->strictValidate(NULL, MacOSErrorSet()); + rep->strictValidate(NULL, MacOSErrorSet(), flags); // initialize progress/cancellation state code->prepareProgress(0); // totally fake workload - we don't know how many files we'll encounter @@ -138,10 +144,10 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) if (identifier.empty() && (inherit & kSecCodeSignerPreserveIdentifier)) identifier = code->identifier(); if (identifier.empty()) { - identifier = rep->recommendedIdentifier(state); + identifier = rep->recommendedIdentifier(*this); if (identifier.find('.') == string::npos) identifier = state.mIdentifierPrefix + identifier; - if (identifier.find('.') == string::npos && state.isAdhoc()) + if (identifier.find('.') == string::npos && isAdhoc()) identifier = identifier + "-" + uniqueName(); secdebug("signer", "using default identifier=%s", identifier.c_str()); } else @@ -154,6 +160,11 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) teamID = c_id; } + // Digest algorithms: explicit or preserved. Subject to diskRep defaults or final default later. + hashAlgorithms = state.mDigestAlgorithms; + if (hashAlgorithms.empty() && (inherit & kSecCodeSignerPreserveDigestAlgorithm)) + hashAlgorithms = code->hashAlgorithms(); + entitlements = state.mEntitlementData; if (!entitlements && (inherit & kSecCodeSignerPreserveEntitlements)) entitlements = code->component(cdEntitlementSlot); @@ -211,9 +222,11 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) // prepare the resource directory, if any string rpath = rep->resourcesRootPath(); + string rrpath; + CFCopyRef resourceRules; if (!rpath.empty()) { // explicitly given resource rules always win - CFCopyRef resourceRules = state.mResourceRules; + resourceRules = state.mResourceRules; // inherited rules come next (overriding embedded ones!) if (!resourceRules && (inherit & kSecCodeSignerPreserveResourceRules)) @@ -240,16 +253,13 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) // finally, ask the DiskRep for its default if (!resourceRules) - resourceRules.take(rep->defaultResourceRules(state)); + resourceRules.take(rep->defaultResourceRules(*this)); // resource root can optionally be the canonical bundle path, // but sealed resource paths are always relative to rpath - string root = rpath; - if (state.signingFlags() & kSecCSSignBundleRoot) - root = cfStringRelease(rep->copyCanonicalPath()); - - // build the resource directory - buildResources(root, rpath, resourceRules); + rrpath = rpath; + if (signingFlags() & kSecCSSignBundleRoot) + rrpath = cfStringRelease(rep->copyCanonicalPath()); } // screen and set the signing time @@ -265,10 +275,21 @@ void SecCodeSigner::Signer::prepare(SecCSFlags flags) signingTime = time; } - pagesize = state.mPageSize ? cfNumber(state.mPageSize) : rep->pageSize(state); - - // Timestamping setup - CFRef mTSAuth; // identity for client-side authentication to the Timestamp server + pagesize = state.mPageSize ? cfNumber(state.mPageSize) : rep->pageSize(*this); + + // Allow the DiskRep to modify the signing parameters. This sees explicit and inherited values but not defaults. + rep->prepareForSigning(*this); + + // apply some defaults after diskRep intervention + if (hashAlgorithms.empty()) { // default to SHA256 + SHA-1 + hashAlgorithms.insert(kSecCodeSignatureHashSHA1); + hashAlgorithms.insert(kSecCodeSignatureHashSHA256); + } + + // build the resource directory (once and for all, using the digests determined above) + if (!rpath.empty()) { + buildResources(rrpath, rpath, resourceRules); + } } @@ -295,7 +316,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase } CFDictionaryRef files2 = NULL; - if (!(state.signingFlags() & kSecCSSignV1)) { + if (!(signingFlags() & kSecCSSignV1)) { CFCopyRef rules2 = cfget(rulesDict, "rules2"); if (!rules2) { // Clone V1 rules and add default nesting rules at weight 0 (overridden by anything in rules). @@ -311,7 +332,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase // build the modern (V2) resource seal __block CFRef files = makeCFMutableDictionary(); CFMutableDictionaryRef filesRef = files.get(); // (into block) - ResourceBuilder resourceBuilder(root, relBase, rules2, digestAlgorithm(), strict, MacOSErrorSet()); + ResourceBuilder resourceBuilder(root, relBase, rules2, strict, MacOSErrorSet()); ResourceBuilder &resources = resourceBuilder; // (into block) rep->adjustResources(resources); @@ -331,8 +352,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase target[len] = '\0'; seal.take(cfmake("{symlink=%s}", target)); } else { - seal.take(cfmake("{hash=%O}", - CFRef(resources.hashFile(accpath.c_str())).get())); + seal.take(resources.hashFile(accpath.c_str(), digestAlgorithms())); } if (ruleFlags & ResourceBuilder::optional) CFDictionaryAddValue(seal, CFSTR("optional"), kCFBooleanTrue); @@ -352,10 +372,10 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase } CFDictionaryAddValue(result, CFSTR("rules"), rules); // preserve V1 rules in any case - if (!(state.signingFlags() & kSecCSSignNoV1)) { + if (!(signingFlags() & kSecCSSignNoV1)) { // build the legacy (V1) resource seal __block CFRef files = makeCFMutableDictionary(); - ResourceBuilder resourceBuilder(root, relBase, rules, digestAlgorithm(), strict, MacOSErrorSet()); + ResourceBuilder resourceBuilder(root, relBase, rules, strict, MacOSErrorSet()); ResourceBuilder &resources = resourceBuilder; rep->adjustResources(resources); // DiskRep-specific adjustments resources.scan(^(FTSENT *ent, uint32_t ruleFlags, std::string relpath, Rule *rule) { @@ -369,7 +389,7 @@ void SecCodeSigner::Signer::buildResources(std::string root, std::string relBase hash = CFDataRef(CFDictionaryGetValue(CFDictionaryRef(seal), CFSTR("hash"))); } if (!hash) - hash.take(resources.hashFile(ent->fts_accpath)); + 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); @@ -396,8 +416,8 @@ CFMutableDictionaryRef SecCodeSigner::Signer::signNested(const std::string &path // sign nested code and collect nesting information try { SecPointer code = new SecStaticCode(DiskRep::bestGuess(path)); - if (state.signingFlags() & kSecCSSignNestedCode) - this->state.sign(code, state.signingFlags()); + 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(), @@ -419,7 +439,7 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context // Mach-O executable at the core - perform multi-architecture signing auto_ptr editor(state.mDetached ? static_cast(new BlobEditor(*fat, *this)) - : new MachOEditor(rep->writer(), *fat, this->digestAlgorithm(), rep->mainExecutablePath())); + : new MachOEditor(rep->writer(), *fat, this->digestAlgorithms(), rep->mainExecutablePath())); assert(editor->count() > 0); if (!editor->attribute(writerNoGlobal)) // can store architecture-common components populate(*editor); @@ -436,11 +456,15 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context } } - arch.ireqs(requirements, rep->defaultRequirements(&arch.architecture, state), context); + arch.ireqs(requirements, rep->defaultRequirements(&arch.architecture, *this), context); if (editor->attribute(writerNoGlobal)) // can't store globally, add per-arch populate(arch); - populate(arch.cdbuilder, arch, arch.ireqs, - arch.source->offset(), arch.source->signingExtent()); + for (auto type = digestAlgorithms().begin(); type != digestAlgorithms().end(); ++type) { + arch.eachDigest(^(CodeDirectory::Builder& builder) { + populate(builder, arch, arch.ireqs, + arch.source->offset(), arch.source->signingExtent(), unsigned(digestAlgorithms().size()-1)); + }); + } // add identification blob (made from this architecture) only if we're making a detached signature if (state.mDetached) { @@ -450,8 +474,11 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context } // prepare SuperBlob size estimate - size_t cdSize = arch.cdbuilder.size(CodeDirectory::currentVersion); - arch.blobSize = arch.size(cdSize, state.mCMSSize, 0); + __block std::vector sizes; + arch.eachDigest(^(CodeDirectory::Builder& builder){ + sizes.push_back(builder.size(CodeDirectory::currentVersion)); + }); + arch.blobSize = arch.size(sizes, state.mCMSSize, 0); } editor->allocate(); @@ -461,12 +488,19 @@ void SecCodeSigner::Signer::signMachO(Universal *fat, const Requirement::Context MachOEditor::Arch &arch = *it->second; editor->reset(arch); - // finish CodeDirectory (off new binary) and sign it - CodeDirectory *cd = arch.cdbuilder.build(); - CFRef signature = signCodeDirectory(cd); + // finish CodeDirectories (off new binary) and sign it + __block CodeDirectorySet cdSet; + arch.eachDigest(^(CodeDirectory::Builder &builder) { + CodeDirectory *cd = builder.build(); + cdSet.add(cd); + }); + CFRef hashes = cdSet.hashBag(); + CFTemp hashDict("{cdhashes=%O}", hashes.get()); + CFRef hashBag = makeCFData(hashDict.get()); + CFRef signature = signCodeDirectory(cdSet.primary(), hashBag); // complete the SuperBlob - arch.add(cdCodeDirectorySlot, cd); // takes ownership + cdSet.populate(&arch); arch.add(cdSignatureSlot, BlobWrapper::alloc( CFDataGetBytePtr(signature), CFDataGetLength(signature))); if (!state.mDryRun) { @@ -490,26 +524,35 @@ void SecCodeSigner::Signer::signArchitectureAgnostic(const Requirement::Context // non-Mach-O executable - single-instance signing RefPointer writer = state.mDetached ? (new DetachedBlobWriter(*this)) : rep->writer(); - CodeDirectory::Builder builder(state.mDigestAlgorithm); - InternalRequirements ireqs; - ireqs(requirements, rep->defaultRequirements(NULL, state), context); - populate(*writer); - populate(builder, *writer, ireqs, rep->signingBase(), rep->signingLimit()); + + CodeDirectorySet cdSet; + for (auto type = digestAlgorithms().begin(); type != digestAlgorithms().end(); ++type) { + CodeDirectory::Builder builder(*type); + InternalRequirements ireqs; + ireqs(requirements, rep->defaultRequirements(NULL, *this), context); + populate(*writer); + populate(builder, *writer, ireqs, rep->signingBase(), rep->signingLimit(), unsigned(digestAlgorithms().size()-1)); + + CodeDirectory *cd = builder.build(); + if (!state.mDryRun) + cdSet.add(cd); + } // add identification blob (made from this architecture) only if we're making a detached signature if (state.mDetached) { CFRef identification = rep->identification(); writer->component(cdIdentificationSlot, identification); - } - - CodeDirectory *cd = builder.build(); - CFRef signature = signCodeDirectory(cd); - if (!state.mDryRun) { - writer->codeDirectory(cd); - writer->signature(signature); - writer->flush(); } - ::free(cd); + + // write out all CodeDirectories + cdSet.populate(writer); + writer->flush(); + + CFRef hashes = cdSet.hashBag(); + CFTemp hashDict("{cdhashes=%O}", hashes.get()); + CFRef hashBag = makeCFData(hashDict.get()); + CFRef signature = signCodeDirectory(cdSet.primary(), hashBag); + writer->signature(signature); } @@ -530,7 +573,7 @@ void SecCodeSigner::Signer::populate(DiskRep::Writer &writer) // for the purposes of this call. // void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer, - InternalRequirements &ireqs, size_t offset /* = 0 */, size_t length /* = 0 */) + InternalRequirements &ireqs, size_t offset, size_t length, unsigned alternateDigestCount) { // fill the CodeDirectory builder.executable(rep->mainExecutablePath(), pagesize, offset, length); @@ -548,24 +591,39 @@ void SecCodeSigner::Signer::populate(CodeDirectory::Builder &builder, DiskRep::W } if (resourceDirectory) builder.specialSlot(cdResourceDirSlot, resourceDictData); -#if NOT_YET - if (state.mApplicationData) - builder.specialSlot(cdApplicationSlot, state.mApplicationData); -#endif if (entitlements) { writer.component(cdEntitlementSlot, entitlements); builder.specialSlot(cdEntitlementSlot, entitlements); } + if (CFRef repSpecific = rep->component(cdRepSpecificSlot)) + builder.specialSlot(cdRepSpecificSlot, repSpecific); writer.addDiscretionary(builder); + + if ((signingFlags() & (kSecCSSignOpaque|kSecCSSignV1)) == 0) { + // calculate sorted list of top SuperBlob keys in this EmbeddedSignatureBlob (if any) + // (but not for opaque or V1 construction, which must remain bit-for-bit compatible) + std::vector > slotVector; + slotVector.push_back(cdCodeDirectorySlot); // mandatory + std::set filledSlots = builder.filledSpecialSlots(); + filledSlots.insert(cdTopDirectorySlot); // will be added below + copy(filledSlots.begin(), filledSlots.end(), back_inserter(slotVector)); + for (unsigned n = 0; n < alternateDigestCount; n++) + slotVector.push_back(cdAlternateCodeDirectorySlots + n); + slotVector.push_back(cdSignatureSlot); + CFTempData cfSlotVector(&slotVector[0], slotVector.size() * sizeof(slotVector[0])); + writer.component(cdTopDirectorySlot, cfSlotVector); + builder.specialSlot(cdTopDirectorySlot, cfSlotVector); + } } + #include // // Generate the CMS signature for a (finished) CodeDirectory. // -CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd) +CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd, CFDataRef hashBag) { assert(state.mSigner); CFRef defaultTSContext = NULL; @@ -587,10 +645,14 @@ CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd) MacOSError::check(CMSEncoderSetSigningTime(cms, signingTime)); } + if (hashBag) { + MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrAppleCodesigningHashAgility)); + MacOSError::check(CMSEncoderSetAppleCodesigningHashAgility(cms, hashBag)); + } + MacOSError::check(CMSEncoderUpdateContent(cms, cd, cd->length())); // Set up to call Timestamp server if requested - if (state.mWantTimeStamp) { CFRef error = NULL; @@ -603,16 +665,40 @@ CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd) CFDictionarySetValue(defaultTSContext, kTSAContextKeyURL, state.mTimestampService); if (state.mNoTimeStampCerts) CFDictionarySetValue(defaultTSContext, kTSAContextKeyNoCerts, kCFBooleanTrue); - } + } - CmsMessageSetTSAContext(cms, defaultTSContext); + CmsMessageSetTSAContext(cms, defaultTSContext); } - + CFDataRef signature; MacOSError::check(CMSEncoderCopyEncodedContent(cms, &signature)); return signature; } + + +// +// Our DiskRep::signingContext methods communicate with the signing subsystem +// in terms those callers can easily understand. +// +string SecCodeSigner::Signer::sdkPath(const std::string &path) const +{ + assert(path[0] == '/'); // need absolute path here + if (state.mSDKRoot) + return cfString(state.mSDKRoot) + path; + else + return path; +} + +bool SecCodeSigner::Signer::isAdhoc() const +{ + return state.mSigner == SecIdentityRef(kCFNull); +} + +SecCSFlags SecCodeSigner::Signer::signingFlags() const +{ + return state.mOpFlags; +} // diff --git a/OSX/libsecurity_codesigning/lib/signer.h b/OSX/libsecurity_codesigning/lib/signer.h index 3902d5bb..fafa3fe3 100644 --- a/OSX/libsecurity_codesigning/lib/signer.h +++ b/OSX/libsecurity_codesigning/lib/signer.h @@ -43,10 +43,10 @@ namespace CodeSigning { // signing stages to cooperate. It is not meant to be API visible; that is // SecCodeSigner's job. // -class SecCodeSigner::Signer { +class SecCodeSigner::Signer : public DiskRep::SigningContext { public: Signer(SecCodeSigner &s, SecStaticCode *c) : state(s), code(c), requirements(NULL) - { strict = state.signingFlags() & kSecCSSignStrictPreflight; } + { strict = signingFlags() & kSecCSSignStrictPreflight; } ~Signer() { ::free((Requirements *)requirements); } void sign(SecCSFlags flags); @@ -55,7 +55,8 @@ public: SecCodeSigner &state; SecStaticCode * const code; - CodeDirectory::HashAlgorithm digestAlgorithm() const { return state.mDigestAlgorithm; } + const CodeDirectory::HashAlgorithms& digestAlgorithms() const { return hashAlgorithms; } + void setDigestAlgorithms(CodeDirectory::HashAlgorithms types) { hashAlgorithms = types; } std::string path() const { return cfStringRelease(rep->copyCanonicalPath()); } SecIdentityRef signingIdentity() const { return state.mSigner; } @@ -68,21 +69,32 @@ protected: void populate(DiskRep::Writer &writer); // global void populate(CodeDirectory::Builder &builder, DiskRep::Writer &writer, - InternalRequirements &ireqs, size_t offset = 0, size_t length = 0); // per-architecture - CFDataRef signCodeDirectory(const CodeDirectory *cd); + InternalRequirements &ireqs, size_t offset, size_t length, unsigned alternateDigestCount); // per-architecture + CFDataRef signCodeDirectory(const CodeDirectory *cd, CFDataRef hashBag); uint32_t cdTextFlags(std::string text); // convert text CodeDirectory flags std::string uniqueName() const; // derive unique string from rep + +protected: + std::string sdkPath(const std::string &path) const; + bool isAdhoc() const; + SecCSFlags signingFlags() const; + +private: + void considerTeamID(const PreSigningContext& context); + std::vector > topSlots(CodeDirectory::Builder &builder) const; protected: void buildResources(std::string root, std::string relBase, CFDictionaryRef rules); CFMutableDictionaryRef signNested(const std::string &path, const std::string &relpath); - CFDataRef hashFile(const char *path); - + CFDataRef hashFile(const char *path, CodeDirectory::HashAlgorithm type); + CFDictionaryRef hashFile(const char *path, CodeDirectory::HashAlgorithms types); + private: RefPointer rep; // DiskRep of Code being signed CFRef resourceDirectory; // resource directory CFRef resourceDictData; // XML form of resourceDirectory + CodeDirectory::HashAlgorithms hashAlgorithms; // hash algorithm(s) to use std::string identifier; // signing identifier std::string teamID; // team identifier CFRef entitlements; // entitlements diff --git a/OSX/libsecurity_codesigning/lib/signerutils.cpp b/OSX/libsecurity_codesigning/lib/signerutils.cpp index eb19d2d3..25a327ba 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.cpp +++ b/OSX/libsecurity_codesigning/lib/signerutils.cpp @@ -76,14 +76,14 @@ void DetachedBlobWriter::flush() // // ArchEditor // -ArchEditor::ArchEditor(Universal &code, CodeDirectory::HashAlgorithm hashType, uint32_t attrs) +ArchEditor::ArchEditor(Universal &code, CodeDirectory::HashAlgorithms hashTypes, uint32_t attrs) : DiskRep::Writer(attrs) { Universal::Architectures archList; code.architectures(archList); for (Universal::Architectures::const_iterator it = archList.begin(); it != archList.end(); ++it) - architecture[*it] = new Arch(*it, hashType); + architecture[*it] = new Arch(*it, hashTypes); } @@ -92,13 +92,21 @@ ArchEditor::~ArchEditor() for (ArchMap::iterator it = begin(); it != end(); ++it) delete it->second; } + + +ArchEditor::Arch::Arch(const Architecture &arch, CodeDirectory::HashAlgorithms hashTypes) + : architecture(arch) +{ + for (auto type = hashTypes.begin(); type != hashTypes.end(); ++type) + cdBuilders.insert(make_pair(*type, new CodeDirectory::Builder(*type))); +} // // BlobEditor // BlobEditor::BlobEditor(Universal &fat, SecCodeSigner::Signer &s) - : ArchEditor(fat, s.digestAlgorithm(), 0), signer(s) + : ArchEditor(fat, s.digestAlgorithms(), 0), signer(s) { } @@ -130,11 +138,12 @@ void BlobEditor::commit() // "drill up" the Mach-O binary for insertion of Code Signing signature data. // After the tool succeeds, we open the new file and are ready to write it. // -MachOEditor::MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath) - : ArchEditor(code, hashType, w->attributes()), +MachOEditor::MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithms hashTypes, std::string srcPath) + : ArchEditor(code, hashTypes, w->attributes()), writer(w), sourcePath(srcPath), tempPath(srcPath + ".cstemp"), + mHashTypes(hashTypes), mNewCode(NULL), mTempMayExist(false) { @@ -242,8 +251,12 @@ void MachOEditor::childAction() void MachOEditor::reset(Arch &arch) { arch.source.reset(mNewCode->architecture(arch.architecture)); - arch.cdbuilder.reopen(tempPath, - arch.source->offset(), arch.source->signingOffset()); + + for (auto type = mHashTypes.begin(); type != mHashTypes.end(); ++type) { + arch.eachDigest(^(CodeDirectory::Builder& builder) { + builder.reopen(tempPath, arch.source->offset(), arch.source->signingOffset()); + }); + } } @@ -355,6 +368,62 @@ PreSigningContext::PreSigningContext(const SecCodeSigner::Signer &signer) // other stuff this->identifier = signer.signingIdentifier(); } + + +// +// A collector of CodeDirectories for hash-agile construction of signatures. +// +CodeDirectorySet::~CodeDirectorySet() +{ + for (auto it = begin(); it != end(); ++it) + ::free(const_cast(it->second)); +} + + +void CodeDirectorySet::add(const Security::CodeSigning::CodeDirectory *cd) +{ + insert(make_pair(cd->hashType, cd)); + if (cd->hashType == kSecCodeSignatureHashSHA1) + mPrimary = cd; +} + + +void CodeDirectorySet::populate(DiskRep::Writer *writer) const +{ + assert(!empty()); + + if (mPrimary == NULL) // didn't add SHA-1; pick another occupant for this slot + mPrimary = begin()->second; + + // reserve slot zero for a SHA-1 digest if present; else pick something else + CodeDirectory::SpecialSlot nextAlternate = cdAlternateCodeDirectorySlots; + for (auto it = begin(); it != end(); ++it) { + if (it->second == mPrimary) { + writer->codeDirectory(it->second, cdCodeDirectorySlot); + } else { + writer->codeDirectory(it->second, nextAlternate++); + } + } +} + + +const CodeDirectory* CodeDirectorySet::primary() const +{ + if (mPrimary == NULL) + mPrimary = begin()->second; + return mPrimary; +} + + +CFArrayRef CodeDirectorySet::hashBag() const +{ + CFRef hashList = makeCFMutableArray(0); + for (auto it = begin(); it != end(); ++it) { + CFRef cdhash = it->second->cdhash(); + CFArrayAppendValue(hashList, cdhash); + } + return hashList.yield(); +} } // end namespace CodeSigning diff --git a/OSX/libsecurity_codesigning/lib/signerutils.h b/OSX/libsecurity_codesigning/lib/signerutils.h index 906be1ea..88cb2055 100644 --- a/OSX/libsecurity_codesigning/lib/signerutils.h +++ b/OSX/libsecurity_codesigning/lib/signerutils.h @@ -81,7 +81,7 @@ public: // class ArchEditor : public DiskRep::Writer { public: - ArchEditor(Universal &fat, CodeDirectory::HashAlgorithm hashType, uint32_t attrs); + ArchEditor(Universal &fat, CodeDirectory::HashAlgorithms hashTypes, uint32_t attrs); virtual ~ArchEditor(); public: @@ -93,12 +93,17 @@ public: struct Arch : public BlobWriter { Architecture architecture; // our architecture auto_ptr source; // Mach-O object to be signed - CodeDirectory::Builder cdbuilder; // builder for CodeDirectory + std::map > cdBuilders; InternalRequirements ireqs; // consolidated internal requirements size_t blobSize; // calculated SuperBlob size - Arch(const Architecture &arch, CodeDirectory::HashAlgorithm hashType) - : architecture(arch), cdbuilder(hashType) { } + Arch(const Architecture &arch, CodeDirectory::HashAlgorithms hashTypes); + + void eachDigest(void (^op)(CodeDirectory::Builder& builder)) + { + for (auto type = cdBuilders.begin(); type != cdBuilders.end(); ++type) + op(*type->second); + } }; // @@ -151,7 +156,7 @@ private: // class MachOEditor : public ArchEditor, private UnixPlusPlus::Child { public: - MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithm hashType, std::string srcPath); + MachOEditor(DiskRep::Writer *w, Universal &code, CodeDirectory::HashAlgorithms hashTypes, std::string srcPath); ~MachOEditor(); const RefPointer writer; @@ -165,6 +170,8 @@ public: void commit(); private: + CodeDirectory::HashAlgorithms mHashTypes; + // fork operation void childAction(); void parentAction(); @@ -193,6 +200,25 @@ public: private: CFRef mCerts; // hold cert chain }; + + +// +// A collector of CodeDirectories for hash-agile construction of signatures. +// +class CodeDirectorySet : public std::map { +public: + CodeDirectorySet() { mPrimary = NULL; } + ~CodeDirectorySet(); + + void add(const CodeDirectory* cd); + void populate(DiskRep::Writer* writer) const; + + const CodeDirectory* primary() const; + CFArrayRef hashBag() const; + +private: + mutable const CodeDirectory* mPrimary; +}; } // end namespace CodeSigning diff --git a/OSX/libsecurity_codesigning/lib/singlediskrep.cpp b/OSX/libsecurity_codesigning/lib/singlediskrep.cpp index 5b01b138..84c5a781 100644 --- a/OSX/libsecurity_codesigning/lib/singlediskrep.cpp +++ b/OSX/libsecurity_codesigning/lib/singlediskrep.cpp @@ -115,10 +115,12 @@ string SingleDiskRep::recommendedIdentifier(const SigningContext &) // // Paranoid validation // -void SingleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated) +void SingleDiskRep::strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags) { + DiskRep::strictValidate(cd, tolerated, flags); + // code limit must cover (exactly) the entire file - if (cd && cd->codeLimit != signingLimit()) + if (cd && cd->signingLimit() != signingLimit()) MacOSError::throwMe(errSecCSSignatureInvalid); } diff --git a/OSX/libsecurity_codesigning/lib/singlediskrep.h b/OSX/libsecurity_codesigning/lib/singlediskrep.h index 1992dc16..cc15854c 100644 --- a/OSX/libsecurity_codesigning/lib/singlediskrep.h +++ b/OSX/libsecurity_codesigning/lib/singlediskrep.h @@ -49,13 +49,13 @@ public: CFDataRef identification(); // partial file hash std::string mainExecutablePath(); // base path CFURLRef copyCanonicalPath(); // base path - size_t signingLimit(); // size of file + virtual size_t signingLimit(); // size of file UnixPlusPlus::FileDesc &fd(); // readable fd for this file void flush(); // close cached fd std::string recommendedIdentifier(const SigningContext &ctx); // basename(path) - void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated); + void strictValidate(const CodeDirectory* cd, const ToleratedErrors& tolerated, SecCSFlags flags); public: class Writer; diff --git a/OSX/libsecurity_codesigning/lib/xpcengine.cpp b/OSX/libsecurity_codesigning/lib/xpcengine.cpp index 2da4e67f..6e415298 100644 --- a/OSX/libsecurity_codesigning/lib/xpcengine.cpp +++ b/OSX/libsecurity_codesigning/lib/xpcengine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 Apple Inc. All Rights Reserved. + * Copyright (c) 2011-2016 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -120,9 +120,26 @@ static void copyCFDictionary(const void *key, const void *value, void *ctx) CFDictionaryAddValue(target, key, value); } } + + +static void 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())); + 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)); + } +} + void xpcEngineAssess(CFURLRef path, SecAssessmentFlags flags, CFDictionaryRef context, CFMutableDictionaryRef result) { + precheckAccess(path, context); Message msg("assess"); xpc_dictionary_set_string(msg, "path", cfString(path).c_str()); xpc_dictionary_set_int64(msg, "flags", flags); @@ -171,9 +188,10 @@ CFDictionaryRef xpcEngineUpdate(CFTypeRef target, SecAssessmentFlags flags, CFDi if (target) { if (CFGetTypeID(target) == CFNumberGetTypeID()) xpc_dictionary_set_uint64(msg, "rule", cfNumber(CFNumberRef(target))); - else if (CFGetTypeID(target) == CFURLGetTypeID()) + else if (CFGetTypeID(target) == CFURLGetTypeID()) { + precheckAccess(CFURLRef(target), context); xpc_dictionary_set_string(msg, "url", cfString(CFURLRef(target)).c_str()); - else if (CFGetTypeID(target) == SecRequirementGetTypeID()) { + } else if (CFGetTypeID(target) == SecRequirementGetTypeID()) { CFRef data; MacOSError::check(SecRequirementCopyData(SecRequirementRef(target), kSecCSDefaultFlags, &data.aref())); xpc_dictionary_set_data(msg, "requirement", CFDataGetBytePtr(data), CFDataGetLength(data)); diff --git a/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj b/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj index deba680e..edb3cacb 100644 --- a/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj @@ -134,6 +134,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 = (); }; }; 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 */; }; @@ -452,6 +454,8 @@ C2CC310E0B852424005FA59D /* SecIntegrityLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecIntegrityLib.c; sourceTree = ""; }; C2CC31130B85254F005FA59D /* antlrplugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = antlrplugin.cpp; path = lib/antlrplugin.cpp; sourceTree = ""; }; C2CC31140B85254F005FA59D /* antlrplugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = antlrplugin.h; path = lib/antlrplugin.h; sourceTree = ""; }; + C2D296781BCF16C000B0A29B /* diskimagerep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = diskimagerep.cpp; sourceTree = ""; }; + C2D296791BCF16C000B0A29B /* diskimagerep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = diskimagerep.h; sourceTree = ""; }; C2D383120A237F47005C63A2 /* bundlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bundlediskrep.cpp; sourceTree = ""; }; C2D383130A237F47005C63A2 /* bundlediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bundlediskrep.h; sourceTree = ""; }; C2D383140A237F47005C63A2 /* cdbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cdbuilder.cpp; sourceTree = ""; }; @@ -861,6 +865,8 @@ C2BD519A0A9392FD000FE43D /* machorep.cpp */, C2A436140F2133B2007A41A6 /* slcrep.h */, C2A436130F2133B2007A41A6 /* slcrep.cpp */, + C2D296791BCF16C000B0A29B /* diskimagerep.h */, + C2D296781BCF16C000B0A29B /* diskimagerep.cpp */, C2C3BCD20BA1E47E00E869D1 /* singlediskrep.h */, C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */, C28342EC0E36719D00E54360 /* detachedrep.h */, @@ -1170,6 +1176,7 @@ 18B965891472FC5B005A4D2E /* reqreader.h in Headers */, 18B9658A1472FC5B005A4D2E /* reqinterp.h in Headers */, 18B9658B1472FC5B005A4D2E /* reqparser.h in Headers */, + C2D2967B1BCF16C000B0A29B /* diskimagerep.h in Headers */, 18B9658C1472FC9E005A4D2E /* codedirectory.h in Headers */, 18B965951472FE30005A4D2E /* cdbuilder.h in Headers */, EB68B133150DB04400B4013D /* RequirementKeywords.h in Headers */, @@ -1556,6 +1563,7 @@ C27360D51436866D00A9A5FF /* xpcengine.cpp in Sources */, C2DC2DCA145F594000AD2A3A /* xar++.cpp in Sources */, C2DC2DCB145F5CD000AD2A3A /* policyengine.cpp in Sources */, + C2D2967A1BCF16C000B0A29B /* diskimagerep.cpp in Sources */, C2F4439A14C626D4000A01E6 /* quarantine++.cpp in Sources */, C26763D714FD9EBE00A46EDF /* drmaker.cpp in Sources */, EB68B111150DAEEA00B4013D /* RequirementLexer.cpp in Sources */, @@ -1730,6 +1738,7 @@ CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; HEADER_SEARCH_PATHS = ( @@ -1760,6 +1769,7 @@ CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + FRAMEWORK_SEARCH_PATHS = "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks"; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; HEADER_SEARCH_PATHS = ( diff --git a/OSX/libsecurity_cssm/lib/cssmapple.h b/OSX/libsecurity_cssm/lib/cssmapple.h index 8539c227..23f383ad 100644 --- a/OSX/libsecurity_cssm/lib/cssmapple.h +++ b/OSX/libsecurity_cssm/lib/cssmapple.h @@ -85,6 +85,7 @@ enum CSSM_WORDID_PREAUTH, CSSM_WORDID_PREAUTH_SOURCE, CSSM_WORDID_ASYMMETRIC_KEY, + CSSM_WORDID_PARTITION, CSSM_WORDID__FIRST_UNUSED }; @@ -98,7 +99,8 @@ enum CSSM_ACL_SUBJECT_TYPE_SYMMETRIC_KEY = CSSM_WORDID_SYMMETRIC_KEY, CSSM_ACL_SUBJECT_TYPE_PREAUTH = CSSM_WORDID_PREAUTH, CSSM_ACL_SUBJECT_TYPE_PREAUTH_SOURCE = CSSM_WORDID_PREAUTH_SOURCE, - CSSM_ACL_SUBJECT_TYPE_ASYMMETRIC_KEY = CSSM_WORDID_ASYMMETRIC_KEY + CSSM_ACL_SUBJECT_TYPE_ASYMMETRIC_KEY = CSSM_WORDID_ASYMMETRIC_KEY, + CSSM_ACL_SUBJECT_TYPE_PARTITION = CSSM_WORDID_PARTITION, }; enum @@ -120,6 +122,8 @@ enum enum { CSSM_ACL_AUTHORIZATION_CHANGE_ACL = CSSM_ACL_AUTHORIZATION_TAG_VENDOR_DEFINED_START, CSSM_ACL_AUTHORIZATION_CHANGE_OWNER, + CSSM_ACL_AUTHORIZATION_PARTITION_ID, + CSSM_ACL_AUTHORIZATION_INTEGRITY, // the "pre-auth" tags form a contiguous range of (up to) 64K pre-authorizations CSSM_ACL_AUTHORIZATION_PREAUTH_BASE = @@ -377,7 +381,14 @@ enum { CSSM_APPLEFILEDL_COMMIT, // Rollback and discard any pending changes to the database. - CSSM_APPLEFILEDL_ROLLBACK + CSSM_APPLEFILEDL_ROLLBACK, + + // Try to take the file lock on the underlying database + // Calling commit or rollback will release the lock + CSSM_APPLEFILEDL_TAKE_FILE_LOCK, + + // Make a backup of this database in a new file + CSSM_APPLEFILEDL_MAKE_BACKUP, }; /* UNLOCK_REFERRAL "type" attribute values */ @@ -685,6 +696,11 @@ enum CSSM_APPLE_PRIVATE_CSPDL_CODE_16 = 16, CSSM_APPLE_PRIVATE_CSPDL_CODE_17 = 17, CSSM_APPLE_PRIVATE_CSPDL_CODE_18 = 18, + CSSM_APPLE_PRIVATE_CSPDL_CODE_19 = 19, + CSSM_APPLE_PRIVATE_CSPDL_CODE_20 = 20, + CSSM_APPLE_PRIVATE_CSPDL_CODE_21 = 21, + CSSM_APPLE_PRIVATE_CSPDL_CODE_22 = 22, + CSSM_APPLE_PRIVATE_CSPDL_CODE_23 = 23, /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the * associated key blob. @@ -1138,6 +1154,13 @@ typedef struct { #define kSystemKeychainName "System.keychain" #define kSystemKeychainDir "/Library/Keychains/" #define kSystemUnlockFile "/var/db/SystemKey" + + +/* + * CSSM ACL tags used to store partition/integrity data in ACLs + */ +#define CSSM_APPLE_ACL_TAG_PARTITION_ID "___PARTITION___" +#define CSSM_APPLE_ACL_TAG_INTEGRITY "___INTEGRITY___" void cssmPerror(const char *how, CSSM_RETURN error); diff --git a/OSX/libsecurity_cssm/lib/cssmapplePriv.h b/OSX/libsecurity_cssm/lib/cssmapplePriv.h index f5dc442e..e3c013a2 100644 --- a/OSX/libsecurity_cssm/lib/cssmapplePriv.h +++ b/OSX/libsecurity_cssm/lib/cssmapplePriv.h @@ -101,8 +101,21 @@ enum // stash a DB key CSSM_APPLECSPDL_DB_STASH = CSSM_APPLE_PRIVATE_CSPDL_CODE_17, - CSSM_APPLECSPDL_DB_STASH_CHECK = CSSM_APPLE_PRIVATE_CSPDL_CODE_18 - + CSSM_APPLECSPDL_DB_STASH_CHECK = CSSM_APPLE_PRIVATE_CSPDL_CODE_18, + + // Ask the CSPDL for its database blob version number. + CSSM_APPLECSPDL_DB_GET_BLOB_VERSION = CSSM_APPLE_PRIVATE_CSPDL_CODE_19, + + // Recode this database blob into a new blob version + CSSM_APPLECSPDL_DB_RECODE_TO_BLOB_VERSION = CSSM_APPLE_PRIVATE_CSPDL_CODE_20, + + // Try to take the file lock on the underlying database + // You should probably be sure that autocommit is off before taking this + CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK = CSSM_APPLE_PRIVATE_CSPDL_CODE_21, + CSSM_APPLECSPDL_DB_RELEASE_FILE_LOCK = CSSM_APPLE_PRIVATE_CSPDL_CODE_22, + + // Make a backup of this database on the filesystem + CSSM_APPLECSPDL_DB_MAKE_BACKUP = CSSM_APPLE_PRIVATE_CSPDL_CODE_23, }; /* AppleCSPDL passthrough parameters */ diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp index ddad1a74..aa307033 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.cpp +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.cpp @@ -34,6 +34,7 @@ #include #include #include +#include static const char *kAppleDatabaseChanged = "com.apple.AppleDatabaseChanged"; @@ -1686,6 +1687,8 @@ DbModifier::commit() return; try { + secdebugfunc("integrity", "committing to %s", mAtomicFile.path().c_str()); + WriteSection aHeaderSection(Allocator::standard(), size_t(HeaderSize)); // Set aHeaderSection to the correct size. aHeaderSection.size(HeaderSize); @@ -2539,6 +2542,14 @@ AppleDatabase::passThrough(DbContext &dbContext, mDbModifier.rollback(); break; + case CSSM_APPLEFILEDL_TAKE_FILE_LOCK: + mDbModifier.modifyDatabase(); + break; + + case CSSM_APPLEFILEDL_MAKE_BACKUP: + dbMakeBackup(); + break; + case CSSM_APPLECSPDL_DB_RELATION_EXISTS: { CSSM_BOOL returnValue; @@ -2562,3 +2573,19 @@ AppleDatabase::passThrough(DbContext &dbContext, break; } } + +void +AppleDatabase::dbMakeBackup() { + // Make a backup copy next to the current keychain, with filename pattern original.keychain_XXXXXX_backup + char * filename_temp_cstr = tempnam( mAtomicFile.dir().c_str(), (mAtomicFile.file() + "_").c_str() ); + 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) { + UnixError::throwMe(errno); + } +} + diff --git a/OSX/libsecurity_filedb/lib/AppleDatabase.h b/OSX/libsecurity_filedb/lib/AppleDatabase.h index c0e9dbd7..c5f429d9 100644 --- a/OSX/libsecurity_filedb/lib/AppleDatabase.h +++ b/OSX/libsecurity_filedb/lib/AppleDatabase.h @@ -441,8 +441,8 @@ public: bool hasTable(Table::Id inTableid); -protected: void modifyDatabase(); +protected: const RefPointer getDbVersion(bool force); ModifiedTable *createTable(MetaRecord *inMetaRecord); // Takes over ownership of inMetaRecord @@ -634,7 +634,9 @@ public: CSSM_DB_ACCESS_TYPE inAccessRequest, const AccessCredentials *inAccessCred, const void *inOpenParameters); - + + virtual void dbMakeBackup(); + const CssmDbRecordAttributeInfo schemaRelations; const CssmDbRecordAttributeInfo schemaAttributes; const CssmDbRecordAttributeInfo schemaIndexes; diff --git a/OSX/libsecurity_keychain/lib/ACL.cpp b/OSX/libsecurity_keychain/lib/ACL.cpp index 9b655a69..6dfd8f28 100644 --- a/OSX/libsecurity_keychain/lib/ACL.cpp +++ b/OSX/libsecurity_keychain/lib/ACL.cpp @@ -57,12 +57,12 @@ const CSSM_ACL_HANDLE ACL::ownerHandle; // // Create an ACL object from the result of a CSSM ACL query // -ACL::ACL(Access &acc, const AclEntryInfo &info, Allocator &alloc) - : allocator(alloc), access(acc), mState(unchanged), mSubjectForm(NULL), mMutex(Mutex::recursive) +ACL::ACL(const AclEntryInfo &info, Allocator &alloc) + : allocator(alloc), mState(unchanged), mSubjectForm(NULL), mIntegrity(alloc), mMutex(Mutex::recursive) { // parse the subject parse(info.proto().subject()); - + // fill in AclEntryInfo layer information const AclEntryPrototype &proto = info.proto(); mAuthorizations = proto.authorization(); @@ -73,8 +73,9 @@ ACL::ACL(Access &acc, const AclEntryInfo &info, Allocator &alloc) mCssmHandle = info.handle(); } -ACL::ACL(Access &acc, const AclOwnerPrototype &owner, Allocator &alloc) - : allocator(alloc), access(acc), mState(unchanged), mSubjectForm(NULL), mMutex(Mutex::recursive) + +ACL::ACL(const AclOwnerPrototype &owner, Allocator &alloc) + : allocator(alloc), mState(unchanged), mSubjectForm(NULL), mIntegrity(alloc), mMutex(Mutex::recursive) { // parse subject parse(owner.subject()); @@ -95,8 +96,8 @@ ACL::ACL(Access &acc, const AclOwnerPrototype &owner, Allocator &alloc) // To generate a "standard" form of ANY, use the appListForm constructor below, // then change its form to allowAnyForm. // -ACL::ACL(Access &acc, Allocator &alloc) - : allocator(alloc), access(acc), mSubjectForm(NULL), mMutex(Mutex::recursive) +ACL::ACL(Allocator &alloc) + : allocator(alloc), mSubjectForm(NULL), mIntegrity(alloc), mMutex(Mutex::recursive) { mState = inserted; // new mForm = allowAllForm; // everybody @@ -115,9 +116,9 @@ ACL::ACL(Access &acc, Allocator &alloc) // Create a new ACL in standard form. // As created, it authorizes all activities. // -ACL::ACL(Access &acc, string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector, +ACL::ACL(string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector, Allocator &alloc) - : allocator(alloc), access(acc), mSubjectForm(NULL), mMutex(Mutex::recursive) + : allocator(alloc), mSubjectForm(NULL), mIntegrity(alloc), mMutex(Mutex::recursive) { mState = inserted; // new mForm = appListForm; @@ -132,6 +133,26 @@ ACL::ACL(Access &acc, string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTO } +// +// Create an "integrity" ACL +// +ACL::ACL(const CssmData &digest, Allocator &alloc) +: allocator(alloc), mSubjectForm(NULL), mIntegrity(alloc, digest), mMutex(Mutex::recursive) +{ + mState = inserted; // new + mForm = integrityForm; + mAuthorizations.insert(CSSM_ACL_AUTHORIZATION_INTEGRITY); + mEntryTag = CSSM_APPLE_ACL_TAG_INTEGRITY; + mDelegate = false; + + //mPromptDescription stays empty + //mPromptSelector stays empty + + // randomize the CSSM handle + UniformRandomBlobs().random(mCssmHandle); +} + + // // Destroy an ACL // @@ -153,6 +174,28 @@ bool ACL::authorizes(AclAuthorization right) || mAuthorizations.empty(); } +// +// Does this ACL have a specific authorization for a particular right? +// +bool ACL::authorizesSpecifically(AclAuthorization right) +{ + StLock_(mMutex); + return mAuthorizations.find(right) != mAuthorizations.end(); +} + +void ACL::setIntegrity(const CssmData& digest) { + if(mForm != integrityForm) { + secdebugfunc("integrity", "acl has incorrect form: %d", mForm); + CssmError::throwMe(CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE); + } + + mIntegrity = digest; + modify(); +} + +const CssmData& ACL::integrity() { + return mIntegrity.get(); +} // // Add an application to the trusted-app list of this ACL. @@ -205,6 +248,7 @@ void ACL::remove() StLock_(mMutex); mAppList.clear(); mForm = invalidForm; + secdebug("SecAccess", "ACL %p marked deleted", this); mState = deleted; } @@ -307,10 +351,12 @@ void ACL::setAccess(AclBearer &target, bool update, case inserted: // insert secdebug("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()); target.changeAcl(entryHandle(), input, cred); + mState = unchanged; break; default: assert(false); @@ -330,11 +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); 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); return; case CSSM_ACL_SUBJECT_TYPE_THRESHOLD: { @@ -353,22 +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); return; } // parse other (code signing) elements - for (uint32 n = 0; n < count - 1; n++) - mAppList.push_back(new TrustedApplication(TypedList(subject[n + 3].list()))); + 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()); + } } mForm = appListForm; + secdebug("SecAccess", "parsed a Threshhold (%d) as an appListForm (%d)", subject.type(), mForm); return; - default: + 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); + return; + default: + secdebug("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; marking custom"); + secdebug("SecAccess", "acl compile failed for type (%d); marking custom", subject.type()); mForm = customForm; mSubjectForm = chunkCopy(&subject); mAppList.clear(); @@ -408,6 +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()); return; case appListForm: { // threshold(1 of n+1) of { app1, ..., appn, PROMPT } @@ -424,10 +483,19 @@ 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()); 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()); + return; case customForm: assert(mSubjectForm); // already set; keep it + secdebug("SecAccess", "have a customForm (%d), already have a subjectForm (%d)", mForm, mSubjectForm->type()); return; + default: assert(false); // unexpected } diff --git a/OSX/libsecurity_keychain/lib/ACL.h b/OSX/libsecurity_keychain/lib/ACL.h index 5ad2a2df..ceacab9b 100644 --- a/OSX/libsecurity_keychain/lib/ACL.h +++ b/OSX/libsecurity_keychain/lib/ACL.h @@ -53,19 +53,25 @@ class ACL : public SecCFObject { public: SECCFFUNCTIONS(ACL, SecACLRef, errSecInvalidItemRef, gTypes().ACL) + // Query AclBearer for ACL entry matching tag. Will throw if there is not exactly 1 entry. + ACL(const AclBearer &aclBearer, const char *selectionTag, + Allocator &alloc = Allocator::standard()); // create from CSSM layer ACL entry - ACL(Access &acc, const AclEntryInfo &info, + ACL(const AclEntryInfo &info, Allocator &alloc = Allocator::standard()); // create from CSSM layer owner prototype - ACL(Access &acc, const AclOwnerPrototype &owner, + ACL(const AclOwnerPrototype &owner, Allocator &alloc = Allocator::standard()); // create an "any" ACL - ACL(Access &acc, Allocator &alloc = Allocator::standard()); + ACL(Allocator &alloc = Allocator::standard()); // create from "standard form" arguments (with empty application list) - ACL(Access &acc, string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector, + ACL(string description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR &promptSelector, Allocator &alloc = Allocator::standard()); + // create an "integrity" ACL + ACL(const CssmData &digest, Allocator &alloc = Allocator::standard()); + virtual ~ACL(); - + Allocator &allocator; enum State { @@ -80,16 +86,19 @@ public: invalidForm, // invalid customForm, // not a recognized format (but valid) allowAllForm, // indiscriminate - appListForm // list of apps + prompt confirm + appListForm, // list of apps + prompt confirm + integrityForm // hashed integrity of item attributes }; Form form() const { return mForm; } void form(Form f) { mForm = f; } - Access &access; // we belong to this Access - + void setIntegrity(const CssmData& integrity); + const CssmData& integrity(); + public: AclAuthorizationSet &authorizations() { return mAuthorizations; } bool authorizes(AclAuthorization right); + bool authorizesSpecifically(AclAuthorization right); void setAuthorization(CSSM_ACL_AUTHORIZATION_TAG auth) { mAuthorizations.clear(); mAuthorizations.insert(auth); } @@ -145,6 +154,7 @@ private: // following values valid only if form() == appListForm ApplicationList mAppList; // list of trusted applications + CssmAutoData mIntegrity; // digest for integrityForm ACL entries CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR mPromptSelector; // selector field of PROMPT subject string mPromptDescription; // description field of PROMPT subject Mutex mMutex; diff --git a/OSX/libsecurity_keychain/lib/Access.cpp b/OSX/libsecurity_keychain/lib/Access.cpp index d510cd98..2aa23a18 100644 --- a/OSX/libsecurity_keychain/lib/Access.cpp +++ b/OSX/libsecurity_keychain/lib/Access.cpp @@ -49,11 +49,11 @@ const CSSM_ACL_HANDLE Access::ownerHandle; // Access::Access() : mMutex(Mutex::recursive) { - SecPointer owner = new ACL(*this); + SecPointer owner = new ACL(); owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL); addOwner(owner); - SecPointer any = new ACL(*this); + SecPointer any = new ACL(); add(any); } @@ -87,12 +87,12 @@ void Access::makeStandard(const string &descriptor, const ACL::ApplicationList & StLock_(mMutex); // owner "entry" - SecPointer owner = new ACL(*this, descriptor, ACL::defaultSelector); + SecPointer owner = new ACL(descriptor, ACL::defaultSelector); owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL); addOwner(owner); // unlimited entry - SecPointer unlimited = new ACL(*this, descriptor, ACL::defaultSelector); + SecPointer unlimited = new ACL(descriptor, ACL::defaultSelector); if (freeRights.empty()) { unlimited->authorizations().clear(); unlimited->authorizations().insert(CSSM_ACL_AUTHORIZATION_ENCRYPT); @@ -102,7 +102,7 @@ void Access::makeStandard(const string &descriptor, const ACL::ApplicationList & add(unlimited); // limited entry - SecPointer limited = new ACL(*this, descriptor, ACL::defaultSelector); + SecPointer limited = new ACL(descriptor, ACL::defaultSelector); if (limitedRights.empty()) { limited->authorizations().clear(); limited->authorizations().insert(CSSM_ACL_AUTHORIZATION_DECRYPT); @@ -160,7 +160,7 @@ convert(const SecPointer &acl) // CFArrayRef Access::copySecACLs() const { - return makeCFArray(convert, mAcls); + return makeCFArrayFrom(convert, mAcls); } CFArrayRef Access::copySecACLs(CSSM_ACL_AUTHORIZATION_TAG action) const @@ -169,7 +169,7 @@ CFArrayRef Access::copySecACLs(CSSM_ACL_AUTHORIZATION_TAG action) const for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) if (it->second->authorizes(action)) choices.push_back(it->second); - return choices.empty() ? NULL : makeCFArray(convert, choices); + return choices.empty() ? NULL : makeCFArrayFrom(convert, choices); } @@ -263,6 +263,20 @@ void Access::copyOwnerAndAcl(CSSM_ACL_OWNER_PROTOTYPE * &ownerResult, } +// +// Remove all ACLs that confer this right. +// +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()); + } else { + it++; + } + } +} + // // Retrieve the description from a randomly chosen ACL within this Access. // In the conventional case where all ACLs have the same descriptor, this @@ -296,8 +310,6 @@ string Access::promptDescription() const void Access::add(ACL *newAcl) { StLock_(mMutex); - if (&newAcl->access != this) - MacOSError::throwMe(errSecParam); assert(!mAcls[newAcl->entryHandle()]); mAcls[newAcl->entryHandle()] = newAcl; } @@ -326,13 +338,15 @@ void Access::compile(const CSSM_ACL_OWNER_PROTOTYPE &owner, { StLock_(mMutex); // add owner acl - mAcls[ownerHandle] = new ACL(*this, AclOwnerPrototype::overlay(owner)); + mAcls[ownerHandle] = new ACL(AclOwnerPrototype::overlay(owner)); + secdebugfunc("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()); - mAcls[acl[n].handle()] = new ACL(*this, acl[n]); + mAcls[acl[n].handle()] = new ACL(acl[n]); + secdebug("SecAccess", "form is: %d", mAcls[acl[n].handle()]->form()); } secdebug("SecAccess", "%p %ld entries compiled", this, mAcls.size()); } @@ -356,6 +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); // create credential sample for access mCreds += TypedList(allocator, CSSM_SAMPLE_TYPE_PASSWORD, new(allocator) ListElement(mKey.get())); @@ -364,6 +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); } } diff --git a/OSX/libsecurity_keychain/lib/Access.h b/OSX/libsecurity_keychain/lib/Access.h index ec562dd8..e3d22db1 100644 --- a/OSX/libsecurity_keychain/lib/Access.h +++ b/OSX/libsecurity_keychain/lib/Access.h @@ -99,6 +99,8 @@ public: void setAccess(AclBearer &target, bool update = false); void setAccess(AclBearer &target, Maker &maker); + void editAccess(AclBearer &target, bool update, const AccessCredentials *cred); + template void findAclsForRight(AclAuthorization right, Container &cont) { @@ -107,6 +109,20 @@ public: if (it->second->authorizes(right)) cont.push_back(it->second); } + + // findAclsForRight may return ACLs that have an empty authorization list (and thus "authorize everything") + // or CSSM_ACL_AUTHORIZATION_ANY, but sometimes you need positive confirmation of a right. + template + void findSpecificAclsForRight(AclAuthorization right, Container &cont) + { + cont.clear(); + for (Map::const_iterator it = mAcls.begin(); it != mAcls.end(); it++) + if (it->second->authorizesSpecifically(right)) + cont.push_back(it->second); + } + + // Remove all acl entries that refer to this right. + void removeAclsForRight(AclAuthorization right); std::string promptDescription() const; // from any one of the ACLs contained @@ -121,8 +137,7 @@ protected: const AclAuthorizationSet &freeRights = AclAuthorizationSet()); void compile(const CSSM_ACL_OWNER_PROTOTYPE &owner, uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls); - - void editAccess(AclBearer &target, bool update, const AccessCredentials *cred); + private: static const CSSM_ACL_HANDLE ownerHandle = ACL::ownerHandle; diff --git a/OSX/libsecurity_keychain/lib/CCallbackMgr.cp b/OSX/libsecurity_keychain/lib/CCallbackMgr.cp index 66741f9f..877dc9d0 100644 --- a/OSX/libsecurity_keychain/lib/CCallbackMgr.cp +++ b/OSX/libsecurity_keychain/lib/CCallbackMgr.cp @@ -220,7 +220,13 @@ void CCallbackMgr::consume (SecurityServer::NotificationDomain domain, SecurityS if (item && thisKeychain) { PrimaryKey pk(item->Value()); - thisItem = thisKeychain->item(pk); + + // if this is a deletion event, do the lookup slightly differently + if(thisEvent != kSecDeleteEvent) { + thisItem = thisKeychain->item(pk); + } else { + thisItem = thisKeychain->itemdeleted(pk); + } } // Deal with events that we care about ourselves first. diff --git a/OSX/libsecurity_keychain/lib/Certificate.cpp b/OSX/libsecurity_keychain/lib/Certificate.cpp index 1b625a49..0b7cc0b2 100644 --- a/OSX/libsecurity_keychain/lib/Certificate.cpp +++ b/OSX/libsecurity_keychain/lib/Certificate.cpp @@ -58,7 +58,8 @@ Certificate::Certificate(const CSSM_DATA &data, CSSM_CERT_TYPE type, CSSM_CERT_E mV1SubjectPublicKeyCStructValue(NULL), mV1SubjectNameCStructValue(NULL), mV1IssuerNameCStructValue(NULL), - mSha1Hash(NULL), + mSha1Hash(NULL), + mSha256Hash(NULL), mEncodingVerified(false) { if (data.Length == 0 || data.Data == NULL) @@ -75,7 +76,8 @@ Certificate::Certificate(const Keychain &keychain, const PrimaryKey &primaryKey, mV1SubjectPublicKeyCStructValue(NULL), mV1SubjectNameCStructValue(NULL), mV1IssuerNameCStructValue(NULL), - mSha1Hash(NULL), + mSha1Hash(NULL), + mSha256Hash(NULL), mEncodingVerified(false) { } @@ -112,6 +114,7 @@ Certificate::Certificate(const Keychain &keychain, const PrimaryKey &primaryKey) mV1SubjectNameCStructValue(NULL), mV1IssuerNameCStructValue(NULL), mSha1Hash(NULL), + mSha256Hash(NULL), mEncodingVerified(false) { // @@@ In this case we don't know the type... @@ -129,6 +132,7 @@ Certificate::Certificate(Certificate &certificate) : mV1SubjectNameCStructValue(NULL), mV1IssuerNameCStructValue(NULL), mSha1Hash(NULL), + mSha256Hash(NULL), mEncodingVerified(false) { } @@ -150,6 +154,8 @@ try if (mSha1Hash) CFRelease(mSha1Hash); + if (mSha256Hash) + CFRelease(mSha256Hash); } catch (...) { @@ -911,6 +917,28 @@ Certificate::sha1Hash() return mSha1Hash; /* object is owned by our instance; caller should NOT release it */ } +CFDataRef +Certificate::sha256Hash() +{ + StLock_(mMutex); + if (!mSha256Hash) { + SecCertificateRef certRef = handle(false); + CFAllocatorRef allocRef = (certRef) ? CFGetAllocator(certRef) : NULL; + CSSM_DATA certData = data(); + if (certData.Length == 0 || !certData.Data) { + MacOSError::throwMe(errSecDataNotAvailable); + } + const UInt8 *dataPtr = (const UInt8 *)certData.Data; + CFIndex dataLen = (CFIndex)certData.Length; + CFMutableDataRef digest = CFDataCreateMutable(allocRef, CC_SHA256_DIGEST_LENGTH); + CFDataSetLength(digest, CC_SHA256_DIGEST_LENGTH); + CCDigest(kCCDigestSHA256, dataPtr, dataLen, CFDataGetMutableBytePtr(digest)); + mSha256Hash = digest; + } + return mSha256Hash; /* object is owned by our instance; caller should NOT release it */ +} + + CFStringRef Certificate::commonName() { diff --git a/OSX/libsecurity_keychain/lib/Certificate.h b/OSX/libsecurity_keychain/lib/Certificate.h index 867cd480..cc74c619 100644 --- a/OSX/libsecurity_keychain/lib/Certificate.h +++ b/OSX/libsecurity_keychain/lib/Certificate.h @@ -74,7 +74,8 @@ public: const CssmData &data(); CSSM_CERT_TYPE type(); CSSM_CERT_ENCODING encoding(); - CFDataRef sha1Hash(); + CFDataRef sha1Hash(); + CFDataRef sha256Hash(); CFStringRef commonName(); CFStringRef distinguishedName(const CSSM_OID *sourceOid, const CSSM_OID *componentOid); CFStringRef copyFirstEmailAddress(); @@ -140,7 +141,8 @@ private: CSSM_DATA_PTR mV1SubjectPublicKeyCStructValue; // Hack to prevent algorithmID() from leaking. CSSM_DATA_PTR mV1SubjectNameCStructValue; CSSM_DATA_PTR mV1IssuerNameCStructValue; - CFDataRef mSha1Hash; + CFDataRef mSha1Hash; + CFDataRef mSha256Hash; bool mEncodingVerified; }; diff --git a/OSX/libsecurity_keychain/lib/Globals.cpp b/OSX/libsecurity_keychain/lib/Globals.cpp index f8d1e70e..6c299b92 100644 --- a/OSX/libsecurity_keychain/lib/Globals.cpp +++ b/OSX/libsecurity_keychain/lib/Globals.cpp @@ -38,8 +38,15 @@ bool gServerMode; #pragma mark ÑÑÑÑ Constructor/Destructor ÑÑÑÑ Globals::Globals() : -mUI(true) +mUI(true), mIntegrityProtection(false) { + //sudo defaults write /Library/Preferences/com.apple.security KeychainIntegrity -bool YES + CFTypeRef integrity = (CFNumberRef)CFPreferencesCopyValue(CFSTR("KeychainIntegrity"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost); + + if (integrity && CFGetTypeID(integrity) == CFBooleanGetTypeID()) { + mIntegrityProtection = CFBooleanGetValue((CFBooleanRef)integrity); + CFRelease(integrity); + } } const AccessCredentials * Globals::keychainCredentials() diff --git a/OSX/libsecurity_keychain/lib/Globals.h b/OSX/libsecurity_keychain/lib/Globals.h index 4b192b0d..5147ea55 100644 --- a/OSX/libsecurity_keychain/lib/Globals.h +++ b/OSX/libsecurity_keychain/lib/Globals.h @@ -56,10 +56,13 @@ public: // Public globals StorageManager storageManager; + bool integrityProtection() { return mIntegrityProtection; } + private: // Other "globals" bool mUI; + bool mIntegrityProtection; CssmClient::AclFactory mACLFactory; }; diff --git a/OSX/libsecurity_keychain/lib/Item.cpp b/OSX/libsecurity_keychain/lib/Item.cpp index 057f0618..025c8b3a 100644 --- a/OSX/libsecurity_keychain/lib/Item.cpp +++ b/OSX/libsecurity_keychain/lib/Item.cpp @@ -43,6 +43,10 @@ #include #include #include +#include + +#include +#include #define SENDACCESSNOTIFICATIONS 1 @@ -148,24 +152,11 @@ ItemImpl::ItemImpl(ItemImpl &item) : mMutex(Mutex::recursive) { mDbAttributes->recordType(item.recordType()); - CSSM_DB_RECORD_ATTRIBUTE_INFO *schemaAttributes = NULL; 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. - - for (uint32 i = 0; i < Schema::DBInfo.NumberOfRecordTypes; i++) - if (item.recordType() == Schema::DBInfo.RecordAttributeNames[i].DataRecordType) { - schemaAttributes = &Schema::DBInfo.RecordAttributeNames[i]; - break; - } - - if (schemaAttributes == NULL) - // the source item is invalid - MacOSError::throwMe(errSecInvalidItemRef); - - for (uint32 i = 0; i < schemaAttributes->NumberOfAttributes; i++) - mDbAttributes->add(schemaAttributes->AttributeInfo[i]); + fillDbAttributesFromSchema(*mDbAttributes, item.recordType()); item.getContent(mDbAttributes.get(), mData.get()); } @@ -199,14 +190,12 @@ ItemImpl::getMutexForObject() } - void ItemImpl::aboutToDestruct() { - if (mKeychain && *mPrimaryKey) - { - mKeychain->removeItem(mPrimaryKey, this); - } + if(mKeychain.get()) { + mKeychain->forceRemoveFromCache(this); + } } @@ -248,7 +237,361 @@ ItemImpl::defaultAttributeValue(const CSSM_DB_ATTRIBUTE_INFO &info) } } +void ItemImpl::fillDbAttributesFromSchema(DbAttributes& dbAttributes, CSSM_DB_RECORDTYPE recordType, Keychain keychain) { + // If we weren't passed a keychain, use our own. + keychain = !!keychain ? keychain : mKeychain; + + // Without a keychain, there's no one to ask. + if(!keychain) { + return; + } + + SecKeychainAttributeInfo* infos; + keychain->getAttributeInfoForItemID(recordType, &infos); + + secdebugfunc("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; + memset(&info, 0, sizeof(info)); + + info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER; + info.Label.AttributeID = infos->tag[i]; + info.AttributeFormat = infos->format[i]; + + dbAttributes.add(info); + } + + keychain->freeAttributeInfo(infos); +} + +DbAttributes* ItemImpl::getCurrentAttributes() { + DbAttributes* dbAttributes; + secdebugfunc("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); + fillDbAttributesFromSchema(*dbAttributes, recordType()); + mUniqueId->get(dbAttributes, NULL); + + // and fold in any updates. + if(mDbAttributes.get()) { + secdebugfunc("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()); + 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"); + dbAttributes = new DbAttributes(); + } + dbAttributes->recordType(recordType()); + // TODO: We don't set semanticInformation. Issue? + + return dbAttributes; +} + + +void ItemImpl::encodeAttributes(CssmOwnedData &attributeBlob) { + // Sometimes we don't have our attributes. Find them. + auto_ptr dbAttributes(getCurrentAttributes()); + encodeAttributesFromDictionary(attributeBlob, dbAttributes.get()); + +} + +void ItemImpl::encodeAttributesFromDictionary(CssmOwnedData &attributeBlob, DbAttributes* dbAttributes) { + // Create a CFDictionary from dbAttributes and call der_encode_dictionary on it + CFRef attributes; + attributes.take(CFDictionaryCreateMutable(NULL, dbAttributes->size(), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + secdebugfunc("integrity", "looking at %d attributes", dbAttributes->size()); + // TODO: include record type and semantic information? + + for(int i = 0; i < dbAttributes->size(); i++) { + CssmDbAttributeData& data = dbAttributes->attributes()[i]; + CssmDbAttributeInfo& datainfo = data.info(); + + // Sometimes we need to normalize the info. Calling Schema::attributeInfo is the best way to do that. + // There's no avoiding the try-catch structure here, since only some of the names are in Schema::attributeInfo, + // but it will only indicate that by throwing. + CssmDbAttributeInfo& actualInfo = datainfo; + try { + if(datainfo.nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER && Schema::haveAttributeInfo(datainfo.intName())) { + actualInfo = Schema::attributeInfo(datainfo.intName()); + } + } catch(...) { + actualInfo = datainfo; + } + + // Pull the label/name out of this data + CFRef label = NULL; + + switch(actualInfo.nameFormat()) { + case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: { + const char* stringname = actualInfo.stringName(); + label.take(CFDataCreate(NULL, reinterpret_cast(stringname), strlen(stringname))); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_OID: { + const CssmOid& oidname = actualInfo.oidName(); + label.take(CFDataCreate(NULL, reinterpret_cast(oidname.data()), oidname.length())); + break; + } + case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: { + uint32 iname = actualInfo.intName(); + label.take(CFDataCreate(NULL, reinterpret_cast(&(iname)), sizeof(uint32))); + break; + } + } + + if(data.size() == 0) { + // This attribute doesn't have a value, and so shouldn't be included in the digest. + continue; + } + + // Do not include the Creation or Modification date attributes in the hash. + // Use this complicated method of checking so we'll catch string and integer names. + SecKeychainAttrType cdat = kSecCreationDateItemAttr; + SecKeychainAttrType cmod = kSecModDateItemAttr; + if((CFDataGetLength(label) == sizeof(SecKeychainAttrType)) && + ((memcmp(CFDataGetBytePtr(label), &cdat, sizeof(SecKeychainAttrType)) == 0) || + (memcmp(CFDataGetBytePtr(label), &cmod, sizeof(SecKeychainAttrType)) == 0))) { + continue; + } + + // Collect the raw data for each value of this CssmDbAttributeData + CFRef attributeDataContainer; + attributeDataContainer.take(CFArrayCreateMutable(NULL, data.size(), &kCFTypeArrayCallBacks)); + + for(int j = 0; j < data.size(); j++) { + CssmData& entry = data.values()[j]; + + CFRef datadata = NULL; + switch(actualInfo.format()) { + case CSSM_DB_ATTRIBUTE_FORMAT_BLOB: + case CSSM_DB_ATTRIBUTE_FORMAT_STRING: + case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: + datadata.take(CFDataCreate(NULL, reinterpret_cast(data.values()[j].data()), data.values()[j].length())); + break; + + case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: { + uint32 x = entry.length() == 1 ? *reinterpret_cast(entry.Data) : + entry.length() == 2 ? *reinterpret_cast(entry.Data) : + entry.length() == 4 ? *reinterpret_cast(entry.Data) : 0; + datadata.take(CFDataCreate(NULL, reinterpret_cast(&x), sizeof(x))); + break; + } + + case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: { + sint32 x = entry.length() == 1 ? *reinterpret_cast(entry.Data) : + entry.length() == 2 ? *reinterpret_cast(entry.Data) : + entry.length() == 4 ? *reinterpret_cast(entry.Data) : 0; + datadata.take(CFDataCreate(NULL, reinterpret_cast(&x), sizeof(x))); + break; + } + // CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM is unimplemented here but + // has some canonicalization requirements, see DbValue.cpp + + default: + continue; + } + + CFArrayAppendValue(attributeDataContainer, datadata); + } + CFDictionaryAddValue(attributes, label, attributeDataContainer); + } + + // Now that we have a CFDictionary containing a bunch of CFDatas, turn that + // into a der blob. + + CFErrorRef error; + CFRef derBlob; + derBlob.take(CFPropertyListCreateDERData(NULL, attributes, &error)); + + // TODO: How do we check error here? + + if(!derBlob) { + return; + } + + attributeBlob.length(CFDataGetLength(derBlob)); + attributeBlob.copy(CFDataGetBytePtr(derBlob), CFDataGetLength(derBlob)); +} + +void ItemImpl::computeDigest(CssmOwnedData &sha2) { + auto_ptr dbAttributes(getCurrentAttributes()); + ItemImpl::computeDigestFromDictionary(sha2, dbAttributes.get()); +} + +void ItemImpl::computeDigestFromDictionary(CssmOwnedData &sha2, DbAttributes* dbAttributes) { + try{ + CssmAutoData attributeBlob(Allocator::standard()); + encodeAttributesFromDictionary(attributeBlob, dbAttributes); + + 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()); + } catch (MacOSError mose) { + secdebugfunc("integrity", "MacOSError: %d", (int)mose.osStatus()); + } catch (...) { + secdebugfunc("integrity", "unknown exception"); + } +} + +void ItemImpl::addIntegrity(Access &access, bool force) { + secdebugfunc("integrity", "called"); + + if(!force && (!mKeychain || !mKeychain->hasIntegrityProtection())) { + secdebugfunc("integrity", "skipping integrity add due to keychain version\n"); + return; + } + + ACL * acl = NULL; + CssmAutoData digest(Allocator::standard()); + computeDigest(digest); + + // First, check if this already has an integrity tag + vector acls; + access.findSpecificAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY, acls); + + if(acls.size() >= 1) { + // Use the existing ACL + acl = acls[0]; + secdebugfunc("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); + acls[i]->remove(); + } + } else if(acls.size() == 0) { + // Make a new ACL + secdebugfunc("integrity", "no previous integrity acl exists; making a new one"); + acl = new ACL(digest.get()); + access.add(acl); + } +} + + void ItemImpl::setIntegrity(bool force) { + if(!force && (!mKeychain || !mKeychain->hasIntegrityProtection())) { + secdebugfunc("integrity", "skipping integrity set due to keychain version"); + return; + } + + // For Items, only passwords should have integrity + if(!(recordType() == CSSM_DL_DB_RECORD_GENERIC_PASSWORD || recordType() == CSSM_DL_DB_RECORD_INTERNET_PASSWORD)) { + return; + } + + // If we're not on an SSDb, we shouldn't have integrity + Db db(mKeychain->database()); + if (!useSecureStorage(db)) { + return; + } + + setIntegrity(*group(), force); + } + +void ItemImpl::setIntegrity(AclBearer &bearer, bool force) { + if(!force && (!mKeychain || !mKeychain->hasIntegrityProtection())) { + secdebugfunc("integrity", "skipping integrity acl set due to keychain version"); + return; + } + + SecPointer access = new Access(bearer); + + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID); + addIntegrity(*access, force); + access->setAccess(bearer, true); +} + +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?"); + return true; + } + + if(!mKeychain || !mKeychain->hasIntegrityProtection()) { + secdebugfunc("integrity", "skipping integrity check due to keychain version"); + return true; + } + + // Collect our SSGroup, if it exists. + dbUniqueRecord(); + SSGroup ssGroup = group(); + if(ssGroup) { + return checkIntegrity(*ssGroup); + } + + // If we don't have an SSGroup, we can't be invalid. return true. + return true; +} + +bool ItemImpl::checkIntegrity(AclBearer& aclBearer) { + if(!mKeychain || !mKeychain->hasIntegrityProtection()) { + secdebugfunc("integrity", "skipping integrity check due to keychain version"); + return true; + } + + auto_ptr dbAttributes(getCurrentAttributes()); + return checkIntegrityFromDictionary(aclBearer, dbAttributes.get()); +} + +bool ItemImpl::checkIntegrityFromDictionary(AclBearer& aclBearer, DbAttributes* dbAttributes) { + try { + AutoAclEntryInfoList aclInfos; + aclBearer.getAcl(aclInfos, CSSM_APPLE_ACL_TAG_INTEGRITY); + + // We should only expect there to be one integrity tag. If there's not, + // take the first one and ignore the rest. We should probably attempt delete + // them. + + AclEntryInfo &info = aclInfos.at(0); + 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"); + } + + CssmAutoData digest(Allocator::standard()); + computeDigestFromDictionary(digest, dbAttributes); + if (acl->integrity() == digest.get()) { + return true; + } + } + catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secdebugfunc("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); + + if(cssme.error == CSSMERR_CSP_ACL_ENTRY_TAG_NOT_FOUND) { + // TODO: No entry, run migrator? + return true; + } + if(cssme.error == CSSMERR_CSP_INVALID_ACL_SUBJECT_VALUE) { + // something went horribly wrong with fetching acl. + + secdebugfunc("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"); + } + + throw cssme; + } + secdebugfunc("integrity", "***** INVALID ITEM"); + return false; +} PrimaryKey ItemImpl::addWithCopyInfo (Keychain &keychain, bool isCopy) { @@ -339,115 +682,30 @@ PrimaryKey ItemImpl::addWithCopyInfo (Keychain &keychain, bool isCopy) } } - Db db(keychain->database()); - if (mDoNotEncrypt) - { - mUniqueId = db->insertWithoutEncryption (recordType, NULL, mData.get()); - } - else if (useSecureStorage(db)) - { - // Add the item to the secure storage db - SSDbImpl* impl = dynamic_cast(&(*db)); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - SSDb ssDb(impl); - - TrackingAllocator allocator(Allocator::standard()); - - // hhs replaced with the new aclFactory class - AclFactory aclFactory; - const AccessCredentials *nullCred = aclFactory.nullCred(); - - SecPointer access = mAccess; - if (!access) { - // 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"; - access = new Access(printName); - - // special case for "iTools" password - allow anyone to decrypt the item - if (recordType == CSSM_DL_DB_RECORD_GENERIC_PASSWORD) - { - CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(kSecServiceItemAttr)); - if (data && data->Value[0].Length == 6 && !memcmp("iTools", data->Value[0].Data, 6)) - { - typedef vector > AclSet; - AclSet acls; - access->findAclsForRight(CSSM_ACL_AUTHORIZATION_DECRYPT, acls); - for (AclSet::const_iterator it = acls.begin(); it != acls.end(); it++) - (*it)->form(ACL::allowAllForm); - } - } - } - - // Get the handle of the DL underlying this CSPDL. - CSSM_DL_DB_HANDLE dldbh; - db->passThrough(CSSM_APPLECSPDL_DB_GET_HANDLE, NULL, - reinterpret_cast(&dldbh)); - - // Turn off autocommit on the underlying DL and remember the old state. - CSSM_BOOL autoCommit = CSSM_TRUE; - ObjectImpl::check(CSSM_DL_PassThrough(dldbh, - CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - 0, reinterpret_cast(&autoCommit))); - - try - { - // Create a new SSGroup with temporary access controls - Access::Maker maker; - ResourceControlContext prototype; - maker.initialOwner(prototype, nullCred); - SSGroup ssGroup(ssDb, &prototype); - - try - { - // Insert the record using the newly created group. - mUniqueId = ssDb->insert(recordType, mDbAttributes.get(), - mData.get(), ssGroup, maker.cred()); - } - catch(...) - { - ssGroup->deleteKey(nullCred); - throw; - } + try { + mKeychain = keychain; - // now finalize the access controls on the group - access->setAccess(*ssGroup, maker); - mAccess = NULL; // use them and lose them - if (autoCommit) - { - // autoCommit was on so commit now that we are done and turn - // it back on. - ObjectImpl::check(CSSM_DL_PassThrough(dldbh, - CSSM_APPLEFILEDL_COMMIT, NULL, NULL)); - CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - reinterpret_cast(autoCommit), NULL); - } - } - catch (...) - { - if (autoCommit) - { - // autoCommit was off so rollback since we failed and turn - // autoCommit back on. - CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_ROLLBACK, NULL, NULL); - CSSM_DL_PassThrough(dldbh, CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, - reinterpret_cast(autoCommit), NULL); - } - throw; - } - } - else - { - // add the item to the (regular) db - mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); - } + Db db(keychain->database()); + if (mDoNotEncrypt) + { + mUniqueId = db->insertWithoutEncryption (recordType, NULL, mData.get()); + } + else if (useSecureStorage(db)) + { + updateSSGroup(db, recordType, mData.get(), keychain, mAccess); + mAccess = NULL; // use them and lose them - TODO: should this only be unset if there's no error in saveToNewSSGroup? Unclear. + } + else + { + // add the item to the (regular) db + mUniqueId = db->insert(recordType, mDbAttributes.get(), mData.get()); + } - mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); - mKeychain = keychain; + mPrimaryKey = keychain->makePrimaryKey(recordType, mUniqueId); + } catch(...) { + mKeychain = NULL; + throw; + } // Forget our data and attributes. mData = NULL; @@ -526,26 +784,13 @@ ItemImpl::update() } else if (useSecureStorage(db)) { - // Add the item to the secure storage db - SSDbUniqueRecordImpl * impl = dynamic_cast(&(*mUniqueId)); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - SSDbUniqueRecord ssUniqueId(impl); - - // @@@ Share this instance - const AccessCredentials *autoPrompt = globals().itemCredentials(); - - - // Only call this is user interaction is enabled. - ssUniqueId->modify(aRecordType, - mDbAttributes.get(), - mData.get(), - CSSM_DB_MODIFY_ATTRIBUTE_REPLACE, - autoPrompt); - } + // Pass mData to updateSSGroup. If we have any data to change (and it's + // therefore non-null), it'll save to a new SSGroup; otherwise, it will + // update the old ssgroup. This prevents a RAA on attribute update, while + // still protecting new data from being decrypted by old SSGroups with + // outdated attributes. + updateSSGroup(db, recordType(), mData.get()); + } else { mUniqueId->modify(aRecordType, @@ -568,6 +813,270 @@ ItemImpl::update() } } +void +ItemImpl::updateSSGroup(Db& db, CSSM_DB_RECORDTYPE recordType, CssmDataContainer* newdata, Keychain keychain, SecPointer access) +{ + // hhs replaced with the new aclFactory class + AclFactory aclFactory; + const AccessCredentials *nullCred = aclFactory.nullCred(); + + secdebugfunc("integrity", "called"); + + bool haveOldUniqueId = !!mUniqueId.get(); + SSDbUniqueRecord ssUniqueId(NULL); + SSGroup ssGroup(NULL); + if(haveOldUniqueId) { + ssUniqueId = SSDbUniqueRecord(dynamic_cast(&(*mUniqueId))); + if (ssUniqueId.get() == NULL) { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + ssGroup = ssUniqueId->group(); + } + + // If we have new data OR no old unique id, save to a new group + bool saveToNewSSGroup = (!!newdata) || (!haveOldUniqueId); + + // If there aren't any attributes, make up some blank ones. + if (!mDbAttributes.get()) + { + secdebugfunc("integrity", "making new dbattributes"); + mDbAttributes.reset(new DbAttributes()); + mDbAttributes->recordType(mPrimaryKey->recordType()); + } + + // Add the item to the secure storage db + SSDbImpl* impl = dynamic_cast(&(*db)); + if (impl == NULL) + { + CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); + } + + SSDb ssDb(impl); + + TrackingAllocator allocator(Allocator::standard()); + + if ((!access) && (haveOldUniqueId)) { + // Copy the ACL from the old group. + secdebugfunc("integrity", "copying old ACL"); + access = new Access(*(ssGroup)); + + // We can't copy these over to the new item; they're going to be reset. + // Remove them before securityd complains. + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_PARTITION_ID); + access->removeAclsForRight(CSSM_ACL_AUTHORIZATION_INTEGRITY); + } else if (!access) { + secdebugfunc("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"; + access = new Access(printName); + + // special case for "iTools" password - allow anyone to decrypt the item + if (recordType == CSSM_DL_DB_RECORD_GENERIC_PASSWORD) + { + CssmDbAttributeData *data = mDbAttributes->find(Schema::attributeInfo(kSecServiceItemAttr)); + if (data && data->Value[0].Length == 6 && !memcmp("iTools", data->Value[0].Data, 6)) + { + typedef vector > AclSet; + AclSet acls; + access->findAclsForRight(CSSM_ACL_AUTHORIZATION_DECRYPT, acls); + for (AclSet::const_iterator it = acls.begin(); it != acls.end(); it++) + (*it)->form(ACL::allowAllForm); + } + } + } else { + secdebugfunc("integrity", "passed an Access, use it"); + // Access is non-null. Do nothing. + } + + // If we have an old group and an old mUniqueId, then we're in the middle of an update. + // mDbAttributes contains the newest attributes, but not the old ones. Find + // them, merge them, and shove them all back into mDbAttributes. This lets + // us re-apply them all to the new item. + if(haveOldUniqueId) { + mDbAttributes.reset(getCurrentAttributes()); + } + + // Create a CSPDL transaction. Note that this does things when it goes out of scope. + CSPDLTransaction transaction(db); + + Access::Maker maker; + ResourceControlContext prototype; + maker.initialOwner(prototype, nullCred); + + if(saveToNewSSGroup) { + secdebugfunc("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"); + mUniqueId->deleteRecord(); + mUniqueId.release(); + } else { + secdebugfunc("integrity", "no old mUniqueId"); + } + + // Create a new SSGroup with temporary access controls + SSGroup newSSGroup(ssDb, &prototype); + const AccessCredentials * cred = maker.cred(); + + try { + doChange(keychain, recordType, ^{ + mUniqueId = ssDb->insert(recordType, mDbAttributes.get(), + newdata, newSSGroup, cred); + }); + + // now finalize the access controls on the group + addIntegrity(*access); + access->setAccess(*newSSGroup, maker); + + // We have to reset this after we add the integrity, since it needs the attributes + mDbAttributes.reset(NULL); + + transaction.success(); + } + catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secdebugfunc("integrity", "caught CssmError during add: %d %s", (int) cssme.error, errStr); + newSSGroup->deleteKey(nullCred); + throw; + } + catch (MacOSError mose) { + secdebugfunc("integrity", "caught MacOSError during add: %d", (int) mose.osStatus()); + newSSGroup->deleteKey(nullCred); + throw; + } + catch (...) + { + secdebugfunc("integrity", "caught unknown exception during add"); + // Delete the new SSGroup that we just created + newSSGroup->deleteKey(nullCred); + throw; + } + } else { + // Modify the old SSGroup + secdebugfunc("integrity", "modifying the existing SSGroup"); + + try { + doChange(keychain, recordType, ^{ + assert(!newdata); + const AccessCredentials *autoPrompt = globals().itemCredentials(); + ssUniqueId->modify(recordType, + mDbAttributes.get(), + newdata, + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE, + autoPrompt); + }); + + // Update the integrity on the SSGroup + setIntegrity(*ssGroup); + + // We have to reset this after we add the integrity, since it needs the attributes + mDbAttributes.reset(NULL); + + transaction.success(); + } + catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secdebugfunc("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()); + throw; + } + catch (...) + { + secdebugfunc("integrity", "caught unknown exception during modify"); + throw; + } + + } +} + +void +ItemImpl::doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryChange) ()) +{ + // Insert the record using the newly created group. + try { + tryChange(); + } catch (CssmError cssme) { + // If there's a "duplicate" of this item, it might be an item with corrupt/invalid attributes + // Try to extract the item and check its attributes, then try again if necessary + auto_ptr primaryKeyAttrs; + if(cssme.error == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) { + secdebugfunc("integrity", "possible duplicate, trying to delete invalid items"); + + Keychain kc = (keychain ? keychain : mKeychain); + if(!kc) { + secdebugfunc("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"); + throw; + } else { + primaryKeyAttrs.reset(getCurrentAttributes()); + PrimaryKey pk = kc->makePrimaryKey(recordType, primaryKeyAttrs.get()); + + bool tryAgain = false; + + // Because things are lazy, maybe our keychain has a version + // of this item with different attributes. Ask it! + ItemImpl* maybeItem = kc->_lookupItem(pk); + if(maybeItem) { + if(!maybeItem->checkIntegrity()) { + Item item(maybeItem); + kc->deleteItem(item); + tryAgain = true; + } + } else { + // 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"); + CssmClient::DbCursor cursor = pk->createCursor(kc); + DbUniqueRecord uniqueId; + + StLock _mutexLocker(*kc->getKeychainMutex()); + + // The item on-disk might have more or different attributes than we do, since we're + // only searching via primary key. Fetch all of its attributes. + auto_ptrdbDupAttributes (new DbAttributes(kc->database(), 1)); + fillDbAttributesFromSchema(*dbDupAttributes, recordType, kc); + + // 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..."); + + SSGroup group = safer_cast(*uniqueId).group(); + if(!ItemImpl::checkIntegrityFromDictionary(*group, dbDupAttributes.get())) { + secdebugfunc("integrity", "item is invalid! deleting..."); + uniqueId->deleteRecord(); + tryAgain = true; + } + } + } + + if(tryAgain) { + secdebugfunc("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"); + throw; + } + } + } else { + throw; + } + } +} + void ItemImpl::getClass(SecKeychainAttribute &attr, UInt32 *actualLength) { diff --git a/OSX/libsecurity_keychain/lib/Item.h b/OSX/libsecurity_keychain/lib/Item.h index ff1e205a..26d7d7f2 100644 --- a/OSX/libsecurity_keychain/lib/Item.h +++ b/OSX/libsecurity_keychain/lib/Item.h @@ -81,12 +81,38 @@ public: PrimaryKey addWithCopyInfo(Keychain &keychain, bool isCopy); Mutex* getMutexForObject(); + // Return true iff the item integrity has not been compromised. + virtual bool checkIntegrity(); + bool checkIntegrity(AclBearer& key); + static bool checkIntegrityFromDictionary(AclBearer& key, DbAttributes* dbAttributes); + protected: // Methods called by KeychainImpl; // Add the receiver to keychain virtual PrimaryKey add(Keychain &keychain); + // Prepare a dbAttributes to extract all possible attributes with a call to + // getContent. + void fillDbAttributesFromSchema(DbAttributes& dbAttributes, CSSM_DB_RECORDTYPE recordType, Keychain keychain = NULL); + + // Get all current attributes of this item. This will call out to the + // database (if there is one) and then overly the current pending updates. + // You must delete the returned object. + DbAttributes* getCurrentAttributes(); + + // Return a canonical form of this item's attributes + void encodeAttributes(CssmOwnedData &attributeBlob); + + // Return a canonical form of the attributes passed in + static void encodeAttributesFromDictionary(CssmOwnedData &attributeBlob, DbAttributes* dbAttributes); + + // Return a canonical digest of the record type and attributes of the item + void computeDigest(CssmOwnedData &sha2); + + // Return a canonical digest of the record type and attributes passed in + static void computeDigestFromDictionary(CssmOwnedData &sha2, DbAttributes* dbAttributes); + // Get the default value for an attribute static const CSSM_DATA &defaultAttributeValue(const CSSM_DB_ATTRIBUTE_INFO &info); @@ -163,6 +189,25 @@ public: bool mayDelete(); protected: + + /* Saves the item with a new SSGroup and ACL. If you pass in an old SSGroup, + * 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); + + void doChange(Keychain keychain, CSSM_DB_RECORDTYPE recordType, void (^tryChange) () ); + + // Add integrity acl entry to access. + void addIntegrity(Access &access, bool force = false); + + // Set the integrity of this item to whatever my attributes are now + // If force, then perform this even if the underlying keychain claims to not + // support it. (This is needed because during an upgrade, the underlying + // keychain is confused about its actual version until it's written to disk.) + virtual void setIntegrity(bool force = false); + + // Set the integrity of this bearer to be whatever my attributes are now + virtual void setIntegrity(AclBearer &bearer, bool force = false); + // 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 fc968cfc..1c0cdb9d 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.cpp +++ b/OSX/libsecurity_keychain/lib/KCCursor.cpp @@ -36,6 +36,7 @@ #include "StorageManager.h" #include #include +#include using namespace KeychainCore; using namespace CssmClient; @@ -58,7 +59,9 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, SecIt mSearchList(searchList), mCurrent(mSearchList.begin()), mAllFailed(true), - mMutex(Mutex::recursive) + mDeleteInvalidRecords(false), + mMutex(Mutex::recursive), + mKeychainReadLock(NULL) { recordType(Schema::recordTypeFor(itemClass)); @@ -113,7 +116,9 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const mSearchList(searchList), mCurrent(mSearchList.begin()), mAllFailed(true), - mMutex(Mutex::recursive) + mDeleteInvalidRecords(false), + mMutex(Mutex::recursive), + mKeychainReadLock(NULL) { if (!attrList) // No additional selectionPredicates: we are done return; @@ -167,6 +172,9 @@ KCCursorImpl::KCCursorImpl(const StorageManager::KeychainList &searchList, const KCCursorImpl::~KCCursorImpl() throw() { + if(mKeychainReadLock) { + delete mKeychainReadLock; + } } //static ModuleNexus gActivationMutex; @@ -179,120 +187,192 @@ 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 (;;) { - while (!mDbCursor) - { - if (mCurrent == mSearchList.end()) - { - // If we got always failed when calling mDbCursor->next return the error from - // the last call to mDbCursor->next now - if (mAllFailed && status) - CssmError::throwMe(status); - - // No more keychains to search so we are done. - return false; - } - - try - { - // StLock _(gActivationMutex()); // force serialization of cursor creation - Keychain &kc = *mCurrent; - Mutex* mutex = kc->getKeychainMutex(); - StLock _(*mutex); - (*mCurrent)->database()->activate(); - mDbCursor = DbCursor((*mCurrent)->database(), *this); - } - catch(const CommonError &err) - { - ++mCurrent; - } - } + Item tempItem = NULL; + { + if(isNewKeychain) { + newKeychain(mCurrent); + isNewKeychain = false; + } - Keychain &kc = *mCurrent; - Mutex* mutex = kc->getKeychainMutex(); - StLock _(*mutex); - - bool gotRecord; - try - { - // Clear out existing attributes first! - // (the previous iteration may have left attributes from a different schema) - dbAttributes.clear(); + while (!mDbCursor) + { + // Do the newKeychain dance before we check our done status + newKeychain(mCurrent); - gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId); - mAllFailed = false; - } - catch(const CommonError &err) - { - // Catch the last error we get and move on to the next keychain - // This error will be returned when we reach the end of our keychain list - // iff all calls to KCCursorImpl::next failed - status = err.osStatus(); - gotRecord = false; - dbAttributes.invalidate(); - } - catch(...) - { - // Catch all other errors - status = errSecItemNotFound; - gotRecord = false; - } + if (mCurrent == mSearchList.end()) + { + // If we got always failed when calling mDbCursor->next return the error from + // the last call to mDbCursor->next now + if (mAllFailed && status) + CssmError::throwMe(status); - // If we did not get a record from the current keychain or the current - // keychain did not exist skip to the next keychain in the list. - if (!gotRecord) - { - ++mCurrent; - mDbCursor = DbCursor(); - continue; - } + // No more keychains to search so we are done. + return false; + } + + try + { + // StLock _(gActivationMutex()); // force serialization of cursor creation + Keychain &kc = *mCurrent; + Mutex* mutex = kc->getKeychainMutex(); + StLock _(*mutex); + (*mCurrent)->database()->activate(); + mDbCursor = DbCursor((*mCurrent)->database(), *this); + } + catch(const CommonError &err) + { + ++mCurrent; + } + } + + Keychain &kc = *mCurrent; + Mutex* mutex = kc->getKeychainMutex(); + StLock _(*mutex); + + bool gotRecord; + try + { + // Clear out existing attributes first! + // (the previous iteration may have left attributes from a different schema) + dbAttributes.clear(); + + gotRecord = mDbCursor->next(&dbAttributes, NULL, uniqueId); + mAllFailed = false; + } + catch(const CommonError &err) + { + // Catch the last error we get and move on to the next keychain + // This error will be returned when we reach the end of our keychain list + // iff all calls to KCCursorImpl::next failed + status = err.osStatus(); + gotRecord = false; + dbAttributes.invalidate(); + } + catch(...) + { + // Catch all other errors + status = errSecItemNotFound; + gotRecord = false; + } - // If doing a search for all records, skip the db blob added by the CSPDL - if (dbAttributes.recordType() == CSSM_DL_DB_RECORD_METADATA && - mDbCursor->recordType() == CSSM_DL_DB_RECORD_ANY) + // If we did not get a record from the current keychain or the current + // keychain did not exist skip to the next keychain in the list. + if (!gotRecord) + { + ++mCurrent; + mDbCursor = DbCursor(); + // 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; continue; - - // Filter out group keys at this layer - if (dbAttributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) - { - bool groupKey = false; - try - { - // fetch the key label attribute, if it exists - dbAttributes.add(KeySchema::Label); - Db db((*mCurrent)->database()); - CSSM_RETURN getattr_result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), uniqueId, &dbAttributes, NULL); - if (getattr_result == CSSM_OK) - { - CssmDbAttributeData *label = dbAttributes.find(KeySchema::Label); - CssmData attrData; - if (label) - attrData = *label; - if (attrData.length() > 4 && !memcmp(attrData.data(), "ssgp", 4)) - groupKey = true; - } - else + } + + // If doing a search for all records, skip the db blob added by the CSPDL + if (dbAttributes.recordType() == CSSM_DL_DB_RECORD_METADATA && + mDbCursor->recordType() == CSSM_DL_DB_RECORD_ANY) + continue; + + // Filter out group keys at this layer + if (dbAttributes.recordType() == CSSM_DL_DB_RECORD_SYMMETRIC_KEY) + { + bool groupKey = false; + try { - dbAttributes.invalidate(); + // fetch the key label attribute, if it exists + dbAttributes.add(KeySchema::Label); + Db db((*mCurrent)->database()); + CSSM_RETURN getattr_result = CSSM_DL_DataGetFromUniqueRecordId(db->handle(), uniqueId, &dbAttributes, NULL); + if (getattr_result == CSSM_OK) + { + CssmDbAttributeData *label = dbAttributes.find(KeySchema::Label); + CssmData attrData; + if (label) + attrData = *label; + if (attrData.length() > 4 && !memcmp(attrData.data(), "ssgp", 4)) + groupKey = true; + } + else + { + dbAttributes.invalidate(); + } } - } - catch (...) {} + catch (...) {} - if (groupKey) - continue; + if (groupKey) + continue; + } + + // Create the Item + // Go though Keychain since item might already exist. + // This might throw a CSSMERR_DL_RECORD_NOT_FOUND or be otherwise invalid. If we're supposed to delete these items, delete them... + try { + tempItem = (*mCurrent)->item(dbAttributes.recordType(), uniqueId); + } 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; + } + } } + // 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; } - // Go though Keychain since item might already exist. - Keychain &kc = *mCurrent; - StLock _mutexLocker(*kc->getKeychainMutex()); - item = (*mCurrent)->item(dbAttributes.recordType(), uniqueId); + // If we reach here, we've found an item return true; } +void KCCursorImpl::deleteInvalidRecord(DbUniqueRecord& uniqueId) { + // This might throw a RECORD_NOT_FOUND. Handle that, because we don't care if we're trying to delete the item. + try { + uniqueId->deleteRecord(); + } catch(CssmError delcssme) { + if (delcssme.osStatus() == CSSMERR_DL_RECORD_NOT_FOUND) { + secdebugfunc("integrity", "couldn't delete nonexistent record (this is okay)"); + } else { + throw; + } + } +} + bool KCCursorImpl::mayDelete() @@ -306,3 +386,22 @@ bool KCCursorImpl::mayDelete() return true; } } + +void KCCursorImpl::setDeleteInvalidRecords(bool deleteRecord) { + mDeleteInvalidRecords = deleteRecord; +} + +void KCCursorImpl::newKeychain(StorageManager::KeychainList::iterator kcIter) { + // Always lose the last keychain's lock + if(mKeychainReadLock) { + delete mKeychainReadLock; + mKeychainReadLock = NULL; + } + + if(kcIter != mSearchList.end()) { + (*kcIter)->performKeychainUpgradeIfNeeded(); + + // Grab a read lock on the keychain + mKeychainReadLock = new StReadWriteLock(*((*kcIter)->getKeychainReadWriteLock()), StReadWriteLock::Read); + } +} diff --git a/OSX/libsecurity_keychain/lib/KCCursor.h b/OSX/libsecurity_keychain/lib/KCCursor.h index a05db8e7..c65bf060 100644 --- a/OSX/libsecurity_keychain/lib/KCCursor.h +++ b/OSX/libsecurity_keychain/lib/KCCursor.h @@ -50,15 +50,38 @@ public: virtual ~KCCursorImpl() throw(); bool next(Item &item); bool mayDelete(); - + + // Occasionally, you might end up with a keychain where finding a record + // might return CSSMERR_DL_RECORD_NOT_FOUND. This is usually due to having a + // existing SSGroup element whose matching SSGroup key has been deleted. + // + // You might also have invalid ACLs or records with bad MACs. + // + // If you set this to true, this KCCursor will silently suppress errors when + // creating items, and try to delete these corrupt records. + void setDeleteInvalidRecords(bool deleteRecord); + private: StorageManager::KeychainList mSearchList; StorageManager::KeychainList::iterator mCurrent; CssmClient::DbCursor mDbCursor; bool mAllFailed; + bool mDeleteInvalidRecords; protected: Mutex mMutex; + StReadWriteLock* mKeychainReadLock; + + // Call this every time we switch to a new keychain + // Will: + // 1. handle the read locks on the new keychain and the old one + // 2. Try to upgrade the new keychain if needed and possible + // Handles the end iterator. + void newKeychain(StorageManager::KeychainList::iterator kcIter); + + // Try to delete a record. Silently swallow any RECORD_NOT_FOUND exceptions, + // but throw others upward. + void deleteInvalidRecord(DbUniqueRecord& uniqueId); }; diff --git a/OSX/libsecurity_keychain/lib/KeyItem.cpp b/OSX/libsecurity_keychain/lib/KeyItem.cpp index 69e7f919..0fe303ba 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.cpp +++ b/OSX/libsecurity_keychain/lib/KeyItem.cpp @@ -33,11 +33,13 @@ #include #include #include +#include #include #include "KCEventNotifier.h" #include #include +#include // @@@ This needs to be shared. #pragma clang diagnostic push @@ -110,7 +112,16 @@ KeyItem::~KeyItem() void KeyItem::update() { - ItemImpl::update(); + //Create a new CSPDLTransaction + Db db(mKeychain->database()); + CSPDLTransaction transaction(db); + + ItemImpl::update(); + + /* Update integrity on key */ + setIntegrity(); + + transaction.success(); } Item @@ -221,7 +232,8 @@ KeyItem::copyTo(const Keychain &keychain, Access *newAccess) throw; } - /* Set the acl and owner on the unwrapped key. */ + /* Set the acl and owner on the unwrapped key. */ + addIntegrity(*access); access->setAccess(*unwrappedKey, maker); /* Return a keychain item which represents the new key. */ @@ -321,9 +333,6 @@ KeyItem::importTo(const Keychain &keychain, Access *newAccess, SecKeychainAttrib // Set the initial label, application label, and application tag (if provided) if (attrList) { DbAttributes newDbAttributes; - SSDbCursor otherDbCursor(ssDb, 1); - otherDbCursor->recordType(recordType()); - bool checkForDuplicates = false; for (UInt32 index=0; index < attrList->count; index++) { SecKeychainAttribute attr = attrList->attr[index]; @@ -333,35 +342,17 @@ KeyItem::importTo(const Keychain &keychain, Access *newAccess, SecKeychainAttrib } if (attr.tag == kSecKeyLabel) { newDbAttributes.add(kInfoKeyLabel, attrData); - otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, attrData); - checkForDuplicates = true; } if (attr.tag == kSecKeyApplicationTag) { newDbAttributes.add(kInfoKeyApplicationTag, attrData); - otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, attrData); - checkForDuplicates = true; } } - DbAttributes otherDbAttributes; - DbUniqueRecord otherUniqueId; - CssmClient::Key otherKey; - try - { - if (checkForDuplicates && otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId)) - MacOSError::throwMe(errSecDuplicateItem); - - uniqueId->modify(recordType(), &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); - } - catch (CssmError e) - { - // clean up after trying to insert a duplicate key - uniqueId->deleteRecord (); - throw; - } + modifyUniqueId(keychain, ssDb, uniqueId, newDbAttributes, recordType()); } /* Set the acl and owner on the unwrapped key. */ + addIntegrity(*access); access->setAccess(*unwrappedKey, maker); /* Return a keychain item which represents the new key. */ @@ -573,7 +564,7 @@ KeyItem::createPair( CSSM_CC_HANDLE ccHandle = 0; - Item publicKeyItem, privateKeyItem; + SecPointer publicKeyItem, privateKeyItem; try { CSSM_RETURN status; @@ -661,19 +652,29 @@ KeyItem::createPair( // Set the PrintName of the public key to the description in the acl. pubDbAttributes.add(kInfoKeyLabel, pubKeyHash); pubDbAttributes.add(kInfoKeyPrintName, *pubDescription); - pubUniqueId->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY, &pubDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + modifyUniqueId(keychain, ssDb, pubUniqueId, pubDbAttributes, CSSM_DL_DB_RECORD_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); - privUniqueId->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY, &privDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + modifyUniqueId(keychain, ssDb, privUniqueId, privDbAttributes, CSSM_DL_DB_RECORD_PRIVATE_KEY); // @@@ Not exception safe! csp.allocator().free(cssmData->Data); csp.allocator().free(cssmData); + // 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 (!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); if(publicKeyAttr & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) { @@ -684,28 +685,12 @@ KeyItem::createPair( * CDSA-specified behavior). */ SecPointer pubKeyAccess(new Access()); + publicKeyItem->addIntegrity(*pubKeyAccess); pubKeyAccess->setAccess(*publicKey, maker); } - // Create keychain items which will represent the keys. - publicKeyItem = keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId); - privateKeyItem = keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId); - - KeyItem* impl = dynamic_cast(&(*publicKeyItem)); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - outPublicKey = impl; - - impl = dynamic_cast(&(*privateKeyItem)); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - outPrivateKey = impl; + outPublicKey = publicKeyItem; + outPrivateKey = privateKeyItem; } catch (...) { @@ -781,7 +766,7 @@ KeyItem::importPair( CSSM_CC_HANDLE ccHandle = 0; - Item publicKeyItem, privateKeyItem; + SecPointer publicKeyItem, privateKeyItem; try { CSSM_RETURN status; @@ -896,38 +881,33 @@ KeyItem::importPair( // 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(kInfoKeyPrintName, *pubDescription); - pubUniqueId->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY, &pubDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + modifyUniqueId(keychain, ssDb, pubUniqueId, pubDbAttributes, CSSM_DL_DB_RECORD_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(kInfoKeyPrintName, *privDescription); - privUniqueId->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY, &privDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + modifyUniqueId(keychain, ssDb, privUniqueId, privDbAttributes, CSSM_DL_DB_RECORD_PRIVATE_KEY); - // Finally fix the acl and owner of the private key to the specified access control settings. + // 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 (!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); // Make the public key acl completely open SecPointer pubKeyAccess(new Access()); + publicKeyItem->addIntegrity(*pubKeyAccess); pubKeyAccess->setAccess(*publicKey, maker); - // Create keychain items which will represent the keys. - publicKeyItem = keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId); - privateKeyItem = keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId); - - KeyItem* impl = dynamic_cast(&(*publicKeyItem)); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - outPublicKey = impl; - - impl = dynamic_cast(&(*privateKeyItem)); - if (impl == NULL) - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - outPrivateKey = impl; + outPublicKey = publicKeyItem; + outPrivateKey = privateKeyItem; } catch (...) { @@ -952,8 +932,8 @@ KeyItem::importPair( if (keychain && publicKeyItem && privateKeyItem) { - KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, publicKeyItem); - KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, privateKeyItem); + KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, Item(publicKeyItem)); + KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, Item(privateKeyItem)); } } @@ -1005,7 +985,10 @@ KeyItem::generateWithAttributes(const SecKeychainAttributeList *attrList, ResourceControlContext *prcc = NULL, rcc; const AccessCredentials *cred = NULL; Access::Maker maker; - if (keychain && initialAccess) + + + + if (keychain) { memset(&rcc, 0, sizeof(rcc)); // @@@ Potentially provide a credential argument which allows us to generate keys in the csp. @@ -1015,13 +998,18 @@ KeyItem::generateWithAttributes(const SecKeychainAttributeList *attrList, // Create the cred we need to manipulate the keys until we actually set a new access control for them. cred = maker.cred(); prcc = &rcc; - } + + if (!initialAccess) { + // We don't have an access, but we need to set integrity. Make an Access. + initialAccess = new Access(string(label)); + } + } CSSM_KEY cssmKey; CSSM_CC_HANDLE ccHandle = 0; - Item keyItem; + SecPointer keyItem; try { CSSM_RETURN status; @@ -1071,9 +1059,6 @@ KeyItem::generateWithAttributes(const SecKeychainAttributeList *attrList, // Set the initial label, application label, and application tag (if provided) if (attrList) { DbAttributes newDbAttributes; - SSDbCursor otherDbCursor(ssDb, 1); - otherDbCursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY); - bool checkForDuplicates = false; for (UInt32 index=0; index < attrList->count; index++) { SecKeychainAttribute attr = attrList->attr[index]; @@ -1083,31 +1068,21 @@ KeyItem::generateWithAttributes(const SecKeychainAttributeList *attrList, } if (attr.tag == kSecKeyLabel) { newDbAttributes.add(kInfoKeyLabel, attrData); - otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, attrData); - checkForDuplicates = true; } if (attr.tag == kSecKeyApplicationTag) { newDbAttributes.add(kInfoKeyApplicationTag, attrData); - otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, attrData); - checkForDuplicates = true; } } - DbAttributes otherDbAttributes; - DbUniqueRecord otherUniqueId; - CssmClient::Key otherKey; - if (checkForDuplicates && otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId)) - MacOSError::throwMe(errSecDuplicateItem); - - uniqueId->modify(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); - } + modifyUniqueId(keychain, ssDb, uniqueId, newDbAttributes, CSSM_DL_DB_RECORD_SYMMETRIC_KEY); + } - // Finally, fix the acl and owner of the key to the specified access control settings. - if (initialAccess) - initialAccess->setAccess(*key, maker); + // Create keychain item which will represent the key. + keyItem = dynamic_cast(keychain->item(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueId).get()); - // Create keychain item which will represent the key. - keyItem = keychain->item(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueId); + // Finally, fix the acl and owner of the key to the specified access control settings. + keyItem->addIntegrity(*initialAccess); + initialAccess->setAccess(*key, maker); } else { @@ -1418,3 +1393,97 @@ CFHashCode KeyItem::hash() return result; } +void KeyItem::setIntegrity(bool force) { + ItemImpl::setIntegrity(*key(), force); +} + +bool KeyItem::checkIntegrity() { + if(!isPersistent()) { + return true; + } + + return ItemImpl::checkIntegrity(*key()); +} + +// KeyItems are a little bit special: the only modifications you can do to them +// is to change their Print Name, Label, or Application Tag. +// +// When we do this modification, we need to look ahead to see if there's an item +// that's already there. If there are, we're going to throw a errSecDuplicateItem. +// +// Unless that item doesn't pass the integrity check, in which case we delete it +// and continue with the add. +void KeyItem::modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqueId, DbAttributes& newDbAttributes, CSSM_DB_RECORDTYPE recordType) { + SSDbCursor otherDbCursor(ssDb, 1); + otherDbCursor->recordType(recordType); + + bool checkForDuplicates = false; + // Set up the ssdb cursor + CssmDbAttributeData* label = newDbAttributes.findAttribute(kInfoKeyLabel); + if(label) { + otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label->at(0)); + checkForDuplicates = true; + } + CssmDbAttributeData* apptag = newDbAttributes.findAttribute(kInfoKeyApplicationTag); + if(apptag) { + otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, apptag->at(0)); + checkForDuplicates = true; + } + + // 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"); + checkForDuplicates = false; + } + + if (checkForDuplicates) { + secdebugfunc("integrity", "looking for duplicates"); + // If there are duplicates that are invalid, delete it and + // continue. Otherwise, if there are duplicates, throw errSecDuplicateItem. + DbAttributes otherDbAttributes; + DbUniqueRecord otherUniqueId; + CssmClient::Key otherKey; + + while(otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId)) { + secdebugfunc("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"); + MacOSError::throwMe(errSecDuplicateItem); + } else { + secdebugfunc("integrity", "existing duplicate item is invalid, removing..."); + Item item(maybeItem); + keychain->deleteItem(item); + } + } else { + KeyItem temp(keychain, pk, otherUniqueId); + + if(temp.checkIntegrity()) { + secdebugfunc("integrity", "duplicate is real, throwing error"); + MacOSError::throwMe(errSecDuplicateItem); + } else { + secdebugfunc("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(); + keychain->removeItem(temp.primaryKey(), &temp); + } + } + } + } + + try { + secdebugfunc("integrity", "modifying unique id"); + uniqueId->modify(recordType, &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + secdebugfunc("integrity", "done modifying unique id"); + } catch(CssmError e) { + // Just in case something went wrong, clean up after this add + uniqueId->deleteRecord(); + throw; + } +} diff --git a/OSX/libsecurity_keychain/lib/KeyItem.h b/OSX/libsecurity_keychain/lib/KeyItem.h index 9ac071d1..56776933 100644 --- a/OSX/libsecurity_keychain/lib/KeyItem.h +++ b/OSX/libsecurity_keychain/lib/KeyItem.h @@ -126,6 +126,11 @@ public: virtual CFHashCode hash(); + virtual void setIntegrity(bool force = false); + virtual bool checkIntegrity(); + + static void modifyUniqueId(Keychain keychain, SSDb ssDb, DbUniqueRecord& uniqueId, DbAttributes& newDbAttributes, CSSM_DB_RECORDTYPE recordType); + protected: virtual PrimaryKey add(Keychain &keychain); private: diff --git a/OSX/libsecurity_keychain/lib/Keychains.cpp b/OSX/libsecurity_keychain/lib/Keychains.cpp index 1d94dee2..de34f0b4 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.cpp +++ b/OSX/libsecurity_keychain/lib/Keychains.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "SecKeychainPriv.h" @@ -393,7 +395,8 @@ static void check_system_keychain() // KeychainImpl // KeychainImpl::KeychainImpl(const Db &db) - : mInCache(false), mDb(db), mCustomUnlockCreds (this), mIsInBatchMode (false), mMutex(Mutex::recursive) + : mAttemptedUpgrade(false), mDbItemMapMutex(Mutex::recursive), mDbDeletedItemMapMutex(Mutex::recursive), + mInCache(false), mDb(db), mCustomUnlockCreds (this), mIsInBatchMode (false), mMutex(Mutex::recursive) { dispatch_once(&SecKeychainSystemKeychainChecked, ^{ check_system_keychain(); @@ -428,6 +431,12 @@ KeychainImpl::getKeychainMutex() return &mMutex; } +ReadWriteLock* +KeychainImpl::getKeychainReadWriteLock() +{ + return &mRWLock; +} + void KeychainImpl::aboutToDestruct() { // remove me from the global cache, we are done @@ -766,26 +775,26 @@ void KeychainImpl::completeAdd(Item &inItem, PrimaryKey &primaryKey) // Insert inItem into mDbItemMap with key primaryKey. p.second will be // true if it got inserted. If not p.second will be false and p.first // will point to the current entry with key primaryKey. + StLock _(mDbItemMapMutex); pair p = mDbItemMap.insert(DbItemMap::value_type(primaryKey, inItem.get())); if (!p.second) { // There was already an ItemImpl * in mDbItemMap with key - // primaryKey. Get a ref to the pointer to it so we can assign a - // new value to it below. + // primaryKey. Remove it, and try the add again. ItemImpl *oldItem = p.first->second; - // @@@ If this happens we are breaking our API contract of + // @@@ If this happens we are breaking our API contract of // 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. - assert(oldItem->inCache()); secdebug("keychain", "add of new item %p somehow replaced %p", inItem.get(), oldItem); - - // make sure that we both mark the item and remove the item from the cache - removeItem(oldItem->primaryKey(), oldItem); - oldItem = inItem.get(); + + mDbItemMap.erase(p.first); + oldItem->inCache(false); + forceRemoveFromCache(oldItem); + mDbItemMap.insert(DbItemMap::value_type(primaryKey, inItem.get())); } inItem->inCache(true); @@ -820,6 +829,7 @@ KeychainImpl::didUpdate(const Item &inItem, PrimaryKey &oldPK, assert(inItem->inCache()); if (inItem->inCache()) { + StLock _(mDbItemMapMutex); // First remove the entry for inItem in mDbItemMap with key oldPK. DbItemMap::iterator it = mDbItemMap.find(oldPK); if (it != mDbItemMap.end() && (ItemImpl*) it->second == inItem.get()) @@ -833,24 +843,27 @@ KeychainImpl::didUpdate(const Item &inItem, PrimaryKey &oldPK, if (!p.second) { // There was already an ItemImpl * in mDbItemMap with key - // primaryKey. Get a ref to the pointer to it so we can assign - // a new value to it below. + // primaryKey. Remove it, and try the add again. ItemImpl *oldItem = p.first->second; - // @@@ If this happens we are breaking our API contract of + // @@@ If this happens we are breaking our API contract of // 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. - assert(oldItem->inCache()); secdebug("keychain", "update of item %p somehow replaced %p", inItem.get(), oldItem); - oldItem->inCache(false); - oldItem = inItem.get(); + + mDbItemMap.erase(p.first); + oldItem->inCache(false); + forceRemoveFromCache(oldItem); + mDbItemMap.insert(DbItemMap::value_type(newPK, inItem.get())); } } } - - postEvent(kSecUpdateEvent, inItem); + + // Item updates now are technically a delete and re-add, so post these events instead of kSecUpdateEvent + postEvent(kSecDeleteEvent, inItem); + postEvent(kSecAddEvent, inItem); } void @@ -865,15 +878,29 @@ KeychainImpl::deleteItem(Item &inoutItem) if (!inoutItem->isPersistent()) MacOSError::throwMe(errSecInvalidItemRef); + secdebug("kcnotify", "starting deletion of item %p", inoutItem.get()); + DbUniqueRecord uniqueId = inoutItem->dbUniqueRecord(); PrimaryKey primaryKey = inoutItem->primaryKey(); uniqueId->deleteRecord(); - // Don't remove the item from the mDbItemMap here since this would cause - // us to report a new item to our caller when we receive the - // kSecDeleteEvent notification. - // It will be removed before we post the notification, because - // CCallbackMgr will call didDeleteItem() + // Move the item from mDbItemMap to mDbDeletedItemMap. We need the item + // to give to the client process when we receive the kSecDeleteEvent + // notification, but if that notification never arrives, we don't want + // the item hanging around. When didDeleteItem is called by CCallbackMgr, + // we'll remove all traces of the item. + + if (inoutItem->inCache()) { + StLock _(mDbItemMapMutex); + StLock __(mDbDeletedItemMapMutex); + // Only look for it if it's in the cache + DbItemMap::iterator it = mDbItemMap.find(primaryKey); + + if (it != mDbItemMap.end() && (ItemImpl*) it->second == inoutItem.get()) { + mDbDeletedItemMap.insert(DbItemMap::value_type(primaryKey, it->second)); + mDbItemMap.erase(it); + } + } // Post the notification for the item deletion with // the primaryKey obtained when the item still existed @@ -922,6 +949,26 @@ KeychainImpl::makePrimaryKey(CSSM_DB_RECORDTYPE recordType, DbUniqueRecord &uniq return PrimaryKey(primaryKeyAttrs); } +PrimaryKey +KeychainImpl::makePrimaryKey(CSSM_DB_RECORDTYPE recordType, DbAttributes* currentAttributes) +{ + StLock_(mMutex); + + DbAttributes primaryKeyAttrs; + primaryKeyAttrs.recordType(recordType); + gatherPrimaryKeyAttributes(primaryKeyAttrs); + + for(int i = 0; i < primaryKeyAttrs.size(); i++) { + CssmDbAttributeData& attr = primaryKeyAttrs[i]; + + CssmDbAttributeData * actual = currentAttributes->find(attr.info()); + if(actual) { + attr.set(*actual, Allocator::standard()); + } + } + return PrimaryKey(primaryKeyAttrs); +} + const CssmAutoDbRecordAttributeInfo & KeychainImpl::primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) { @@ -947,7 +994,7 @@ KeychainImpl::primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType) void KeychainImpl::gatherPrimaryKeyAttributes(DbAttributes& primaryKeyAttrs) { - StLock_(mMutex); + StLock _(mMutex); const CssmAutoDbRecordAttributeInfo &infos = primaryKeyInfosFor(primaryKeyAttrs.recordType()); @@ -960,23 +1007,28 @@ void KeychainImpl::gatherPrimaryKeyAttributes(DbAttributes& primaryKeyAttrs) ItemImpl * KeychainImpl::_lookupItem(const PrimaryKey &primaryKey) { + StLock _(mDbItemMapMutex); DbItemMap::iterator it = mDbItemMap.find(primaryKey); if (it != mDbItemMap.end()) { - if (it->second == NULL) - { - // we've been weak released... - mDbItemMap.erase(it); - } - else - { - return it->second; - } + return it->second; } return NULL; } +ItemImpl * +KeychainImpl::_lookupDeletedItemOnly(const PrimaryKey &primaryKey) +{ + DbItemMap::iterator it = mDbDeletedItemMap.find(primaryKey); + if (it != mDbDeletedItemMap.end()) + { + return it->second; + } + + return NULL; +} + Item KeychainImpl::item(const PrimaryKey &primaryKey) { @@ -984,8 +1036,9 @@ KeychainImpl::item(const PrimaryKey &primaryKey) // Lookup the item in the map while holding the apiLock. ItemImpl *itemImpl = _lookupItem(primaryKey); - if (itemImpl) + if (itemImpl) { return Item(itemImpl); + } try { @@ -1010,6 +1063,18 @@ KeychainImpl::item(const PrimaryKey &primaryKey) throw; } } +// Check for an item that may have been deleted. +Item +KeychainImpl::itemdeleted(const PrimaryKey& primaryKey) { + StLock_(mMutex); + + Item i = _lookupDeletedItemOnly(primaryKey); + if(i.get()) { + return i; + } else { + return item(primaryKey); + } +} Item @@ -1081,6 +1146,7 @@ KeychainImpl::addItem(const PrimaryKey &primaryKey, ItemImpl *dbItemImpl) // Insert dbItemImpl into mDbItemMap with key primaryKey. p.second will // be true if it got inserted. If not p.second will be false and p.first // will point to the current entry with key primaryKey. + StLock __(mDbItemMapMutex); pair p = mDbItemMap.insert(DbItemMap::value_type(primaryKey, dbItemImpl)); @@ -1115,13 +1181,66 @@ KeychainImpl::removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl) if (!inItemImpl->inCache()) return; - DbItemMap::iterator it = mDbItemMap.find(primaryKey); - if (it != mDbItemMap.end() && (ItemImpl*) it->second == inItemImpl) - mDbItemMap.erase(it); + { + StLock _(mDbItemMapMutex); + DbItemMap::iterator it = mDbItemMap.find(primaryKey); + if (it != mDbItemMap.end() && (ItemImpl*) it->second == inItemImpl) { + mDbItemMap.erase(it); + } + } // drop mDbItemMapMutex + + { + StLock _(mDbDeletedItemMapMutex); + DbItemMap::iterator it = mDbDeletedItemMap.find(primaryKey); + if (it != mDbDeletedItemMap.end() && (ItemImpl*) it->second == inItemImpl) { + mDbDeletedItemMap.erase(it); + } + } // drop mDbDeletedItemMapMutex inItemImpl->inCache(false); } +void +KeychainImpl::forceRemoveFromCache(ItemImpl* inItemImpl) { + try { + // Wrap all this in a try-block and ignore all errors - we're trying to clean up these maps + { + StLock _(mDbItemMapMutex); + for(DbItemMap::iterator it = mDbItemMap.begin(); it != mDbItemMap.end(); ) { + if(it->second == inItemImpl) { + // Increment the iterator, but use its pre-increment value for the erase + it->second->inCache(false); + mDbItemMap.erase(it++); + } else { + it++; + } + } + } // drop mDbItemMapMutex + + { + StLock _(mDbDeletedItemMapMutex); + for(DbItemMap::iterator it = mDbDeletedItemMap.begin(); it != mDbDeletedItemMap.end(); ) { + if(it->second == inItemImpl) { + // Increment the iterator, but use its pre-increment value for the erase + it->second->inCache(false); + mDbDeletedItemMap.erase(it++); + } else { + it++; + } + } + } // drop mDbDeletedItemMapMutex + } catch(UnixError ue) { + secdebugfunc("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); + } catch (MacOSError mose) { + secdebugfunc("keychain", "MacOSError: %d", (int)mose.osStatus()); + } catch(...) { + secdebugfunc("keychain", "Unknown error"); + } +} + void KeychainImpl::getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, SecKeychainAttributeInfo **Info) @@ -1264,6 +1383,213 @@ KeychainImpl::postEvent(SecKeychainEvent kcEvent, ItemImpl* item) } } + +bool KeychainImpl::performKeychainUpgradeIfNeeded() { + // Grab this keychain's mutex. This might not be sufficient, since the + // keychain might have outstanding cursors. We'll grab the RWLock later if needed. + StLock_(mMutex); + + if(!globals().integrityProtection()) { + secdebugfunc("integrity", "skipping upgrade for %s due to global integrity protection being diabled", mDb->name()); + return false; + } + + // We need a CSP database for 'upgrade' to be meaningful + if((mDb->dl()->subserviceMask() & CSSM_SERVICE_CSP) == 0) { + return false; + } + + // 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()); + return false; + } + + // If we've already attempted an upgrade on this keychain, don't bother again + if(mAttemptedUpgrade) { + return false; + } + + // 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()); + return false; + } + + uint32 dbBlobVersion = SecurityServer::DbBlob::version_MacOS_10_0; + + try { + dbBlobVersion = mDb->dbBlobVersion(); + } catch (CssmError cssme) { + 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"); + 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); + return false; + } + } catch (...) { + secdebugfunc("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); + + // 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; + } + + 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); + } + } + } catch (CssmError cssme) { + const char* errStr = cssmErrorString(cssme.error); + secdebugfunc("integrity", "caught CssmError: %d %s", (int) cssme.error, errStr); + } catch (...) { + // Something went wrong, but don't worry about it. + } + + // 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()); + + return true; + } + + return false; +} + +// 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(); + + // Let's reload this keychain to see if someone changed it on disk + globals().storageManager.reloadKeychain(this); + + if(mDb->dbBlobVersion() == newBlobVersion) { + // Someone else upgraded this, hurray! + secdebugfunc("integrity", "reloaded keychain version %d, quitting", mDb->dbBlobVersion()); + db->releaseFileLock(false); + return newBlobVersion; + } + + mAttemptedUpgrade = true; + uint32 newDbVersion = oldBlobVersion; + + try { + secdebugfunc("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(); + + 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); + return newDbVersion; + } + + secdebugfunc("integrity", "recoded db successfully, adding extra integrity"); + + Keychain keychain(db); + + // Breaking abstraction, but what're you going to do? + // 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; + + SecItemClass classes[] = {kSecGenericPasswordItemClass, + kSecInternetPasswordItemClass, + kSecPublicKeyItemClass, + kSecPrivateKeyItemClass, + kSecSymmetricKeyItemClass}; + + for(int i = 0; i < sizeof(classes) / sizeof(classes[0]); i++) { + Item item; + KCCursor kcc = keychain->createCursor(classes[i], NULL); + + // 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. Tell the KCCursor to + // delete these if found. + // This will also try to suppress any other invalid items. + kcc->setDeleteInvalidRecords(true); + + 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); + } 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"); + keychain->deleteItem(item); + } else { + throw; + } + } + } + } + + // If we reach here, tell releaseFileLock() to commit the transaction and return the new blob version + secdebugfunc("integrity", "releasing file lock"); + db->releaseFileLock(true); + + secdebugfunc("integrity", "success, returning version %d", newDbVersion); + return newDbVersion; + } + } 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); + } + + // If we reached here, we failed the migration. Return the old version. + return oldBlobVersion; +} + + Keychain::Keychain() { dispatch_once(&SecKeychainSystemKeychainChecked, ^{ @@ -1330,3 +1656,20 @@ bool KeychainImpl::mayDelete() { return true; } + +bool KeychainImpl::hasIntegrityProtection() { + // This keychain only supports integrity if there's a database attached, that database is an Apple CSPDL, and the blob version is high enough + if(mDb && (mDb->dl()->guid() == gGuidAppleCSPDL)) { + if(mDb->dbBlobVersion() >= SecurityServer::DbBlob::version_partition) { + return true; + } else { + secdebugfunc("integrity", "keychain blob version does not support integrity"); + return false; + } + } else { + secdebugfunc("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 7931313e..334cd682 100644 --- a/OSX/libsecurity_keychain/lib/Keychains.h +++ b/OSX/libsecurity_keychain/lib/Keychains.h @@ -120,6 +120,9 @@ public: friend class Keychain; friend class ItemImpl; + friend class KeyItem; + friend class KCCursorImpl; + friend class StorageManager; protected: KeychainImpl(const CssmClient::Db &db); @@ -134,6 +137,8 @@ public: Mutex* getKeychainMutex(); Mutex* getMutexForObject(); + + ReadWriteLock* getKeychainReadWriteLock(); void aboutToDestruct(); bool operator ==(const KeychainImpl &) const; @@ -178,12 +183,15 @@ public: KCCursor createCursor(const SecKeychainAttributeList *attrList); KCCursor createCursor(SecItemClass itemClass, const SecKeychainAttributeList *attrList); - CssmClient::Db database() { return mDb; } + CssmClient::Db database() { StLock_(mDbMutex); return mDb; } DLDbIdentifier dlDbIdentifier() const { return mDb->dlDbIdentifier(); } CssmClient::CSP csp(); PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); + + // This will make a primary key for this record type, and populate it completely from the given attributes + PrimaryKey makePrimaryKey(CSSM_DB_RECORDTYPE recordType, CssmClient::DbAttributes *currentAttributes); void gatherPrimaryKeyAttributes(CssmClient::DbAttributes& primaryKeyAttrs); const CssmAutoDbRecordAttributeInfo &primaryKeyInfosFor(CSSM_DB_RECORDTYPE recordType); @@ -191,6 +199,9 @@ public: Item item(const PrimaryKey& primaryKey); Item item(CSSM_DB_RECORDTYPE recordType, CssmClient::DbUniqueRecord &uniqueId); + // Check for an item that may have been deleted. + Item itemdeleted(const PrimaryKey& primaryKey); + CssmDbAttributeInfo attributeInfoFor(CSSM_DB_RECORDTYPE recordType, UInt32 tag); void getAttributeInfoForItemID(CSSM_DB_RECORDTYPE itemID, SecKeychainAttributeInfo **Info); static void freeAttributeInfo(SecKeychainAttributeInfo *Info); @@ -216,15 +227,55 @@ public: bool mayDelete(); + // Returns true if this keychain supports the attribute integrity and + // partition ID protections + bool hasIntegrityProtection(); + private: + // Checks for and triggers a keychain database upgrade + // DO NOT hold any of the keychain locks when you call this + bool performKeychainUpgradeIfNeeded(); + + // Attempt to upgrade this keychain's database + uint32 attemptKeychainMigration(uint32 oldBlobVersion, uint32 newBlobVersion); + + // Remember if we've attempted to upgrade this keychain's database + bool mAttemptedUpgrade; + void removeItem(const PrimaryKey &primaryKey, ItemImpl *inItemImpl); + + // Use this when you want to be extra sure this item is removed from the + // cache. Iterates over the whole cache to find all instances. This function + // will take both cache map mutexes, so you must not hold only the + // mDbDeletedItemMapMutex when you call this function. + void forceRemoveFromCache(ItemImpl* inItemImpl); + ItemImpl *_lookupItem(const PrimaryKey &primaryKey); + // Looks up a deleted item in the deleted item map. Does not check the normal map. + ItemImpl *_lookupDeletedItemOnly(const PrimaryKey &primaryKey); + const AccessCredentials *makeCredentials(); - typedef map DbItemMap; - // Weak reference map of all items we know about that have a primaryKey + typedef map DbItemMap; + // Reference map of all items we know about that have a primaryKey DbItemMap mDbItemMap; + Mutex mDbItemMapMutex; + + // Reference map of all items we know about that have been deleted + // but we haven't yet received a deleted notification about. + // We need this for when we delete an item (and so don't want it anymore) + // but stil need the item around to pass along to the client process with the + // deletion notification (if they've registered for such things). + DbItemMap mDbDeletedItemMap; + Mutex mDbDeletedItemMapMutex; + + // Note on ItemMapMutexes: STL maps are not thread-safe, so you must hold the + // mutex for the entire duration of your access/modification to the map. + // Otherwise, other processes might interrupt your iterator by adding/removing + // items. If you must hold both mutexes, you must take mDbItemMapMutex before + // mDbDeletedItemMapMutex. + // True iff we are in the cache of keychains in StorageManager bool mInCache; @@ -237,6 +288,16 @@ private: bool mIsInBatchMode; EventBuffer *mEventBuffer; Mutex mMutex; + + // Now that we sometimes change the database object, Db object + // creation/returning needs a mutex. You should only hold this if you're + // copying or changing the mDb object. + Mutex mDbMutex; + + // Used to protect mDb across calls. + // Grab a read lock if you expect to read from this keychain in the future. + // The write lock is taken if we're replacing the database wholesale with something new. + ReadWriteLock mRWLock; }; @@ -253,6 +314,8 @@ public: private: friend class StorageManager; + friend class KeychainImpl; + friend class TrustKeychains; Keychain(const CssmClient::Db &db) : SecPointer(new KeychainImpl(db)) {} diff --git a/OSX/libsecurity_keychain/lib/SecACL.cpp b/OSX/libsecurity_keychain/lib/SecACL.cpp index 335c6cf9..fabae241 100644 --- a/OSX/libsecurity_keychain/lib/SecACL.cpp +++ b/OSX/libsecurity_keychain/lib/SecACL.cpp @@ -64,7 +64,7 @@ OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef, { BEGIN_SECAPI SecPointer access = Access::required(accessRef); - SecPointer acl = new ACL(*access, cfString(description), *promptSelector); + SecPointer acl = new ACL(cfString(description), *promptSelector); if (applicationList) { // application-list + prompt acl->form(ACL::appListForm); @@ -125,10 +125,18 @@ OSStatus SecACLCopySimpleContents(SecACLRef aclRef, break; case ACL::appListForm: Required(applicationList) = - makeCFArray(convert, acl->applications()); + makeCFArrayFrom(convert, acl->applications()); Required(promptDescription) = makeCFString(acl->promptDescription()); Required(promptSelector) = acl->promptSelector(); break; + case ACL::integrityForm: + Required(applicationList) = NULL; + Required(promptDescription) = makeCFString(acl->integrity().toHex()); + + // We don't have a prompt selector. Nullify. + Required(promptSelector).version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION; + Required(promptSelector).flags = 0; + break; default: return errSecACLNotSimple; // custom or unknown } @@ -155,15 +163,30 @@ OSStatus SecACLSetSimpleContents(SecACLRef aclRef, { BEGIN_SECAPI SecPointer acl = ACL::required(aclRef); - acl->promptDescription() = description ? cfString(description) : ""; + if(acl->form() == ACL::integrityForm) { + // If this is an integrity ACL, route the (unhexified) promptDescription into the right place + string hex = cfString(description); + if(hex.length() %2 == 0) { + // might be a valid hex string, try to set + CssmAutoData data(Allocator::standard()); + data.malloc(hex.length() / 2); + data.get().fromHex(hex.c_str()); + acl->setIntegrity(data); + } + } else { + // Otherwise, put it in the promptDescription where it belongs + acl->promptDescription() = description ? cfString(description) : ""; + } acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector; - if (applicationList) { - // application-list + prompt - acl->form(ACL::appListForm); - setApplications(acl, applicationList); - } else { - // allow-any - acl->form(ACL::allowAllForm); + if(acl->form() != ACL::integrityForm) { + if (applicationList) { + // application-list + prompt + acl->form(ACL::appListForm); + setApplications(acl, applicationList); + } else { + // allow-any + acl->form(ACL::allowAllForm); + } } acl->modify(); END_SECAPI @@ -248,7 +271,7 @@ CFArrayRef SecACLCopyAuthorizations(SecACLRef acl) strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]); } - result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, NULL); + result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, &kCFTypeArrayCallBacks); delete[] strings; delete[] tags; diff --git a/OSX/libsecurity_keychain/lib/SecAccess.cpp b/OSX/libsecurity_keychain/lib/SecAccess.cpp index 9491f85c..39a8b120 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.cpp +++ b/OSX/libsecurity_keychain/lib/SecAccess.cpp @@ -66,6 +66,8 @@ const CFStringRef kSecACLAuthorizationKeychainItemDelete = CFSTR("ACLAuthorizati const CFStringRef kSecACLAuthorizationChangeACL = CFSTR("ACLAuthorizationChangeACL"); const CFStringRef kSecACLAuthorizationChangeOwner = CFSTR("ACLAuthorizationChangeOwner"); +const CFStringRef kSecACLAuthorizationPartitionID = CFSTR("ACLAuthorizationPartitionID"); +const CFStringRef kSecACLAuthorizationIntegrity = CFSTR("ACLAuthorizationIntegrity"); static CFArrayRef copyTrustedAppListFromBundle(CFStringRef bundlePath, CFStringRef trustedAppListFileName); @@ -95,8 +97,9 @@ static CFStringRef gKeys[] = kSecACLAuthorizationKeychainItemDelete, kSecACLAuthorizationChangeACL, - kSecACLAuthorizationChangeOwner - + kSecACLAuthorizationChangeOwner, + kSecACLAuthorizationPartitionID, + kSecACLAuthorizationIntegrity }; static sint32 gValues[] = @@ -121,7 +124,9 @@ static sint32 gValues[] = CSSM_ACL_AUTHORIZATION_DB_MODIFY, CSSM_ACL_AUTHORIZATION_DB_DELETE, CSSM_ACL_AUTHORIZATION_CHANGE_ACL, - CSSM_ACL_AUTHORIZATION_CHANGE_OWNER + CSSM_ACL_AUTHORIZATION_CHANGE_OWNER, + CSSM_ACL_AUTHORIZATION_PARTITION_ID, + CSSM_ACL_AUTHORIZATION_INTEGRITY }; static diff --git a/OSX/libsecurity_keychain/lib/SecAccess.h b/OSX/libsecurity_keychain/lib/SecAccess.h index 9464790f..f355ab94 100644 --- a/OSX/libsecurity_keychain/lib/SecAccess.h +++ b/OSX/libsecurity_keychain/lib/SecAccess.h @@ -102,6 +102,10 @@ extern const CFStringRef kSecACLAuthorizationChangeACL __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); extern const CFStringRef kSecACLAuthorizationChangeOwner __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA); +extern const CFStringRef kSecACLAuthorizationPartitionID + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); +extern const CFStringRef kSecACLAuthorizationIntegrity + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); /*! @function SecAccessGetTypeID diff --git a/OSX/libsecurity_keychain/lib/SecCertificate.cpp b/OSX/libsecurity_keychain/lib/SecCertificate.cpp index 9950aa33..8c908f64 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificate.cpp +++ b/OSX/libsecurity_keychain/lib/SecCertificate.cpp @@ -260,6 +260,25 @@ SecCertificateGetSHA1Digest(SecCertificateRef certificate) catch (...) { __secapiresult=errSecInternalComponent; } return data; } + +CFDataRef +SecCertificateCopySHA256Digest(SecCertificateRef certificate) +{ + CFDataRef data = NULL; + OSStatus __secapiresult = errSecSuccess; + try { + data = Certificate::required(certificate)->sha256Hash(); + if (data) + CFRetain(data); + } + 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 diff --git a/OSX/libsecurity_keychain/lib/SecCertificatePriv.h b/OSX/libsecurity_keychain/lib/SecCertificatePriv.h index 429fbc2a..1827773d 100644 --- a/OSX/libsecurity_keychain/lib/SecCertificatePriv.h +++ b/OSX/libsecurity_keychain/lib/SecCertificatePriv.h @@ -78,6 +78,9 @@ 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. */ +CFDataRef SecCertificateCopySHA256Digest(SecCertificateRef certificate); + /* Return the SHA-1 hash of the public key in this certificate. */ CFDataRef SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate); diff --git a/OSX/libsecurity_keychain/lib/SecFrameworkP.c b/OSX/libsecurity_keychain/lib/SecFrameworkP.c index 5c143ab7..64bdd381 100644 --- a/OSX/libsecurity_keychain/lib/SecFrameworkP.c +++ b/OSX/libsecurity_keychain/lib/SecFrameworkP.c @@ -46,25 +46,10 @@ #include -/* Security.framework's bundle id. */ -static CFStringRef kSecFrameworkBundleID = CFSTR("com.apple.Security"); - /* Security framework's own bundle used for localized string lookups. */ static CFBundleRef kSecFrameworkBundle; static pthread_once_t kSecFrameworkBundleLookup = PTHREAD_ONCE_INIT; -#if 0 -// copied from SecAsn1Coder.c - -bool SecAsn1OidCompare(const SecAsn1Oid *oid1, const SecAsn1Oid *oid2) { - if (!oid1 || !oid2) - return oid1 == oid2; - if (oid1->Length != oid2->Length) - return false; - return !memcmp(oid1->Data, oid2->Data, oid1->Length); -} -#endif - static void SecFrameworkBundleLookup(void) { // figure out the path to our executable Dl_info info; diff --git a/OSX/libsecurity_keychain/lib/SecImportExportCrypto.cpp b/OSX/libsecurity_keychain/lib/SecImportExportCrypto.cpp index 71a4b315..1f89f4ce 100644 --- a/OSX/libsecurity_keychain/lib/SecImportExportCrypto.cpp +++ b/OSX/libsecurity_keychain/lib/SecImportExportCrypto.cpp @@ -41,6 +41,7 @@ #include #include #include +#include /* * Key attrribute names and values. @@ -562,8 +563,14 @@ OSStatus impExpImportKeyCommon( KeychainCore::Access::required(accessRef) : new KeychainCore::Access("Imported Private Key")); try { - CssmClient::KeyAclBearer bearer(cspHand, unwrappedKey, Allocator::standard()); - theAccess->setAccess(bearer, maker); + if(secKeyRef != NULL) { + // setAccess using the new secKeyRef, not the old unwrappedKey. + // At this point, we might have duplicate keys registered with securityd. Use the newest one. + theAccess->setAccess(*KeyItem::required(secKeyRef)->key(), maker); + } else { + CssmClient::KeyAclBearer bearer(cspHand, unwrappedKey, Allocator::standard()); + theAccess->setAccess(bearer, maker); + } } catch (const CssmError &e) { /* not implemented means we're talking to the raw CSP which does diff --git a/OSX/libsecurity_keychain/lib/SecItem.cpp b/OSX/libsecurity_keychain/lib/SecItem.cpp index 2467ebb1..173eb892 100644 --- a/OSX/libsecurity_keychain/lib/SecItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecItem.cpp @@ -3025,7 +3025,9 @@ _CreateSecItemParamsFromDictionary(CFDictionaryRef dict, OSStatus *error) else if (value) { itemParams->itemClass = _ConvertItemClass(value, itemParams->keyClass, &itemParams->returnIdentity); if (itemParams->itemClass == kSecSymmetricKeyItemClass && !itemParams->keyClass) { - itemParams->assumedKeyClass = kSecAttrKeyClassSymmetric; // no key class specified, so start with symmetric key class; will search the others later + // no key class specified, so start with symmetric key class; will search the others later in UpdateKeychainSearchAndCopyNext + itemParams->itemClass = kSecSymmetricKeyItemClass; + itemParams->assumedKeyClass = kSecAttrKeyClassPublic; } require_action(!(itemParams->itemClass == 0 && !itemParams->useItems), error_exit, status = errSecItemClassMissing); } diff --git a/OSX/libsecurity_keychain/lib/SecItemConstants.c b/OSX/libsecurity_keychain/lib/SecItemConstants.c index 06dc4b41..994a1fea 100644 --- a/OSX/libsecurity_keychain/lib/SecItemConstants.c +++ b/OSX/libsecurity_keychain/lib/SecItemConstants.c @@ -111,6 +111,7 @@ SEC_CONST_DECL (kSecAttrSynchronizable, "sync"); SEC_CONST_DECL (kSecAttrSynchronizableAny, "syna"); SEC_CONST_DECL (kSecAttrTombstone, "tomb"); SEC_CONST_DECL (kSecAttrNoLegacy, "nleg"); +SEC_CONST_DECL (kSecAttrMultiUser, "musr"); /* Search Constants */ SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); @@ -146,6 +147,8 @@ SEC_CONST_DECL (kSecValuePersistentRef, "v_PersistentRef"); /* Other Constants */ SEC_CONST_DECL (kSecUseItemList, "u_ItemList"); SEC_CONST_DECL (kSecUseKeychain, "u_Keychain"); +SEC_CONST_DECL (kSecUseSystemKeychain, "u_SystemKeychain"); +SEC_CONST_DECL (kSecUseSyncBubbleKeychain, "u_SyncBubbleKeychain"); /* kSecAttrAccessible Value Constants. */ SEC_CONST_DECL (kSecAttrAccessibleWhenUnlocked, "ak"); diff --git a/OSX/libsecurity_keychain/lib/SecItemPriv.h b/OSX/libsecurity_keychain/lib/SecItemPriv.h index f46a1646..58ecbbe6 100644 --- a/OSX/libsecurity_keychain/lib/SecItemPriv.h +++ b/OSX/libsecurity_keychain/lib/SecItemPriv.h @@ -277,11 +277,13 @@ extern const CFStringRef kSecAttrCanSignRecover; extern const CFStringRef kSecAttrCanVerifyRecover; extern const CFStringRef kSecAttrTombstone; extern const CFStringRef kSecAttrNoLegacy - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); + __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); /* View Hint Constants */ @@ -329,10 +331,6 @@ extern const CFStringRef kSecUseTombstones __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecUseCredentialReference __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); -#if defined(MULTIPLE_KEYCHAINS) -extern const CFStringRef kSecUseKeychain; -extern const CFStringRef kSecUseKeychainList; -#endif /* !defined(MULTIPLE_KEYCHAINS) */ /*! @@ -380,7 +378,7 @@ OSStatus _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDic Requires caller to have the kSecEntitlementKeychainSyncUpdates entitlement. */ CFArrayRef _SecKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#if !TARGET_OS_IPHONE CFDataRef _SecItemGetPersistentReference(CFTypeRef raw_item); #endif @@ -390,6 +388,10 @@ OSStatus SecErrorGetOSStatus(CFErrorRef error); bool _SecKeychainRollKeys(bool force, CFErrorRef *error); +CFDictionaryRef _SecSecuritydCopyWhoAmI(CFErrorRef *error); +bool _SecSyncBubbleTransfer(CFArrayRef services, CFErrorRef *error); +bool _SecSystemKeychainTransfer(CFErrorRef *error); + __END_DECLS #endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/OSX/libsecurity_keychain/lib/SecKeychain.cpp b/OSX/libsecurity_keychain/lib/SecKeychain.cpp index 8a48d3f2..9580a994 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychain.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychain.cpp @@ -408,6 +408,18 @@ SecKeychainGetPath(SecKeychainRef keychainRef, UInt32 *ioPathLength, char *pathN END_SECAPI } +OSStatus +SecKeychainGetKeychainVersion(SecKeychainRef keychainRef, UInt32* version) +{ + BEGIN_SECAPI + + RequiredParam(version); + + *version = Keychain::optional(keychainRef)->database()->dbBlobVersion(); + + END_SECAPI +} + // @@@ Deprecated UInt16 diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp index 30bb1d3e..e606a191 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp +++ b/OSX/libsecurity_keychain/lib/SecKeychainItem.cpp @@ -475,6 +475,32 @@ SecKeychainItemSetAccess(SecKeychainItemRef itemRef, SecAccessRef accessRef) END_SECAPI } +OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password) { + BEGIN_SECAPI + + OSStatus result; + + // try to unlock the keychain with this password first + SecKeychainRef kc = NULL; + result = SecKeychainItemCopyKeychain(itemRef, &kc); + if(!result) { + SecKeychainUnlock(kc, passwordLength, password, true); + if(kc) { + CFRelease(kc); + } + } + + // Create some credentials with this password + CssmAutoData data(Allocator::standard(), password, passwordLength); + AclFactory::PassphraseUnlockCredentials cred(data, Allocator::standard()); + + Access::required(accessRef)->editAccess(*aclBearer(reinterpret_cast(itemRef)), true, cred.getAccessCredentials()); + ItemImpl::required(itemRef)->postItemEvent (kSecUpdateEvent); + + END_SECAPI +} + + /* Sets an item's data for legacy "KC" CoreServices APIs. Note this version sets the data, but doesn't update the item as the KC behavior dictates. diff --git a/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h index c7eb963d..f3ed51e7 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h @@ -157,6 +157,17 @@ OSStatus SecKeychainItemModifyEncryptedData(SecKeychainItemRef itemRef, UInt32 l OSStatus SecKeychainItemCreateFromEncryptedContent(SecItemClass itemClass, UInt32 length, const void *data, SecKeychainRef keychainRef, SecAccessRef initialAccess, SecKeychainItemRef *itemRef, CFDataRef *itemLocalID); + + /*! + @function SecKeychainItemSetAccessWithPassword + @abstract Sets the access of a given keychain item. + @param itemRef A reference to a keychain item. + @param access A reference to an access to replace the keychain item's current access. + @param passwordLength An unsigned 32-bit integer representing the length of the password buffer. + @param password A buffer containing the password for the keychain. if this password is incorrect, this call might fail---it will not prompt the user. + @result A result code. See "Security Error Codes" (SecBase.h). +*/ + OSStatus SecKeychainItemSetAccessWithPassword(SecKeychainItemRef itemRef, SecAccessRef accessRef, UInt32 passwordLength, const void * password); #if defined(__cplusplus) } #endif diff --git a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h index d4528aca..e9650f96 100644 --- a/OSX/libsecurity_keychain/lib/SecKeychainPriv.h +++ b/OSX/libsecurity_keychain/lib/SecKeychainPriv.h @@ -115,6 +115,9 @@ OSStatus SecKeychainSystemKeychainCheckWouldDeadlock() OSStatus SecKeychainStoreUnlockKey(SecKeychainRef userKeychainRef, SecKeychainRef systemKeychainRef, CFStringRef username, CFStringRef password) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_NA); +OSStatus SecKeychainGetKeychainVersion(SecKeychainRef keychain, UInt32* version) + __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); + /*! @function SecKeychainMDSInstall Set up MDS. diff --git a/OSX/libsecurity_keychain/lib/SecPolicy.cpp b/OSX/libsecurity_keychain/lib/SecPolicy.cpp index 269db0b1..95fc6f36 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicy.cpp +++ b/OSX/libsecurity_keychain/lib/SecPolicy.cpp @@ -77,6 +77,7 @@ 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 (kSecPolicyOid, "SecPolicyOid"); SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); @@ -162,33 +163,6 @@ const oidmap_entry_t oidmap[] = { { kSecPolicyAppleOSXProvisioningProfileSigning, &CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING }, }; -// TBD: have only one set of policy identifiers in SecPolicy.c so we can get rid of this -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 }, -}; - // // CF boilerplate // @@ -878,6 +852,11 @@ SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRe return SecPolicyCreateSSL(true, hostname); } +SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef __unused context) +{ + return SecPolicyCreateSSL(true, hostname); +} + #if !SECTRUST_OSX /* new in 10.11 */ SecPolicyRef SecPolicyCreateAppleATVAppSigning(void) @@ -981,7 +960,6 @@ SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray) resultPolicyArray=appleTimeStampingPolicies.yield(); } catch (...) { - syslog(LOG_ERR, "SecPolicyCreateAppleTimeStampingAndRevocationPolicies: unable to create policy array"); CFReleaseNull(resultPolicyArray); }; #else diff --git a/OSX/libsecurity_keychain/lib/SecPolicyPriv.h b/OSX/libsecurity_keychain/lib/SecPolicyPriv.h index 0612aa33..6243ab9e 100644 --- a/OSX/libsecurity_keychain/lib/SecPolicyPriv.h +++ b/OSX/libsecurity_keychain/lib/SecPolicyPriv.h @@ -101,6 +101,9 @@ extern const CFStringRef kSecPolicyAppleOSXProvisioningProfileSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); 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); + /*! @function SecPolicyCopy @@ -173,16 +176,23 @@ SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname, CFDictionaryR /*! @function SecPolicyCreateAppleGSService @abstract Ensure we're appropriately pinned to the GS service (SSL + Apple restrictions) -*/ + */ SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef 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) -*/ + */ SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef context); +/*! + @function SecPolicyCreateAppleAST2Service + @abstract Ensure we're appropriately pinned to the AST2 Diagnostic service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef 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) diff --git a/OSX/libsecurity_keychain/lib/StorageManager.cpp b/OSX/libsecurity_keychain/lib/StorageManager.cpp index f5d16aed..55176915 100644 --- a/OSX/libsecurity_keychain/lib/StorageManager.cpp +++ b/OSX/libsecurity_keychain/lib/StorageManager.cpp @@ -52,6 +52,7 @@ #include #include "TrustSettingsSchema.h" #include +#include //%%% add this to AuthorizationTagsPriv.h later #ifndef AGENT_HINT_LOGIN_KC_SUPPRESS_RESET_PANEL @@ -156,14 +157,7 @@ StorageManager::keychain(const DLDbIdentifier &dLDbIdentifier) KeychainMap::iterator it = mKeychains.find(dLDbIdentifier); if (it != mKeychains.end()) { - if (it->second == NULL) // cleared by weak reference? - { - mKeychains.erase(it); - } - else - { - return it->second; - } + return it->second; } if (gServerMode) { @@ -171,17 +165,8 @@ StorageManager::keychain(const DLDbIdentifier &dLDbIdentifier) return Keychain(); } - // The keychain is not in our cache. Create it. - Module module(dLDbIdentifier.ssuid().guid()); - DL dl; - if (dLDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) - dl = SSCSPDL(module); - else - dl = DL(module); - - dl->subserviceId(dLDbIdentifier.ssuid().subserviceId()); - dl->version(dLDbIdentifier.ssuid().version()); - Db db(dl, dLDbIdentifier.dbName()); + // The keychain is not in our cache. Create it. + Db db(makeDb(dLDbIdentifier)); Keychain keychain(db); // Add the keychain to the cache. @@ -191,6 +176,43 @@ StorageManager::keychain(const DLDbIdentifier &dLDbIdentifier) return keychain; } +CssmClient::Db +StorageManager::makeDb(DLDbIdentifier dLDbIdentifier) { + Module module(dLDbIdentifier.ssuid().guid()); + + DL dl; + if (dLDbIdentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) + dl = SSCSPDL(module); + else + dl = DL(module); + + dl->subserviceId(dLDbIdentifier.ssuid().subserviceId()); + dl->version(dLDbIdentifier.ssuid().version()); + + CssmClient::Db db(dl, dLDbIdentifier.dbName()); + + return db; +} + +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; + } + + // Since this new database is based on the exact same dLDbIdentifier, we + // don't need to update the mKeychains map. +} + void StorageManager::removeKeychain(const DLDbIdentifier &dLDbIdentifier, KeychainImpl *keychainImpl) @@ -216,12 +238,6 @@ StorageManager::didRemoveKeychain(const DLDbIdentifier &dLDbIdentifier) KeychainMap::iterator it = mKeychains.find(dLDbIdentifier); if (it != mKeychains.end()) { - if (it->second != NULL) // did we get zapped by weak reference destruction - { - KeychainImpl *keychainImpl = it->second; - keychainImpl->inCache(false); - } - mKeychains.erase(it); } } @@ -1538,6 +1554,10 @@ Keychain StorageManager::make(const char *pathName) Keychain StorageManager::make(const char *pathName, bool add) { + return makeKeychain(makeDLDbIdentifier(pathName), add); +} + +DLDbIdentifier StorageManager::makeDLDbIdentifier(const char *pathName) { StLock_(mMutex); string fullPathName; @@ -1582,8 +1602,8 @@ Keychain StorageManager::make(const char *pathName, bool add) CSSM_SERVICE_TYPE subserviceType = CSSM_SERVICE_DL | CSSM_SERVICE_CSP; const CssmSubserviceUid ssuid(gGuidAppleCSPDL, version, subserviceId, subserviceType); - DLDbIdentifier dLDbIdentifier(ssuid, fullPathName.c_str(), DbLocation); - return makeKeychain(dLDbIdentifier, add); + DLDbIdentifier dlDbIdentifier(ssuid, fullPathName.c_str(), DbLocation); + return dlDbIdentifier; } Keychain StorageManager::makeLoginAuthUI(const Item *item) diff --git a/OSX/libsecurity_keychain/lib/StorageManager.h b/OSX/libsecurity_keychain/lib/StorageManager.h index edd02841..b1f82cf4 100644 --- a/OSX/libsecurity_keychain/lib/StorageManager.h +++ b/OSX/libsecurity_keychain/lib/StorageManager.h @@ -92,6 +92,8 @@ public: // 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); + // Reload a keychain from the on-disk database + void reloadKeychain(Keychain keychain); // Keychain list maintenance @@ -155,14 +157,17 @@ private: static void convertList(DLDbList &ids, const KeychainList &kcs); void convertList(KeychainList &kcs, const DLDbList &ids); + DLDbIdentifier makeDLDbIdentifier(const char* pathName); + CssmClient::Db makeDb(DLDbIdentifier dLDbIdentifier); + // Only add if not there yet. Writes out CFPref and broadcasts KCPrefListChanged notification void addAndNotify(const Keychain& keychainToAdd); // remove a keychain from the sync list void removeKeychainFromSyncList (const DLDbIdentifier &id); - typedef map KeychainMap; - // Weak reference map of all keychains we know about that aren't deleted + typedef map KeychainMap; + // Reference map of all keychains we know about that aren't deleted // or removed KeychainMap mKeychains; diff --git a/OSX/libsecurity_keychain/lib/Trust.cpp b/OSX/libsecurity_keychain/lib/Trust.cpp index c1514284..45a28a49 100644 --- a/OSX/libsecurity_keychain/lib/Trust.cpp +++ b/OSX/libsecurity_keychain/lib/Trust.cpp @@ -35,6 +35,7 @@ #include "TrustAdditions.h" #include "TrustKeychains.h" #include +#include using namespace Security; @@ -65,29 +66,6 @@ ModuleNexus Trust::gStore; #pragma mark -- TrustKeychains -- -static const CSSM_DL_DB_HANDLE nullCSSMDLDBHandle = {0,}; -// -// TrustKeychains maintains a global reference to standard system keychains, -// to avoid having them be opened anew for each Trust instance. -// -class TrustKeychains -{ -public: - TrustKeychains(); - ~TrustKeychains() {} - CSSM_DL_DB_HANDLE rootStoreHandle() { return mRootStoreHandle; } - CSSM_DL_DB_HANDLE systemKcHandle() { return mSystem ? mSystem->database()->handle() : nullCSSMDLDBHandle; } - Keychain &systemKc() { return mSystem; } - Keychain &rootStore() { return *mRootStore; } - -private: - DL* mRootStoreDL; - Db* mRootStoreDb; - Keychain* mRootStore; - CSSM_DL_DB_HANDLE mRootStoreHandle; - Keychain mSystem; -}; - // // Singleton maintaining open references to standard system keychains, // to avoid having them be opened anew every time SecTrust is used. @@ -102,19 +80,20 @@ TrustKeychains::TrustKeychains() : mRootStoreHandle(nullCSSMDLDBHandle), mSystem(globals().storageManager.make(ADMIN_CERT_STORE_PATH, false)) { - if (GetServerMode()) // in server mode? Don't make a keychain for the root store + if (GetServerMode()) // in server mode? Don't go through StorageManager to make a keychain { mRootStoreDL = new DL(gGuidAppleFileDL), mRootStoreDb = new Db(*mRootStoreDL, SYSTEM_ROOT_STORE_PATH), - (*mRootStoreDb)->activate(); - mRootStoreHandle = (*mRootStoreDb)->handle(); + mRootStore = new Keychain(*mRootStoreDb); } else { + mRootStoreDL = NULL; + mRootStoreDb = NULL; mRootStore = new Keychain(globals().storageManager.make(SYSTEM_ROOT_STORE_PATH, false)); - (*mRootStore)->database()->activate(); - mRootStoreHandle = (*mRootStore)->database()->handle(); } + (*mRootStore)->database()->activate(); + mRootStoreHandle = (*mRootStore)->database()->handle(); } RecursiveMutex& SecTrustKeychainsGetMutex() @@ -505,7 +484,7 @@ void Trust::evaluate(bool disableEV) } /* do post-processing for the evaluated certificate chain */ - CFArrayRef fullChain = makeCFArray(convert, mCertChain); + CFArrayRef fullChain = makeCFArrayFrom(convert, mCertChain); CFDictionaryRef etResult = extendedTrustResults(fullChain, mResult, mTpReturn, isEVCandidate); mExtendedResult = etResult; // assignment to CFRef type is an implicit retain if (etResult) { @@ -758,7 +737,7 @@ void Trust::buildEvidence(CFArrayRef &certChain, TPEvidenceInfo * &statusChain) if (mResult == kSecTrustResultInvalid) MacOSError::throwMe(errSecTrustNotAvailable); certChain = mEvidenceReturned = - makeCFArray(convert, mCertChain); + makeCFArrayFrom(convert, mCertChain); if(mTpResult.count() >= 3) { statusChain = mTpResult[2].as(); } diff --git a/OSX/libsecurity_keychain/lib/Trust.h b/OSX/libsecurity_keychain/lib/Trust.h index 1df98146..3ebdf780 100644 --- a/OSX/libsecurity_keychain/lib/Trust.h +++ b/OSX/libsecurity_keychain/lib/Trust.h @@ -184,6 +184,30 @@ private: Mutex mMutex; }; +// +// TrustKeychains maintains a global reference to standard system keychains, +// to avoid having them be opened anew for each Trust instance. +// +static const CSSM_DL_DB_HANDLE nullCSSMDLDBHandle = {0,}; + +class TrustKeychains +{ + public: + TrustKeychains(); + ~TrustKeychains() {} + CSSM_DL_DB_HANDLE rootStoreHandle() { return mRootStoreHandle; } + CSSM_DL_DB_HANDLE systemKcHandle() { return mSystem ? mSystem->database()->handle() : nullCSSMDLDBHandle; } + Keychain &systemKc() { return mSystem; } + Keychain &rootStore() { return *mRootStore; } + + private: + DL* mRootStoreDL; + Db* mRootStoreDb; + Keychain* mRootStore; + CSSM_DL_DB_HANDLE mRootStoreHandle; + Keychain mSystem; +}; + } // end namespace KeychainCore } // end namespace Security diff --git a/OSX/libsecurity_keychain/lib/security_keychain.exp b/OSX/libsecurity_keychain/lib/security_keychain.exp index 8b6b9269..8672c790 100644 --- a/OSX/libsecurity_keychain/lib/security_keychain.exp +++ b/OSX/libsecurity_keychain/lib/security_keychain.exp @@ -217,6 +217,7 @@ _kSecPolicyAppleTestATVAppSigning _kSecPolicyApplePayIssuerEncryption _kSecPolicyAppleOSXProvisioningProfileSigning _kSecPolicyAppleATVVPNProfileSigning +_kSecPolicyAppleAST2DiagnosticsServerAuth _kSecPolicyOid _kSecPolicyName _kSecPolicyClient @@ -553,6 +554,7 @@ _SecKeychainGetStatus _SecKeychainGetTypeID _SecKeychainGetUserInteractionAllowed _SecKeychainGetVersion +_SecKeychainGetKeychainVersion _SecKeychainIsValid _SecKeychainMDSInstall _SecKeychainItemAdd @@ -587,6 +589,7 @@ _SecKeychainItemModifyAttributesAndData _SecKeychainItemModifyEncryptedData _SecKeychainItemModifyContent _SecKeychainItemSetAccess +_SecKeychainItemSetAccessWithPassword _SecKeychainItemSetAttribute _SecKeychainItemSetData _SecKeychainItemSetExtendedAttribute @@ -634,6 +637,7 @@ _SecPolicyCreateAppleIDSServiceContext _SecPolicyCreateApplePushService _SecPolicyCreateAppleMMCSService _SecPolicyCreateApplePPQService +_SecPolicyCreateAppleAST2Service _SecPolicyCreateAppleATVAppSigning _SecPolicyCreateTestAppleATVAppSigning _SecPolicyCreateAppleATVVPNProfileSigning diff --git a/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj b/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj index a9f1f2c9..f14c162a 100644 --- a/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj @@ -587,6 +587,7 @@ baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + SDKROOT = macosx.internal; }; name = Debug; }; @@ -595,6 +596,7 @@ baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */; buildSettings = { COMBINE_HIDPI_IMAGES = YES; + SDKROOT = macosx.internal; }; name = Release; }; @@ -675,6 +677,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = macosx.internal; }; name = Debug; }; @@ -695,6 +698,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; RUN_CLANG_STATIC_ANALYZER = YES; + SDKROOT = macosx.internal; }; name = Release; }; diff --git a/OSX/libsecurity_keychain/libDER/libDER/oids.c b/OSX/libsecurity_keychain/libDER/libDER/oids.c index d6f28263..2a65d35c 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/oids.c +++ b/OSX/libsecurity_keychain/libDER/libDER/oids.c @@ -313,6 +313,13 @@ /* AppleTV VPN Profile Signing 1.2.840.113635.100.6.43 */ #define APPLE_CERT_EXT_APPLE_ATV_VPN_PROFILE_SIGNING APPLE_CERT_EXT, 43 +/* AST2 Diagnostics Server Authentication + * Test Marker OID 1.2.840.113635.100.6.27.8.1 + * Prod Marker OID 1.2.840.113635.100.6.27.8.2 + */ +#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 + /* * Netscape OIDs. */ @@ -538,7 +545,9 @@ __unused static const DERByte _oidAppleCertExtATVAppSigningTest[] = {APPLE_ATV_APP_SIGNING_OID_TEST}, _oidAppleCertExtATVAppSigningProd[] = {APPLE_ATV_APP_SIGNING_OID}, _oidAppleCertExtATVVPNProfileSigning[] = {APPLE_CERT_EXT_APPLE_ATV_VPN_PROFILE_SIGNING}, - _oidAppleCertExtCryptoServicesExtEncryption[] = {APPLE_CERT_EXT_CRYPTO_SERVICES_EXT_ENCRYPTION}; + _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}; __unused const DERItem oidSubjectKeyIdentifier = { (DERByte *)_oidSubjectKeyIdentifier, @@ -725,7 +734,11 @@ __unused const DERItem oidAppleCertExtATVVPNProfileSigning = { (DERByte *) _oidAppleCertExtATVVPNProfileSigning, sizeof(_oidAppleCertExtATVVPNProfileSigning)}, oidAppleCertExtCryptoServicesExtEncryption = { (DERByte *)_oidAppleCertExtCryptoServicesExtEncryption, - sizeof(_oidAppleCertExtCryptoServicesExtEncryption)}; + sizeof(_oidAppleCertExtCryptoServicesExtEncryption)}, + oidAppleCertExtAST2DiagnosticsServerAuthTest = { (DERByte *)_oidAppleCertExtAST2DiagnosticsServerAuthTest, + sizeof(_oidAppleCertExtAST2DiagnosticsServerAuthTest)}, + oidAppleCertExtAST2DiagnosticsServerAuthProd = { (DERByte *)_oidAppleCertExtAST2DiagnosticsServerAuthProd, + sizeof(_oidAppleCertExtAST2DiagnosticsServerAuthProd)}; diff --git a/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h b/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h index 8834d9ca..302459d5 100644 --- a/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h +++ b/OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h @@ -77,7 +77,9 @@ extern const DERItem oidAppleCertExtATVAppSigningProd, oidAppleCertExtATVAppSigningTest, oidAppleCertExtATVVPNProfileSigning, - oidAppleCertExtCryptoServicesExtEncryption; + oidAppleCertExtCryptoServicesExtEncryption, + oidAppleCertExtAST2DiagnosticsServerAuthTest, + oidAppleCertExtAST2DiagnosticsServerAuthProd; /* Compare two decoded OIDs. Returns true iff they are equivalent. */ bool DEROidCompare(const DERItem *oid1, const DERItem *oid2); diff --git a/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj b/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj index 72226efb..57e98c0b 100644 --- a/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj +++ b/OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj @@ -159,6 +159,8 @@ C429431E053B2F8B00470431 /* KCUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C429431C053B2F8B00470431 /* KCUtilities.cpp */; }; D4A2FC821BC8A65B00BF6E56 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4A2FC811BC8A65B00BF6E56 /* Security.framework */; }; D6095E960A94F17C0026C68B /* KCEventNotifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6E1457B0A632A5A008AA7E8 /* KCEventNotifier.cpp */; }; + DC3C16001BAB76B50041A23A /* kc-30-xara.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3C15F81BAB6FE20041A23A /* kc-30-xara.c */; }; + DCD20F421BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = DCD20F411BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h */; }; F92321381ACF69EE00634C21 /* si-34-one-true-keychain.c in Sources */ = {isa = PBXBuildFile; fileRef = F92321371ACF69EE00634C21 /* si-34-one-true-keychain.c */; }; /* End PBXBuildFile section */ @@ -424,6 +426,11 @@ 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 = ""; }; + 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 = ""; }; + 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 = ""; }; 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 */ @@ -672,6 +679,11 @@ isa = PBXGroup; children = ( 0CBD509C16C324B100713B6C /* keychain_regressions.h */, + 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 */, AC9ADAD2199AD6BA00BDAF54 /* kc-42-trust-revocation.c */, @@ -784,6 +796,7 @@ files = ( 05FB016905E54A3A00A5194C /* SecNetscapeTemplates.h in Headers */, 056CDA5D05FD5AEB00820BC3 /* SecPkcs8Templates.h in Headers */, + DCD20F421BCDA8260046D8EB /* kc-30-xara-upgrade-helpers.h in Headers */, 4CF36F650581376700834D11 /* SecAccess.h in Headers */, 4CF36F680581376700834D11 /* SecACL.h in Headers */, 4CF36F6A0581376700834D11 /* SecBase.h in Headers */, @@ -1007,6 +1020,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DC3C16001BAB76B50041A23A /* kc-30-xara.c in Sources */, AC9ADAD3199AD6BA00BDAF54 /* kc-42-trust-revocation.c in Sources */, 0CBD509B16C3246D00713B6C /* kc-41-sececkey.c in Sources */, 188BB546171DD8B5009D22CE /* si-33-keychain-backup.c in Sources */, diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h new file mode 100644 index 00000000..e5e89a0c --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h @@ -0,0 +1,210 @@ +/* + * 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 kc_30_xara_helpers_h +#define kc_30_xara_helpers_h + +#include +#include +#include +#include "utilities/SecCFRelease.h" + +static char keychainFile[1000]; +static char keychainName[1000]; + +#if TARGET_OS_MAC + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +/* name is the name of the test, not the name of the keychain */ +static SecKeychainRef newKeychain(const char * name) { + SecKeychainRef kc = NULL; + char* password = "password"; + + // Kill the test keychain if it exists. + unlink(keychainFile); + + ok_status(SecKeychainCreate(keychainName, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); + return kc; +} +#define newKeychainTests 1 + +/* 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) { + SecKeychainRef kc = NULL; + + // Kill the keychain if it exists. + unlink(path); + + ok_status(SecKeychainCreate(path, (UInt32) strlen(password), password, false, NULL, &kc), "%s: SecKeychainCreate", name); + return kc; +} +#define newCustomKeychainTests 1 + +static SecKeychainRef openCustomKeychain(const char * name, const char * path, const char * password) { + SecKeychainRef kc = NULL; + ok_status(SecKeychainOpen(path, &kc), "%s: SecKeychainOpen", name); + + if(password) { + ok_status(SecKeychainUnlock(kc, (UInt32) strlen(password), password, true), "%s: SecKeychainUnlock", name); + } else { + pass("make test count right"); + } + + return kc; +} +#define openCustomKeychainTests 2 + +static SecKeychainRef openKeychain(const char * name) { + return openCustomKeychain(name, "test.keychain", NULL); +} +#define openKeychainTests (openCustomKeychainTests) + +#define getIntegrityHashTests 3 +static CFStringRef getIntegrityHash(const char* name, SecKeychainItemRef item) { + if(!item) { + for(int i = 0; i < getIntegrityHashTests; i++) { + fail("%s: getIntegrityHash not passed an item", name); + } + return NULL; + } + SecAccessRef access = NULL; + ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); + + CFArrayRef acllist = NULL; + ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name); + + int hashesFound = 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, kSecACLAuthorizationIntegrity)) { + + CFArrayRef applications = NULL; + CFStringRef description = NULL; + SecKeychainPromptSelector selector; + SecACLCopyContents(acl, &applications, &description, &selector); + + // found a hash. match it. + hashesFound++; + + output = description; + } + + CFReleaseNull(auths); + } + + CFReleaseNull(acllist); + } + + is(hashesFound, 1, "%s: Wrong number of hashes found", name); + return output; +} + +// Pulls the Integrity hash out of an item and compares it against the given one. +static void checkIntegrityHash(const char* name, SecKeychainItemRef item, CFStringRef expectedHash) { + CFStringRef hash = getIntegrityHash(name, item); + + if(!hash) { + fail("No hash to match"); + return; + } + + // We can't use use the ok macro here, because we + // might run it too many times and mess up the test count. + if(CFStringCompare(expectedHash, hash, 0) == kCFCompareEqualTo) { + pass("Hashes match."); + } else { + printf("%s: Hashes didn't match. Was: ", name); + fflush(stdout); + CFShow(hash); + fail("Hashes don't match"); + } +} +#define checkIntegrityHashTests (getIntegrityHashTests + 1) + +static void checkHashesMatch(const char* name, SecKeychainItemRef item, SecKeychainItemRef comp) { + CFStringRef itemhash = getIntegrityHash(name, item); + CFStringRef comparehash = getIntegrityHash(name, comp); + + if(!itemhash) { + fail("%s: original item not passed in", name); + return; + } + if(!comparehash) { + fail("%s: compare item not passed in", name); + return; + } + + is(CFStringCompare(itemhash, comparehash, 0), kCFCompareEqualTo, "%s: hashes do not match", name); + if(CFStringCompare(itemhash, comparehash, 0) != kCFCompareEqualTo) { + fflush(stdout); + CFShow(itemhash); + CFShow(comparehash); + } +} +#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 + +#endif /* TARGET_OS_MAC */ + +#endif /* kc_30_xara_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h new file mode 100644 index 00000000..e2f523c1 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h @@ -0,0 +1,299 @@ +/* + * 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-30-xara-helpers.h" + +#ifndef kc_30_xara_item_helpers_h +#define kc_30_xara_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 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); + CFReleaseNull(item); +} +#define makeCustomItemWithIntegrityTests (makeItemTests + checkIntegrityHashTests) + +static void makeItemWithIntegrity(const char* name, SecKeychainRef kc, CFStringRef itemclass, CFStringRef expectedHash) { + makeCustomItemWithIntegrity(name, kc, itemclass, CFSTR("test_label"), expectedHash); +} +#define makeItemWithIntegrityTests (makeCustomItemWithIntegrityTests) + +static void testAddItem(CFStringRef itemclass, CFStringRef expectedHash) { + char name[100]; + sprintf(name, "testAddItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + makeItemWithIntegrity(name, kc, itemclass, expectedHash); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#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); + + SecKeychainRef kc = newKeychain(name); + makeItemWithIntegrity(name, kc, itemclass, expectedHash); + + SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, itemclass), 1); + checkIntegrityHash(name, item, expectedHash); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#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); + + SecKeychainRef kc = newKeychain(name); + makeItemWithIntegrity(name, kc, itemclass, expectedHashOrig); + + CFMutableDictionaryRef query = makeQueryItemDictionary(kc, itemclass); + CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(update, kSecAttrComment, CFSTR("a modification")); + CFDictionarySetValue(update, kSecAttrAccount, CFSTR("a account modification")); + CFDictionarySetValue(update, kSecAttrLabel, CFSTR("a label modification")); + ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name); + + CFReleaseNull(update); + + SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, itemclass), 1); + checkIntegrityHash(name, item, expectedHashAfter); + CFReleaseNull(item); + + // Check that updating data works + update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(update, kSecValueData, CFDataCreate(NULL, (void*)"data", 4)); + ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name); + + item = checkN(name, makeQueryItemDictionary(kc, itemclass), 1); + checkIntegrityHash(name, item, expectedHashAfter); + + CFReleaseNull(query); + CFReleaseNull(update); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testUpdateItemTests (newKeychainTests + makeItemWithIntegrityTests \ + + 1 + checkNTests + checkIntegrityHashTests \ + + 1 + checkNTests + checkIntegrityHashTests \ + + 1) + +static void testAddDuplicateItem(CFStringRef itemclass, CFStringRef expectedHash) { + char name[100]; + sprintf(name, "testAddDuplicateItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + makeItemWithIntegrity(name, kc, itemclass, expectedHash); + + makeDuplicateItem(name, kc, itemclass); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#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); + + SecKeychainRef kc = newKeychain(name); + makeItemWithIntegrity(name, kc, itemclass, expectedHash); + + SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, itemclass), 1); + checkIntegrityHash(name, item, expectedHash); + + ok_status(SecKeychainItemDelete(item), "%s: SecKeychainItemDelete", name); + checkN(name, makeQueryItemDictionary(kc, itemclass), 0); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testDeleteItemTests (newKeychainTests + makeItemWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1 + checkNTests + 1) + +static void writeEmptyV512Keychain(const char* name, const char* keychainFile); + +// This test is to find CrashTracer: accountsd at …curity: Security::KeychainCore::CCallbackMgr::consume + 387 +// +// The issue was that items could remain in the Keychain cache, even after the +// actual object was freed. The main path involved updating an item so that it +// had the same primary key as an item which was in the cache but not in the +// database (this could be caused by another process deleting the item and us +// not receiving the notification). +// +// This test should pass. Failure is shown by crashing. +// +static void testUpdateRetainedItem(CFStringRef itemclass) { + char name[100]; + sprintf(name, "testUpdateRetainedItem[%s]", CFStringGetCStringPtr(itemclass, kCFStringEncodingUTF8)); + secdebugfunc("integrity", "************************************* %s", name); + + writeEmptyV512Keychain(name, keychainFile); + SecKeychainRef kc = openCustomKeychain(name, "test.keychain", "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); + + // 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); + + // 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); + + secdebugfunc("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); + + // Now, update the second item so it would collide with the first + CFMutableDictionaryRef query = makeQueryCustomItemDictionary(kc, itemclass, CFSTR("not_a_test_label")); + CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(update, kSecAttrAccount, CFSTR("account1")); + CFDictionarySetValue(update, kSecAttrLabel, CFSTR("test_label")); + ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name); + + is(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); +} +#define testUpdateRetainedItemTests (openCustomKeychainTests + makeCustomItemTests + checkNTests \ + + 1 + makeCustomItemTests + makeCustomItemTests \ + + newCustomKeychainTests + makeCustomItemTests + 1 \ + + makeCustomItemTests + checkNTests + 1 \ + + 1 + 1 + checkNTests + 1) + +#pragma clang pop +#else + +#endif /* TARGET_OS_MAC */ + + +#endif /* kc_30_xara_item_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h new file mode 100644 index 00000000..d9593f19 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h @@ -0,0 +1,471 @@ +/* + * 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-30-xara-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); + CFReleaseNull(key); + } +#define makeCustomKeyWithIntegrityTests (makeCustomKeyTests + checkIntegrityHashTests) + +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; + SecKeyRef priv; + makeKeyPair(name, kc, &pub, &priv); + + checkIntegrityHash(name, (SecKeychainItemRef) pub, expectedPubHash); + checkIntegrityHash(name, (SecKeychainItemRef) priv, expectedPrivHash); +} +#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) { + char* name = "testAddKey"; + SecKeychainRef kc = newKeychain(name); + makeKeyWithIntegrity(name, kc, expectedHash); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testAddKeyTests (newKeychainTests + makeKeyWithIntegrityTests + 1) + +static void testAddFreeKey(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 = "testAddFreeKey"; + //SecKeychainRef kc = newKeychain(name); + + //SecKeyRef key = makeFreeKey(name, kc); + //checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash); + + //ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +//#define testAddFreeKeyTests (newKeychainTests + makeFreeKeyTests + checkIntegrityHashTests + 1) +#define testAddFreeKeyTests 0 + +static void testCopyMatchingKey(CFStringRef expectedHash) { + char* name = "testCopyMatchingKey"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + + makeKeyWithIntegrity(name, kc, expectedHash); + + SecKeyRef item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + checkIntegrityHash(name, (SecKeychainItemRef) item, expectedHash); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testCopyMatchingKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + checkIntegrityHashTests + 1) + + +static void testUpdateKey(CFStringRef expectedHash, CFStringRef expectedHashAfter) { + char * name = "testUpdateKey"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + makeKeyWithIntegrity(name, kc, expectedHash); + SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + CFReleaseNull(item); + + CFStringRef label = CFSTR("a modified label"); + + CFMutableDictionaryRef query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric); + CFMutableDictionaryRef update = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(update, kSecAttrLabel, label); + ok_status(SecItemUpdate(query, update), "%s: SecItemUpdate", name); + + CFReleaseNull(query); + CFReleaseNull(update); + + // Find the item again. + query = makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric); + CFDictionarySetValue(query, kSecAttrLabel, label); + item = checkN(name, query, 1); + checkIntegrityHash(name, item, expectedHashAfter); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testUpdateKeyTests (newKeychainTests + makeKeyWithIntegrityTests + checkNTests + 1 + checkNTests + checkIntegrityHashTests + 1) + +// Key Pairs have non-predictable hashes, since they receive an attribute kSecKeyLabel that is +// the hash of the public key. Since the key is generated randomly, so is the label. +// +// We can't do our normal "add", "copymatching", "update" tests here, so do +// something special... + +static void testKeyPair() { + char* name = "testKeyPair"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); + + SecKeyRef pub; + SecKeyRef priv; + makeKeyPair(name, kc, &pub, &priv); + + // Now that we have the key pair, make sure we can pull the individual keys + // out (and the hashes match) + + SecKeyRef item; + item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + checkHashesMatch(name, (SecKeychainItemRef)pub, (SecKeychainItemRef)item); + + item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + checkHashesMatch(name, (SecKeychainItemRef)priv, (SecKeychainItemRef)item); + + // TODO: is there a way to test SecItemUpdate? + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testKeyPairTests (newKeychainTests + checkNTests + checkNTests + makeKeyPairTests \ + + checkNTests + checkHashesMatchTests \ + + checkNTests + checkHashesMatchTests + 1) + +static void testAddDuplicateKey(CFStringRef expectedHash) { + char * name = "testAddDuplicateKey"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + + makeKeyWithIntegrity(name, kc, expectedHash); + + SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + makeDuplicateKey(name, kc); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testAddDuplicateKeyTests (newKeychainTests + checkNTests +makeKeyWithIntegrityTests + checkNTests + makeDuplicateKeyTests + checkNTests + 1) + +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); + //SecKeychainRef kc = newKeychain(name); + //checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + + //SecKeyRef key = makeFreeKey(name, kc); + //checkIntegrityHash(name, (SecKeychainItemRef) key, expectedHash); + //SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + + //makeDuplicateFreeKey(name, kc); + //checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + + //ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +//#define testAddDuplicateFreeKeyTests (newKeychainTests + checkNTests + makeFreeKeyTests + checkIntegrityHashTests + checkNTests \ +// + makeDuplicateKeyTests + checkNTests + 1) +#define testAddDuplicateFreeKeyTests 0 + +// testAddDuplicateKeyPair: +// +// By use of the Sec* APIs, you will almost certainly never get an +// errSecDuplicateItem out of SecKeychainGeneratePair. Since it sets a primary +// key attribute as the hash of the public key, it just will never generate a +// duplicate item. + +static void testExportImportKeyPair() { + char* name = "testExportImportKeyPair"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); + + SecKeyRef pub; + SecKeyRef priv; + makeKeyPair(name, kc, &pub, &priv); + + // Now that we have the key pair, make sure we can pull the individual keys out + + SecKeyRef item; + item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + checkHashesMatch(name, (SecKeychainItemRef)pub, (SecKeychainItemRef)item); + + item = (SecKeyRef) checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + checkHashesMatch(name, (SecKeychainItemRef)priv, (SecKeychainItemRef)item); + + CFMutableArrayRef applications = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + SecTrustedApplicationRef app = NULL; + + ok_status(SecTrustedApplicationCreateFromPath(NULL, &app), "%s: SecTrustedApplicationCreateFromPath", name); + CFArrayAppendValue(applications, app); + + ok_status(SecTrustedApplicationCreateFromPath("/usr/bin/codesign", &app), "%s: SecTrustedApplicationCreateFromPath", name); + CFArrayAppendValue(applications, app); + + SecAccessRef accessRef = NULL; + ok_status(SecAccessCreate(CFSTR("accessDescription"), applications, &accessRef), "%s: SecAccessCreate", name); + + const SecItemImportExportKeyParameters keyParams = + { + SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, + 0, + CFSTR( "" ), + CFSTR( "" ), + CFSTR( "" ), + accessRef, 0, 0 + }; + CFArrayRef items = NULL; + + CFDataRef keyData = NULL; + ok_status(SecItemExport(pub, kSecFormatPEMSequence, kSecItemPemArmour, &keyParams, &keyData), "%s: SecItemExport", name); + ok_status(SecKeychainItemDelete((SecKeychainItemRef)pub), "%s: SecKeychainDelete", name);; + CFRelease(pub); + pub = NULL; + + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + ok_status(SecItemImport(keyData, NULL, NULL, NULL, kSecItemPemArmour, &keyParams, kc, &items), "%s: SecItemImport", name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + + + ok_status(SecItemExport(priv, kSecFormatPEMSequence, kSecItemPemArmour, &keyParams, &keyData), "%s: SecItemExport", name); + ok_status(SecKeychainItemDelete((SecKeychainItemRef)priv), "%s: SecKeychainDelete", name);; + CFRelease(priv); + priv = NULL; + + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); + + ok_status(SecItemImport(keyData, NULL, NULL, NULL, kSecItemPemArmour, &keyParams, kc, &items), "%s: SecItemImport", name); + + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + + SecAccessRef newRef = NULL; + ok_status(SecKeychainItemCopyAccess((SecKeychainItemRef) CFArrayGetValueAtIndex(items, 0), &newRef), "%s:SecKeychainItemCopyAccess", name); + + SecKeyRef importedKey = items && CFArrayGetCount(items) > 0 ? (SecKeyRef)CFArrayGetValueAtIndex(items, 0) : NULL; + if (importedKey) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(query, kSecClass, kSecClassKey); + CFDictionaryAddValue(query, kSecValueRef, importedKey); + + CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attrs, kSecAttrLabel, CFSTR("private key custom label")); + + ok_status( SecItemUpdate(query, attrs), "%s: SecItemUpdate", name); + } else { + fail("%s: Didn't have an item to update", name); + } + + ok_status(SecKeychainItemCopyAccess((SecKeychainItemRef) CFArrayGetValueAtIndex(items, 0), &newRef), "%s:SecKeychainItemCopyAccess", name); + // TODO: should probably check this AccessRef object to make sure it's simple + + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testExportImportKeyPairTests (newKeychainTests + checkNTests + checkNTests + makeKeyPairTests \ + + checkNTests + checkHashesMatchTests \ + + checkNTests + checkHashesMatchTests \ + + 5 + checkNTests + 1 + checkNTests \ + + 2 + checkNTests + 1 + checkNTests + 1 + 1 + 1 + checkNTests\ + + 1) + + +#else + +#endif /* TARGET_OS_MAC */ + + +#endif /* kc_30_xara_key_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h b/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h new file mode 100644 index 00000000..e76f69af --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h @@ -0,0 +1,2459 @@ +/* + * 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 kc_30_xara_upgrade_helpers_h +#define kc_30_xara_upgrade_helpers_h + +#if TARGET_OS_MAC + +#include "kc-30-xara-helpers.h" +#include "kc-30-xara-item-helpers.h" +#include "kc-30-xara-key-helpers.h" + +static void makeOldKeychainBlob() { + char* name = "makeOldKeychainBlob"; + + SecKeychainRef kc = newKeychain(keychainName); + + makeItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + makeItem(name, kc, kSecClassInternetPassword, CFSTR("test_internet")); + makeKey(name, kc); + makeKeyPair(name, kc, NULL, NULL); +} + +static void makeEmptyKeychainBlob() { + char * name = "makeEmptyKeychainBlob"; + SecKeychainRef kc = newKeychain(keychainName); +} + +// To construct, use the function above. + + +#define OLD_KEYCHAIN_SIZE 27156 +uint8_t old_keychain[OLD_KEYCHAIN_SIZE] = { + 0x6b, 0x79, 0x63, 0x68, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x69, 0xfc, 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, 0x4d, 0x3c, 0x00, 0x00, 0x55, 0xa4, 0x00, 0x00, 0x63, 0xbc, + 0x00, 0x00, 0x65, 0x6c, 0x00, 0x00, 0x68, 0x54, 0x00, 0x00, 0x69, 0x14, 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, 0x05, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb5, 0x00, 0x00, 0x01, 0xb9, 0x00, 0x00, 0x01, 0xc5, 0x00, 0x00, 0x01, 0xc9, + 0x00, 0x00, 0x01, 0xcd, 0x00, 0x00, 0x01, 0xd1, 0x00, 0x00, 0x01, 0xd5, 0x00, 0x00, 0x01, 0xed, 0x00, 0x00, 0x01, 0xf1, + 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x02, 0x35, + 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x02, 0x51, + 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x02, 0x65, + 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x02, 0x6d, 0x00, 0x00, 0x02, 0x71, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x01, 0x30, 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, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x81, 0x89, 0x02, + 0x81, 0x81, 0x00, 0xd4, 0x4e, 0x0c, 0xf2, 0x39, 0xe4, 0x7c, 0x2c, 0x3c, 0x55, 0x12, 0xc3, 0x50, 0xd9, 0x32, 0x25, 0x96, + 0x93, 0x19, 0xd7, 0x6a, 0x0b, 0xfc, 0x3a, 0x3a, 0x46, 0x0e, 0xaa, 0x0c, 0x06, 0xe9, 0x51, 0x4b, 0x9e, 0x0a, 0x98, 0x25, + 0x59, 0x82, 0x85, 0x11, 0x9b, 0x47, 0xa9, 0xcc, 0x95, 0xea, 0xa5, 0x49, 0xc4, 0xdc, 0x5f, 0x1c, 0x92, 0x2b, 0x94, 0x8b, + 0x2a, 0xd8, 0xa5, 0xf0, 0xb1, 0x1e, 0x6e, 0xcf, 0x97, 0x00, 0xd3, 0x15, 0x55, 0xfb, 0x2b, 0x5c, 0x03, 0xc7, 0x1b, 0x26, + 0x88, 0x7b, 0x24, 0x14, 0xde, 0x4a, 0x62, 0xe6, 0x0b, 0x8f, 0xa9, 0x47, 0x1d, 0x13, 0x63, 0x42, 0x28, 0xde, 0xb9, 0xc3, + 0xe6, 0x2f, 0xaa, 0xcf, 0x71, 0x42, 0x0d, 0x2c, 0x58, 0x88, 0x43, 0x70, 0x9e, 0x8a, 0x88, 0x4d, 0x71, 0x50, 0x0b, 0x7f, + 0xe3, 0x37, 0x0b, 0x48, 0x07, 0x81, 0x91, 0x3e, 0x89, 0x8d, 0xb5, 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, 0x87, 0xed, 0xfc, 0x63, 0xc2, 0xda, 0x29, 0x2e, + 0x20, 0x2d, 0x2f, 0x15, 0xd3, 0xd0, 0xba, 0x70, 0x6a, 0x79, 0xef, 0x6f, 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, 0x02, 0xc8, + 0x00, 0x00, 0x03, 0x74, 0x00, 0x00, 0x03, 0xb0, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x28, + 0x00, 0x00, 0x04, 0x50, 0x00, 0x00, 0x04, 0x78, 0x00, 0x00, 0x04, 0xa0, 0x00, 0x00, 0x04, 0xc8, 0x00, 0x00, 0x04, 0xf0, + 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, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x87, 0xed, 0xfc, 0x63, 0xc2, 0xda, 0x29, 0x2e, 0x20, 0x2d, 0x2f, 0x15, + 0xd3, 0xd0, 0xba, 0x70, 0x6a, 0x79, 0xef, 0x6f, 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, 0x03, 0x94, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x87, 0xed, 0xfc, 0x63, 0xc2, 0xda, 0x29, 0x2e, + 0x20, 0x2d, 0x2f, 0x15, 0xd3, 0xd0, 0xba, 0x70, 0x6a, 0x79, 0xef, 0x6f, 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, 0x03, 0xd0, + 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, 0x03, 0xf8, + 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, 0x04, 0x20, + 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, 0x04, 0x48, + 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, 0x04, 0x70, + 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, 0x04, 0x98, + 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, 0x04, 0xc0, + 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, 0x04, 0xe8, + 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, 0x05, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x68, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x05, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x05, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x09, 0x00, 0x00, 0x05, 0x15, + 0x00, 0x00, 0x05, 0x19, 0x00, 0x00, 0x05, 0x1d, 0x00, 0x00, 0x05, 0x21, 0x00, 0x00, 0x05, 0x25, 0x00, 0x00, 0x05, 0x3d, + 0x00, 0x00, 0x05, 0x41, 0x00, 0x00, 0x05, 0x6d, 0x00, 0x00, 0x05, 0x71, 0x00, 0x00, 0x05, 0x75, 0x00, 0x00, 0x05, 0x79, + 0x00, 0x00, 0x05, 0x85, 0x00, 0x00, 0x05, 0x91, 0x00, 0x00, 0x05, 0x95, 0x00, 0x00, 0x05, 0x99, 0x00, 0x00, 0x05, 0x9d, + 0x00, 0x00, 0x05, 0xa1, 0x00, 0x00, 0x05, 0xa5, 0x00, 0x00, 0x05, 0xa9, 0x00, 0x00, 0x05, 0xad, 0x00, 0x00, 0x05, 0xb1, + 0x00, 0x00, 0x05, 0xb5, 0x00, 0x00, 0x05, 0xb9, 0x00, 0x00, 0x05, 0xbd, 0x00, 0x00, 0x05, 0xc1, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x04, 0x80, 0x4d, 0xe7, 0x2e, 0xeb, 0x28, 0x75, 0xea, 0x76, + 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, 0x68, 0xd0, 0x7a, 0xd6, 0xa3, 0x4a, 0xf5, 0x07, + 0x45, 0x6f, 0x01, 0xd8, 0x34, 0xe2, 0xed, 0xb0, 0x02, 0x21, 0xc4, 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, 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, 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, 0xd0, 0x26, 0xd5, 0xcb, 0xf3, 0xec, 0xb5, 0xf3, 0x7a, 0xe0, 0xa5, 0x0b, + 0x85, 0xfb, 0xe9, 0x27, 0xad, 0x6b, 0xcb, 0x08, 0x00, 0x00, 0x00, 0xa0, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6b, + 0x6d, 0x6f, 0x77, 0x65, 0x72, 0x79, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2f, 0x44, 0x65, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x72, 0x2f, 0x58, 0x63, 0x6f, 0x64, 0x65, 0x2f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x44, 0x61, + 0x74, 0x61, 0x2f, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2d, 0x66, 0x6b, 0x77, 0x77, 0x63, 0x6e, 0x64, 0x64, + 0x69, 0x6a, 0x74, 0x6e, 0x67, 0x66, 0x61, 0x73, 0x6c, 0x76, 0x73, 0x65, 0x64, 0x76, 0x67, 0x79, 0x7a, 0x62, 0x6f, 0x75, + 0x2f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x2f, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x2f, 0x73, 0x65, 0x63, 0x74, 0x65, 0x73, 0x74, 0x73, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x9e, 0xb6, 0x1a, 0xd8, 0x81, 0xf8, 0xeb, 0x0f, + 0x48, 0x82, 0x1e, 0x61, 0x7f, 0xbf, 0x70, 0x34, 0xfe, 0x79, 0x0f, 0x0c, 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, 0x00, 0x00, 0x00, 0x10, 0xbf, 0x03, 0x5e, 0xa2, 0x83, 0x29, 0x8b, + 0xb9, 0x25, 0x5e, 0x8c, 0x68, 0x3a, 0x48, 0x62, 0x36, 0x18, 0x97, 0x5f, 0xdc, 0x2b, 0x06, 0x1f, 0x38, 0x3f, 0x56, 0xa7, + 0x6c, 0xcc, 0xf4, 0x75, 0xad, 0xc8, 0x1d, 0x16, 0x3d, 0x26, 0xfc, 0x76, 0xc5, 0xd4, 0x9b, 0xbf, 0xe9, 0x3e, 0xf7, 0x9e, + 0x23, 0xd6, 0x71, 0xf8, 0x83, 0xc4, 0x88, 0xd3, 0x94, 0xe1, 0x3d, 0xf5, 0x9f, 0xd7, 0x43, 0x91, 0x9e, 0x31, 0x7f, 0x21, + 0x9e, 0xe6, 0x09, 0xfc, 0x8f, 0xbb, 0x84, 0x40, 0xad, 0x49, 0xc2, 0xe2, 0x47, 0xb9, 0x5b, 0xcd, 0xc1, 0x48, 0x20, 0xf2, + 0xef, 0x53, 0x06, 0x30, 0xdd, 0xb6, 0xe4, 0x1b, 0x0d, 0x45, 0x06, 0x5a, 0xc5, 0xa0, 0xce, 0x32, 0xf8, 0x54, 0x99, 0x65, + 0x70, 0xe1, 0x9d, 0xb7, 0x90, 0x95, 0x0e, 0x60, 0x5b, 0xd9, 0x75, 0xd6, 0xd4, 0x29, 0xb4, 0x3f, 0x53, 0xa9, 0xc6, 0xbe, + 0x38, 0xf2, 0xe4, 0xd6, 0xc7, 0xff, 0x51, 0xae, 0x34, 0x9d, 0x73, 0x02, 0xfe, 0x1b, 0x10, 0x31, 0xdd, 0x63, 0x98, 0x3a, + 0x0c, 0xe1, 0xef, 0xbe, 0x18, 0xc2, 0x5e, 0xf4, 0x6f, 0xf2, 0xfc, 0x19, 0x2c, 0x59, 0x2f, 0x15, 0x70, 0x94, 0xa3, 0xc9, + 0x9c, 0x85, 0x89, 0x13, 0xca, 0xb2, 0xa7, 0x3a, 0x7c, 0xdb, 0xbf, 0x73, 0x3b, 0xf0, 0x92, 0xa8, 0x9c, 0x9e, 0x58, 0x31, + 0x95, 0x8d, 0x2f, 0x7e, 0x17, 0x7c, 0x83, 0xdf, 0x37, 0x34, 0xdb, 0x6d, 0x74, 0x19, 0x19, 0xb0, 0x2b, 0xf5, 0x5c, 0x95, + 0x10, 0x02, 0x48, 0xf9, 0x37, 0x66, 0x8d, 0x4d, 0xcd, 0x14, 0x82, 0xca, 0x2e, 0xe7, 0x29, 0xb0, 0x18, 0x87, 0x39, 0xf4, + 0xf3, 0x9c, 0xee, 0xbe, 0xc2, 0xfc, 0x0a, 0xc6, 0x04, 0xbc, 0x78, 0xe9, 0xcc, 0xe2, 0x45, 0x34, 0xe7, 0xaa, 0x67, 0xc1, + 0x04, 0x83, 0xfd, 0x3f, 0x03, 0x13, 0x37, 0xba, 0x54, 0x1e, 0xb6, 0x2c, 0x5f, 0xc7, 0x11, 0xce, 0x82, 0x30, 0x2a, 0x25, + 0x48, 0xd5, 0x48, 0x2d, 0x78, 0x24, 0x42, 0xe9, 0x65, 0x2d, 0x2e, 0x5b, 0x45, 0x71, 0x1b, 0x17, 0xf4, 0x17, 0xae, 0x7c, + 0xf1, 0xba, 0x84, 0xa5, 0x28, 0xa2, 0xef, 0x19, 0x21, 0x01, 0x3f, 0x7d, 0x40, 0x46, 0xa1, 0xfa, 0x34, 0x71, 0x47, 0x10, + 0x71, 0x22, 0xce, 0x48, 0x05, 0x65, 0x82, 0x88, 0xb3, 0xcc, 0xba, 0x21, 0x2d, 0x8a, 0x6c, 0x4d, 0x9f, 0xfc, 0xea, 0x1d, + 0xd5, 0x1f, 0x41, 0x74, 0xe9, 0x95, 0x48, 0x65, 0x76, 0xe8, 0x03, 0x3b, 0x58, 0x66, 0xef, 0x14, 0xd6, 0x39, 0xa4, 0xd7, + 0x8c, 0xbc, 0x00, 0xac, 0x60, 0x3f, 0x4c, 0xf4, 0xc9, 0x44, 0x9d, 0x82, 0x96, 0x26, 0xec, 0x45, 0xf2, 0x85, 0xe6, 0xe8, + 0x60, 0xae, 0x24, 0xd9, 0x2d, 0xf5, 0xc9, 0x3e, 0xb9, 0x21, 0x39, 0xec, 0xea, 0xc3, 0x64, 0x32, 0x0a, 0xd6, 0x7b, 0x49, + 0x5a, 0x48, 0x44, 0x44, 0x8a, 0x2e, 0xde, 0x70, 0xf1, 0xcf, 0x72, 0x24, 0x78, 0x19, 0xfd, 0x5a, 0xb9, 0xdb, 0xc6, 0x34, + 0xe0, 0x45, 0x0f, 0x01, 0x86, 0x34, 0xec, 0xa0, 0xd1, 0x74, 0x5a, 0x85, 0x8f, 0xf2, 0x9a, 0xc4, 0xdd, 0x48, 0x06, 0xfa, + 0x13, 0xae, 0x83, 0xd9, 0xca, 0x8d, 0xdf, 0xb7, 0x3d, 0xe9, 0x7c, 0x78, 0x97, 0xd6, 0x30, 0xbd, 0x6b, 0xdd, 0xb4, 0x4b, + 0xda, 0x9d, 0xe8, 0x98, 0x0f, 0xc1, 0xef, 0x7d, 0x69, 0xe0, 0x31, 0xbd, 0x63, 0xc8, 0x7c, 0x03, 0x52, 0x5e, 0xb9, 0x28, + 0x51, 0xac, 0xc8, 0x32, 0xb2, 0x20, 0x5b, 0xa4, 0x10, 0x6f, 0xfb, 0x2e, 0xa7, 0x69, 0x0f, 0x8f, 0x9e, 0xeb, 0x5f, 0x7e, + 0x1a, 0x67, 0x7e, 0x63, 0xc2, 0x20, 0x11, 0x92, 0x1d, 0x68, 0x77, 0x92, 0x70, 0x91, 0xdf, 0x7d, 0x36, 0x54, 0xe2, 0x7a, + 0xbc, 0xdb, 0xd4, 0x3c, 0xde, 0x17, 0x46, 0x7a, 0x9b, 0x97, 0xf2, 0xe7, 0xfb, 0x25, 0xfa, 0xcc, 0x98, 0x10, 0xf7, 0x55, + 0xa1, 0x6f, 0x81, 0x77, 0x57, 0x97, 0x56, 0xdb, 0xaf, 0x34, 0x4d, 0x0e, 0x1f, 0x1c, 0x80, 0x2c, 0x47, 0xba, 0xc2, 0x18, + 0xe6, 0x28, 0x1d, 0x61, 0x17, 0x38, 0xba, 0xfe, 0x19, 0x59, 0x0a, 0x42, 0x89, 0xc5, 0x72, 0x78, 0xd1, 0x75, 0xc2, 0xaf, + 0x7b, 0x8a, 0x61, 0x96, 0xf2, 0x07, 0xd8, 0xb7, 0xd6, 0x33, 0x45, 0xe9, 0xc7, 0x7b, 0x78, 0x8f, 0x60, 0x22, 0xe5, 0x70, + 0x81, 0x28, 0xe9, 0x03, 0x8b, 0x57, 0x0f, 0xf4, 0xb7, 0x3d, 0xda, 0xaa, 0x43, 0xe0, 0xb1, 0xe0, 0x9f, 0xa5, 0xeb, 0xe2, + 0xf4, 0x08, 0xb8, 0xe5, 0x84, 0x91, 0x0c, 0x0d, 0xa9, 0xef, 0xf0, 0x8a, 0x8c, 0x08, 0xf3, 0x04, 0xa5, 0xb8, 0x96, 0xe4, + 0x04, 0xa0, 0x21, 0xf5, 0x2a, 0x82, 0x28, 0x56, 0x4d, 0x05, 0xd9, 0x67, 0xe3, 0xb8, 0x47, 0x7c, 0xcd, 0x30, 0x32, 0xa8, + 0xde, 0x84, 0xe2, 0xcf, 0x75, 0xde, 0x48, 0x6f, 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, 0x87, 0xed, 0xfc, 0x63, 0xc2, 0xda, 0x29, 0x2e, 0x20, 0x2d, 0x2f, 0x15, 0xd3, 0xd0, 0xba, 0x70, + 0x6a, 0x79, 0xef, 0x6f, 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, 0x06, 0x18, 0x00, 0x00, 0x06, 0xc4, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x07, 0x28, 0x00, 0x00, 0x07, 0x50, 0x00, 0x00, 0x07, 0x78, 0x00, 0x00, 0x07, 0xa0, 0x00, 0x00, 0x07, 0xc8, + 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, 0x08, 0x40, 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, 0x06, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, + 0x87, 0xed, 0xfc, 0x63, 0xc2, 0xda, 0x29, 0x2e, 0x20, 0x2d, 0x2f, 0x15, 0xd3, 0xd0, 0xba, 0x70, 0x6a, 0x79, 0xef, 0x6f, + 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, 0x06, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x14, 0x87, 0xed, 0xfc, 0x63, 0xc2, 0xda, 0x29, 0x2e, 0x20, 0x2d, 0x2f, 0x15, 0xd3, 0xd0, 0xba, 0x70, + 0x6a, 0x79, 0xef, 0x6f, 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, 0x07, 0x20, 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, 0x07, 0x48, 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, 0x07, 0x70, 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, 0x07, 0x98, 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, 0x07, 0xc0, 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, 0x07, 0xe8, 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, 0x08, 0x10, 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, 0x08, 0x38, 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, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x09, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x03, 0xb0, + 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x03, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xbd, 0x00, 0x00, 0x02, 0xc1, 0x00, 0x00, 0x02, 0xd9, + 0x00, 0x00, 0x02, 0xdd, 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0x00, 0x00, 0x02, 0xe9, 0x00, 0x00, 0x03, 0x01, + 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x03, 0x39, 0x00, 0x00, 0x03, 0x3d, + 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x03, 0x5d, 0x00, 0x00, 0x03, 0x61, + 0x00, 0x00, 0x03, 0x65, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x03, 0x71, 0x00, 0x00, 0x03, 0x75, + 0x00, 0x00, 0x03, 0x79, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x03, 0x85, 0xfa, 0xde, 0x07, 0x11, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x38, 0xf9, 0x14, 0xd9, 0xbc, 0x64, 0x68, 0x1f, 0x33, + 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, 0x76, 0xa9, 0xa7, 0xd2, 0x92, 0xab, 0x56, 0xf5, + 0xdd, 0x6f, 0xaf, 0x4f, 0xcf, 0x11, 0x97, 0x41, 0x5d, 0xa1, 0xb6, 0x8c, 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, 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, 0x74, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x14, 0xd0, 0x26, 0xd5, 0xcb, 0xf3, 0xec, 0xb5, 0xf3, 0x7a, 0xe0, 0xa5, 0x0b, 0x85, 0xfb, 0xe9, 0x27, + 0xad, 0x6b, 0xcb, 0x08, 0x00, 0x00, 0x00, 0xa0, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6b, 0x6d, 0x6f, 0x77, 0x65, + 0x72, 0x79, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2f, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x72, + 0x2f, 0x58, 0x63, 0x6f, 0x64, 0x65, 0x2f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x2f, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2d, 0x66, 0x6b, 0x77, 0x77, 0x63, 0x6e, 0x64, 0x64, 0x69, 0x6a, 0x74, 0x6e, + 0x67, 0x66, 0x61, 0x73, 0x6c, 0x76, 0x73, 0x65, 0x64, 0x76, 0x67, 0x79, 0x7a, 0x62, 0x6f, 0x75, 0x2f, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x2f, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x44, 0x65, 0x62, 0x75, 0x67, 0x2f, 0x73, 0x65, + 0x63, 0x74, 0x65, 0x73, 0x74, 0x73, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x9e, 0xb6, 0x1a, 0xd8, 0x81, 0xf8, 0xeb, 0x0f, 0x48, 0x82, 0x1e, 0x61, + 0x7f, 0xbf, 0x70, 0x34, 0xfe, 0x79, 0x0f, 0x0c, 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, 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, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x00, 0x79, 0x0f, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x65, 0x72, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xc7, 0xed, 0x1f, + 0x0a, 0x54, 0x55, 0x75, 0x72, 0x54, 0xdc, 0xa1, 0xdd, 0x25, 0x06, 0x05, 0xe4, 0x28, 0xd2, 0xa6, 0x3f, 0xd9, 0x4b, 0x31, + 0x6c, 0x51, 0xc4, 0x66, 0x15, 0x89, 0x6b, 0x13, 0xe6, 0xa0, 0x68, 0x80, 0x3a, 0x98, 0x7a, 0xf9, 0xf7, 0xff, 0xf6, 0x1d, + 0x83, 0xea, 0x7d, 0xcc, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x27, 0xac, 0x7c, 0xe7, + 0x33, 0x91, 0xec, 0xb3, 0x6c, 0xd8, 0x39, 0x5d, 0x0f, 0xe7, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x27, 0xac, 0x7c, 0xe7, + 0x33, 0x91, 0xec, 0xb3, 0x6c, 0xd8, 0x39, 0x5d, 0x0f, 0xe7, 0xd0, 0x16, 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, 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xbd, 0x00, 0x00, 0x02, 0xc1, + 0x00, 0x00, 0x02, 0xd9, 0x00, 0x00, 0x02, 0xdd, 0x00, 0x00, 0x02, 0xe1, 0x00, 0x00, 0x02, 0xe5, 0x00, 0x00, 0x02, 0xe9, + 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x03, 0x39, + 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x03, 0x5d, + 0x00, 0x00, 0x03, 0x61, 0x00, 0x00, 0x03, 0x65, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x03, 0x71, + 0x00, 0x00, 0x03, 0x75, 0x00, 0x00, 0x03, 0x79, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x03, 0x85, + 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x38, 0x79, 0x5d, 0xed, 0xf8, + 0xaa, 0xc7, 0x19, 0xb2, 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, 0xf7, 0x4c, 0xfe, 0xd4, + 0x22, 0x15, 0x24, 0xbd, 0x72, 0xf0, 0x9f, 0x69, 0x4c, 0x60, 0xc4, 0x14, 0x19, 0x5e, 0x12, 0x8e, 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, 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, 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, 0xd0, 0x26, 0xd5, 0xcb, 0xf3, 0xec, 0xb5, 0xf3, 0x7a, 0xe0, 0xa5, 0x0b, + 0x85, 0xfb, 0xe9, 0x27, 0xad, 0x6b, 0xcb, 0x08, 0x00, 0x00, 0x00, 0xa0, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, 0x6b, + 0x6d, 0x6f, 0x77, 0x65, 0x72, 0x79, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2f, 0x44, 0x65, 0x76, 0x65, 0x6c, + 0x6f, 0x70, 0x65, 0x72, 0x2f, 0x58, 0x63, 0x6f, 0x64, 0x65, 0x2f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x64, 0x44, 0x61, + 0x74, 0x61, 0x2f, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2d, 0x66, 0x6b, 0x77, 0x77, 0x63, 0x6e, 0x64, 0x64, + 0x69, 0x6a, 0x74, 0x6e, 0x67, 0x66, 0x61, 0x73, 0x6c, 0x76, 0x73, 0x65, 0x64, 0x76, 0x67, 0x79, 0x7a, 0x62, 0x6f, 0x75, + 0x2f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x2f, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2f, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x2f, 0x73, 0x65, 0x63, 0x74, 0x65, 0x73, 0x74, 0x73, 0x00, 0x00, 0xfa, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x14, 0x9e, 0xb6, 0x1a, 0xd8, 0x81, 0xf8, 0xeb, 0x0f, + 0x48, 0x82, 0x1e, 0x61, 0x7f, 0xbf, 0x70, 0x34, 0xfe, 0x79, 0x0f, 0x0c, 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, 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, 0x00, + 0xa9, 0xe4, 0x6b, 0xff, 0xbd, 0x0a, 0x91, 0xb9, 0xf0, 0x78, 0x17, 0x8d, 0xeb, 0x55, 0x69, 0xde, 0xc1, 0xf1, 0x39, 0x5e, + 0x43, 0xd3, 0x79, 0x0c, 0xab, 0xa6, 0xde, 0x3e, 0xd0, 0x1a, 0xd7, 0xe1, 0x44, 0x98, 0x45, 0x91, 0xf5, 0xcd, 0xe4, 0xd4, + 0xc6, 0x16, 0x64, 0xb6, 0x5d, 0x68, 0x49, 0xbe, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0xeb, 0xaf, 0xaf, 0x2c, 0xe6, 0x5f, 0xab, 0xec, 0x72, 0x2f, 0x6c, 0xfc, 0x22, 0xa9, 0xe6, 0xfb, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, + 0xeb, 0xaf, 0xaf, 0x2c, 0xe6, 0x5f, 0xab, 0xec, 0x72, 0x2f, 0x6c, 0xfc, 0x22, 0xa9, 0xe6, 0xfb, 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, 0x0c, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x51, + 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x01, 0x61, 0x00, 0x00, 0x01, 0x65, 0x00, 0x00, 0x01, 0x69, 0x00, 0x00, 0x01, 0x6d, + 0x00, 0x00, 0x01, 0x71, 0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, 0x89, 0x00, 0x00, 0x01, 0xb5, 0x00, 0x00, 0x01, 0xb9, + 0x00, 0x00, 0x01, 0xbd, 0x00, 0x00, 0x01, 0xc1, 0x00, 0x00, 0x01, 0xcd, 0x00, 0x00, 0x01, 0xd9, 0x00, 0x00, 0x01, 0xdd, + 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0xe5, 0x00, 0x00, 0x01, 0xe9, 0x00, 0x00, 0x01, 0xed, 0x00, 0x00, 0x01, 0xf1, + 0x00, 0x00, 0x01, 0xf5, 0x00, 0x00, 0x01, 0xf9, 0x00, 0x00, 0x01, 0xfd, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x05, + 0x00, 0x00, 0x02, 0x09, 0xfa, 0xde, 0x07, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xcc, + 0x4f, 0xe4, 0x4f, 0x25, 0xad, 0xdc, 0x03, 0x14, 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, + 0x08, 0xf4, 0x15, 0x78, 0xc1, 0xb3, 0xa6, 0x63, 0xf6, 0xd7, 0x8c, 0x65, 0xbb, 0xc1, 0xf5, 0x2a, 0xbc, 0xbd, 0xcf, 0x55, + 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, 0x2a, 0x16, 0x0c, 0x08, 0xa9, 0xd5, 0x9c, 0x76, 0x5d, 0xd5, 0xfd, 0xcf, + 0x19, 0xdc, 0xee, 0x1e, 0x12, 0xcd, 0xa3, 0x95, 0xd3, 0xc7, 0x5c, 0x36, 0xa2, 0x71, 0xd6, 0xd9, 0x1a, 0xd6, 0x7a, 0x14, + 0xb0, 0x2a, 0xa2, 0x1d, 0x14, 0xe9, 0xd7, 0xdf, 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, 0x09, 0x78, 0x00, 0x00, 0x0b, 0x10, 0x00, 0x00, 0x0b, 0x90, 0x00, 0x00, 0x0b, 0xd8, + 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x0c, 0x68, 0x00, 0x00, 0x0c, 0xb0, 0x00, 0x00, 0x0c, 0xf8, 0x00, 0x00, 0x0d, 0x40, + 0x00, 0x00, 0x0d, 0x88, 0x00, 0x00, 0x0d, 0xd0, 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, 0x09, 0xc4, 0x00, 0x00, 0x0a, 0x34, 0x00, 0x00, 0x0a, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x27, 0xac, 0x7c, 0xe7, + 0x33, 0x91, 0xec, 0xb3, 0x6c, 0xd8, 0x39, 0x5d, 0x0f, 0xe7, 0xd0, 0x16, 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, 0xeb, 0xaf, 0xaf, 0x2c, 0xe6, 0x5f, 0xab, 0xec, 0x72, 0x2f, 0x6c, 0xfc, + 0x22, 0xa9, 0xe6, 0xfb, 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, 0x0b, 0x40, 0x00, 0x00, 0x0b, 0x5c, 0x00, 0x00, 0x0b, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, 0x73, 0x73, 0x67, 0x70, 0x27, 0xac, 0x7c, 0xe7, + 0x33, 0x91, 0xec, 0xb3, 0x6c, 0xd8, 0x39, 0x5d, 0x0f, 0xe7, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x14, + 0x73, 0x73, 0x67, 0x70, 0xeb, 0xaf, 0xaf, 0x2c, 0xe6, 0x5f, 0xab, 0xec, 0x72, 0x2f, 0x6c, 0xfc, 0x22, 0xa9, 0xe6, 0xfb, + 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, 0x0b, 0xc0, 0x00, 0x00, 0x0b, 0xc8, 0x00, 0x00, 0x0b, 0xd0, + 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, 0x0c, 0x08, 0x00, 0x00, 0x0c, 0x10, 0x00, 0x00, 0x0c, 0x18, 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, 0x0c, 0x50, 0x00, 0x00, 0x0c, 0x58, + 0x00, 0x00, 0x0c, 0x60, 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, 0x0c, 0x98, 0x00, 0x00, 0x0c, 0xa0, 0x00, 0x00, 0x0c, 0xa8, 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, 0x0c, 0xe0, + 0x00, 0x00, 0x0c, 0xe8, 0x00, 0x00, 0x0c, 0xf0, 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, 0x0d, 0x28, 0x00, 0x00, 0x0d, 0x30, 0x00, 0x00, 0x0d, 0x38, + 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, 0x0d, 0x70, 0x00, 0x00, 0x0d, 0x78, 0x00, 0x00, 0x0d, 0x80, 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, 0x0d, 0xb8, 0x00, 0x00, 0x0d, 0xc0, + 0x00, 0x00, 0x0d, 0xc8, 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, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0e, 0x10, 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, 0xb0, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcc, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x67, 0x70, 0x27, 0xac, 0x7c, 0xe7, + 0x33, 0x91, 0xec, 0xb3, 0x6c, 0xd8, 0x39, 0x5d, 0x0f, 0xe7, 0xd0, 0x16, 0x6a, 0x69, 0x78, 0x1c, 0x10, 0x7c, 0x4e, 0x50, + 0x83, 0xda, 0xfe, 0xe6, 0x75, 0x23, 0x03, 0x85, 0x32, 0x30, 0x31, 0x35, 0x31, 0x30, 0x32, 0x32, 0x30, 0x30, 0x32, 0x30, + 0x30, 0x35, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x35, 0x31, 0x30, 0x32, 0x32, 0x30, 0x30, 0x32, 0x30, 0x30, 0x35, 0x5a, 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, 0x00, + 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x7c, 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, 0x24, + 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, 0x68, 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, 0x9c, + 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, 0xe8, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xf8, + 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, 0x00, 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, 0xc1, 0x00, 0x00, 0x00, 0xd1, + 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0xf5, + 0x73, 0x73, 0x67, 0x70, 0xeb, 0xaf, 0xaf, 0x2c, 0xe6, 0x5f, 0xab, 0xec, 0x72, 0x2f, 0x6c, 0xfc, 0x22, 0xa9, 0xe6, 0xfb, + 0xdf, 0x72, 0xf0, 0xdf, 0xa9, 0x85, 0x5d, 0x23, 0x8b, 0xda, 0x17, 0x65, 0xba, 0x8f, 0x50, 0x00, 0x32, 0x30, 0x31, 0x35, + 0x31, 0x30, 0x32, 0x32, 0x30, 0x30, 0x32, 0x30, 0x30, 0x35, 0x5a, 0x00, 0x32, 0x30, 0x31, 0x35, 0x31, 0x30, 0x32, 0x32, + 0x30, 0x30, 0x32, 0x30, 0x30, 0x35, 0x5a, 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, 0x40, 0x00, 0x00, 0x01, 0xb4, + 0x00, 0x00, 0x01, 0xe8, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x02, 0x98, + 0x00, 0x00, 0x02, 0xc0, 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, 0x78, 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, 0xd4, 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, 0x08, + 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, 0x30, + 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, 0x64, 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, 0x8c, 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, 0xb8, 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, 0xe0, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xa8, 0x19, 0x97, 0x6c, 0x2b, 0xfc, 0xe9, 0xba, 0xa4, + 0xdf, 0xb7, 0x21, 0x4a, 0xce, 0xe1, 0xe0, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x00, 0x00, 0x00, + 0x56, 0x42, 0x97, 0xed, 0x96, 0x15, 0xb9, 0x6f, 0x06, 0xea, 0xe4, 0xcd, 0xef, 0x26, 0x37, 0xf3, 0x91, 0xd5, 0xba, 0x45, + 0x93, 0xbf, 0x9a, 0x1a, 0x1f, 0xff, 0x64, 0x04, 0xfe, 0x94, 0x64, 0x23, 0x20, 0x8d, 0xdd, 0xa7, 0x1a, 0xe6, 0x3d, 0x29, + 0xef, 0x66, 0x0a, 0xaf, 0xa8, 0xc0, 0x09, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xaf, 0xd4, 0xa6, 0x01, 0x00, 0x00, 0x00, 0x0b, 0xe0, 0xd0, 0xcb, + 0x7b, 0x98, 0x07, 0xb1, 0x21, 0x3d, 0xc5, 0x31, 0x8d, 0xf2, 0xf7, 0xe6, 0xc2, 0x6f, 0xeb, 0x94, 0x75, 0x6b, 0x83, 0xee, + 0x70, 0x90, 0x3e, 0x81, 0x43, 0xcb, 0xe3, 0xc4, 0xb3, 0xee, 0x68, 0x22, 0xff, 0x1f, 0x01, 0x5f, 0xa2, 0xd9, 0x5d, 0xd3, + 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, + 0x00, 0x00, 0x4f, 0xd4, 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, 0x49, 0x9c, 0x00, 0x00, 0x4b, 0x14, 0x00, 0x00, 0x4c, 0x8c, + 0x00, 0x00, 0x4d, 0x0c, 0x00, 0x00, 0x4e, 0x2c, 0x00, 0x00, 0x4e, 0xec, 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, 0x01, 0x78, 0x00, 0x00, 0x00, 0x0f, 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, 0x01, 0x58, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, + 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x34, 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, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x00, 0x10, 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, 0x01, 0x58, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xb8, + 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x30, + 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x34, 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, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x00, 0x11, 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, 0x01, 0x58, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0xd0, + 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x48, + 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x34, 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, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x00, 0x00, 0x00, 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, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, + 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x61, 0x63, 0x63, 0x74, 0x73, 0x76, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x76, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x80, 0x00, 0x00, 0x01, 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, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xa8, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x30, + 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, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x61, 0x63, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x73, 0x64, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73, 0x72, 0x76, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x70, 0x74, 0x63, 0x6c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x61, 0x74, 0x79, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x70, 0x61, 0x74, 0x68, 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, 0x48, 0x3b, 0xd2, 0x09, + 0x80, 0x5b, 0x06, 0xbb, 0x77, 0xc2, 0xcd, 0xfc, 0x85, 0xd1, 0x19, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2c, + 0x01, 0x00, 0x00, 0x00, 0x56, 0x9a, 0xa0, 0x13, 0x51, 0xcd, 0x1c, 0xd6, 0x68, 0xba, 0xe9, 0x94, 0x4f, 0xf4, 0xe1, 0x5e, + 0x0b, 0xe6, 0x67, 0xfa, 0x0b, 0x7f, 0x15, 0xc5, 0x77, 0xe5, 0x6b, 0xf1, 0x01, 0x38, 0x30, 0x64, 0xef, 0x8e, 0x03, 0x62, + 0x5a, 0xe7, 0xe8, 0x44, 0x3e, 0x72, 0xdb, 0xbf, 0x63, 0x61, 0x3c, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2c, 0xd0, 0xaa, 0x02, 0xbb, 0x2a, 0x9b, 0x32, 0x9c, 0x69, 0xf9, 0xfe, 0x2f, 0x13, 0x3f, 0x14, 0xa0, 0xc4, 0x22, 0x27, + 0xb4, 0x22, 0xef, 0xf5, 0x0e, 0x98, 0x9c, 0xb2, 0x9b, 0x7b, 0x6e, 0x87, 0x83, 0xc7, 0x64, 0x6b, 0xd8, 0xff, 0xb9, 0xb5, + 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); +} + +#else + +#endif /* TARGET_OS_MAC */ + +#endif /* kc_30_xara_upgrade_helpers_h */ diff --git a/OSX/libsecurity_keychain/regressions/kc-30-xara.c b/OSX/libsecurity_keychain/regressions/kc-30-xara.c new file mode 100644 index 00000000..469aab65 --- /dev/null +++ b/OSX/libsecurity_keychain/regressions/kc-30-xara.c @@ -0,0 +1,657 @@ +/* + * 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 "keychain_regressions.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kc-30-xara-item-helpers.h" +#include "kc-30-xara-key-helpers.h" +#include "kc-30-xara-upgrade-helpers.h" + +#if TARGET_OS_MAC + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-function" + +/* Test basic add delete update copy matching stuff. */ + + +/* Standard memory functions required by CSSM. */ +static void *cssmMalloc(CSSM_SIZE size, void *allocRef) { return malloc(size); } +static void cssmFree(void *mem_ptr, void *allocRef) { free(mem_ptr); return; } +static void *cssmRealloc(void *ptr, CSSM_SIZE size, void *allocRef) { return realloc( ptr, size ); } +static void *cssmCalloc(uint32 num, CSSM_SIZE size, void *allocRef) { return calloc( num, size ); } +static CSSM_API_MEMORY_FUNCS memFuncs = { cssmMalloc, cssmFree, cssmRealloc, cssmCalloc, NULL }; + +static CSSM_DL_DB_HANDLE initializeDL() { + CSSM_VERSION version = { 2, 0 }; + CSSM_DL_DB_HANDLE dldbHandle; + CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } }; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + + ok_status(CSSM_Init(&version, CSSM_PRIVILEGE_SCOPE_NONE, &myGuid, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, NULL), "cssm_init"); + ok_status(CSSM_ModuleLoad(&gGuidAppleFileDL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL), "module_load"); + ok_status(CSSM_ModuleAttach(&gGuidAppleFileDL, &version, &memFuncs, 0, CSSM_SERVICE_DL, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &dldbHandle.DLHandle), "module_attach"); + + return dldbHandle; +} +#define initializeDLTests 3 + +static void unloadDL(CSSM_DL_DB_HANDLE* dldbHandle) { + ok_status(CSSM_ModuleDetach(dldbHandle->DLHandle), "detach"); + ok_status(CSSM_ModuleUnload(&gGuidAppleFileDL, NULL, NULL), "unload"); + ok_status(CSSM_Terminate(), "terminate"); +} +#define unloadDLTests 3 + +static void modifyAttributeInKeychain(char * name, CSSM_DL_DB_HANDLE dldbHandle, char * keychainName, CSSM_DB_RECORDTYPE recordType, char* attributeName, char* newValue, size_t len) { + CSSM_RETURN status = CSSM_OK; + ok_status(CSSM_DL_DbOpen(dldbHandle.DLHandle, keychainName, + NULL, + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL, /* Access cred? */ + NULL, /* Open Parameters? */ + &dldbHandle.DBHandle), "%s: CSSM_DL_DbOpen", name); + + CSSM_QUERY queryAll = {}; + queryAll.RecordType = recordType; + + CSSM_HANDLE results = 0; + CSSM_DATA data = {}; + CSSM_DB_UNIQUE_RECORD_PTR uniqueIdPtr = NULL; + + CSSM_DB_RECORD_ATTRIBUTE_DATA attributes = {}; + attributes.NumberOfAttributes = 1; + attributes.AttributeData = malloc(sizeof(CSSM_DB_ATTRIBUTE_DATA) * attributes.NumberOfAttributes); + attributes.AttributeData[0].Info.Label.AttributeName = attributeName; + attributes.AttributeData[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING; + + attributes.AttributeData[0].NumberOfValues = 1; + attributes.AttributeData[0].Value = malloc(sizeof(CSSM_DATA)*attributes.AttributeData[0].NumberOfValues); + + + status = CSSM_DL_DataGetFirst(dldbHandle, &queryAll, &results, &attributes, &data, &uniqueIdPtr); + while(status == CSSM_OK) { + // I'm sure it has one thing and that thing needs to change. + attributes.AttributeData[0].Value[0].Data = (void*)newValue; + attributes.AttributeData[0].Value[0].Length = strlen(newValue); + + CSSM_DL_DataModify(dldbHandle, + attributes.DataRecordType, + uniqueIdPtr, + &attributes, + NULL, // no data modification + CSSM_DB_MODIFY_ATTRIBUTE_REPLACE); + + CSSM_DL_FreeUniqueRecord(dldbHandle, uniqueIdPtr); + status = CSSM_DL_DataGetNext(dldbHandle, results, &attributes, &data, &uniqueIdPtr); + } + ok_status(CSSM_DL_DbClose(dldbHandle), "%s: CSSM_DL_DbClose", name); +} +#define modifyAttributeInKeychainTests 2 + +static void testAttackItem(CSSM_DL_DB_HANDLE dldbHandle) { + char * name = "testAttackItem"; + secdebugfunc("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(kc); + + char * modification = "evil_application"; + modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification)); + + kc = openKeychain(name); + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testAttackItemTests (newKeychainTests + checkNTests + makeItemWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1) + +static void testAttackKey(CSSM_DL_DB_HANDLE dldbHandle) { + char * name = "testAttackKey"; + secdebugfunc("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); + CFReleaseNull(kc); + + char * modification = "evil_application"; + modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_SYMMETRIC_KEY, "Label", modification, strlen(modification)); + + kc = openKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testAttackKeyTests (newKeychainTests + checkNTests + makeKeyWithIntegrityTests + checkNTests + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + 1) + + +static void testAddAfterCorruptItem(CSSM_DL_DB_HANDLE dldbHandle) { + char * name = "testAddAfterCorruptItem"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 0); + + makeCustomItemWithIntegrity(name, kc, kSecClassGenericPassword, CFSTR("test_label"), CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); + SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + CFReleaseNull(item); + + makeDuplicateItem(name, kc, kSecClassGenericPassword); + CFReleaseNull(kc); + + char * modification = "evil_application"; + modifyAttributeInKeychain(name, dldbHandle, keychainFile, CSSM_DL_DB_RECORD_GENERIC_PASSWORD, "PrintName", modification, strlen(modification)); + + kc = openKeychain(name); + 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); +} +#define testAddAfterCorruptItemTests (newKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeDuplicateItemTests \ + + modifyAttributeInKeychainTests + openKeychainTests + checkNTests + makeCustomItemWithIntegrityTests + checkNTests + makeCustomDuplicateItemTests + 1) + +static void testAddAfterCorruptKey(CSSM_DL_DB_HANDLE dldbHandle) { + char * name = "testAddAfterCorruptKey"; + secdebugfunc("integrity", "************************************* %s", name); + + SecKeychainRef kc = newKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); + + // Make a symmetric key + makeCustomKeyWithIntegrity(name, kc, CFSTR("test_key"), CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + + SecKeychainItemRef item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + makeCustomDuplicateKey(name, kc, CFSTR("test_key")); + CFReleaseNull(item); + + // Make a key pair + SecKeyRef pub; + SecKeyRef priv; + makeCustomKeyPair(name, kc, CFSTR("test_key_pair"), &pub, &priv); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + CFReleaseNull(pub); + CFReleaseNull(priv); + + 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)); + + kc = openKeychain(name); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 0); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 0); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 0); + + makeCustomKeyWithIntegrity(name, kc, CFSTR("evil_application"), CFSTR("ca6d90a0b053113e43bbb67f64030230c96537f77601f66bdf821d8684431dfc")); + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassSymmetric), 1); + + makeCustomDuplicateKey(name, kc, CFSTR("evil_application")); + + makeCustomKeyPair(name, kc, CFSTR("evil_application"), &pub, &priv); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPublic), 1); + checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + + // We cannot create a duplicate key pair, so don't try. + + CFReleaseNull(item); + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testAddAfterCorruptKeyTests (newKeychainTests \ + + checkNTests + checkNTests + checkNTests \ + + makeCustomKeyWithIntegrityTests + checkNTests + makeCustomDuplicateKeyTests \ + + makeCustomKeyPairTests + checkNTests + checkNTests \ + + 1 \ + + modifyAttributeInKeychainTests \ + + modifyAttributeInKeychainTests \ + + modifyAttributeInKeychainTests \ + + openKeychainTests \ + + checkNTests + checkNTests + checkNTests \ + + makeCustomKeyWithIntegrityTests + checkNTests \ + + makeCustomDuplicateKeyTests \ + + makeCustomKeyPairTests + checkNTests + checkNTests \ + + 1) + + +static void testKeychainUpgrade() { + char name[100]; + sprintf(name, "testKeychainUpgrade"); + secdebugfunc("integrity", "************************************* %s", name); + + writeOldKeychain(name, keychainFile); + SecKeychainRef kc = openCustomKeychain(name, "test.keychain", "password"); + + SecKeychainItemRef item; + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5")); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03")); + 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")); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d")); + + // Now close the keychain and open it again + CFReleaseNull(kc); + kc = openCustomKeychain(name, "test.keychain", "password"); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + checkIntegrityHash(name, item, CFSTR("39c56eadd3e3b496b6099e5f3d5ff88eaee9ca2e3a50c1be8319807a72e451e5")); + makeCustomDuplicateItem(name, kc, kSecClassGenericPassword, CFSTR("test_generic")); + + item = checkN(name, makeQueryItemDictionary(kc, kSecClassInternetPassword), 1); + checkIntegrityHash(name, item, CFSTR("4f1b64e3c156968916e72d8ff3f1a8eb78b32abe0b2b43f0578eb07c722aaf03")); + 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")); + + item = checkN(name, makeQueryKeyDictionary(kc, kSecAttrKeyClassPrivate), 1); + checkIntegrityHash(name, (SecKeychainItemRef) item, CFSTR("bdf219cdbc2dc6c4521cf39d1beda2e3491ef0330ba59eb41229dd909632f48d")); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testKeychainUpgradeTests (openCustomKeychainTests \ + + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + \ + + checkNTests + checkIntegrityHashTests + \ + + checkNTests + checkIntegrityHashTests + \ + + openCustomKeychainTests \ + + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests + makeCustomDuplicateItemTests \ + + checkNTests + checkIntegrityHashTests +\ + + checkNTests + checkIntegrityHashTests +\ + + checkNTests + checkIntegrityHashTests +\ + 1) + +static SecAccessRef makeUidAccess(uid_t uid) +{ + // make the "uid/gid" ACL subject + // this is a CSSM_LIST_ELEMENT chain + CSSM_ACL_PROCESS_SUBJECT_SELECTOR selector = { + CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION, // selector version + CSSM_ACL_MATCH_UID, // set mask: match uids (only) + uid, // uid to match + 0 // gid (not matched here) + }; + CSSM_LIST_ELEMENT subject2 = { NULL, 0 }; + subject2.Element.Word.Data = (UInt8 *)&selector; + subject2.Element.Word.Length = sizeof(selector); + CSSM_LIST_ELEMENT subject1 = { + &subject2, CSSM_ACL_SUBJECT_TYPE_PROCESS, CSSM_LIST_ELEMENT_WORDID + }; + + // rights granted (replace with individual list if desired) + CSSM_ACL_AUTHORIZATION_TAG rights[] = { + CSSM_ACL_AUTHORIZATION_ANY // everything + }; + // owner component (right to change ACL) + CSSM_ACL_OWNER_PROTOTYPE owner = { + // TypedSubject + { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, + // Delegate + false + }; + // ACL entries (any number, just one here) + CSSM_ACL_ENTRY_INFO acls[] = { + { + // prototype + { + // TypedSubject + { CSSM_LIST_TYPE_UNKNOWN, &subject1, &subject2 }, + false, // Delegate + // rights for this entry + { sizeof(rights) / sizeof(rights[0]), rights }, + // rest is defaulted + } + } + }; + + SecAccessRef access; + SecAccessCreateFromOwnerAndACL(&owner, sizeof(acls) / sizeof(acls[0]), acls, &access); + return access; +} + +static void checkAccessLength(const char * name, SecAccessRef access, int expected) { + CFArrayRef acllist = NULL; + ok_status(SecAccessCopyACLList(access, &acllist), "%s: SecAccessCopyACLList", name); + + // Count the number of non-integrity ACLs in this access + int aclsFound = 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 = CFRangeMake(0, CFArrayGetCount(auths)); + if(!CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationIntegrity) && + !CFArrayContainsValue(auths, searchrange, kSecACLAuthorizationPartitionID)) { + + aclsFound += 1; + } + + CFReleaseNull(auths); + } + + CFReleaseNull(acllist); + } + is(aclsFound, expected, "%s: ACL has correct number of entries", name); +} +#define checkAccessLengthTests 2 + +static void testUidAccess() { + char name[100]; + sprintf(name, "testUidAccess"); + secdebugfunc("integrity", "************************************* %s", name); + + SecAccessRef access = makeUidAccess(getuid()); + + SecKeychainRef kc = newKeychain(name); + CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label")); + CFDictionarySetValue(query, kSecAttrAccess, access); + + CFTypeRef result = NULL; + ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name); + ok(result != NULL, "%s: SecItemAdd returned a result", name); + + SecKeychainItemRef item = checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + + ok_status(SecKeychainItemSetAccess(item, access), "%s: SecKeychainItemSetAccess", name); + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + + // Check to make sure the ACL stays + access = NULL; + ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); + checkAccessLength(name, access, 2); + + const char * newPassword = "newPassword"; + ok_status(SecKeychainItemModifyContent(item, NULL, (UInt32) strlen(newPassword), newPassword), "%s: SecKeychainItemModifyContent", name); + + access = NULL; + ok_status(SecKeychainItemCopyAccess(item, &access), "%s: SecKeychainItemCopyAccess", name); + checkAccessLength(name, access, 2); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testUidAccessTests (newKeychainTests + 2 + checkNTests + 1 + checkNTests + 1 + checkAccessLengthTests \ + + 2 + checkAccessLengthTests + 1) + + +static SecAccessRef makeMultipleUidAccess(uid_t* uids, uint32 count) +{ + // rights granted (replace with individual list if desired) + CSSM_ACL_AUTHORIZATION_TAG rights[] = + { + CSSM_ACL_AUTHORIZATION_ANY // everything + }; + size_t numRights = sizeof(rights) / sizeof(rights[0]); + + // allocate the arrays of objects used to define the ACL + CSSM_ACL_PROCESS_SUBJECT_SELECTOR selectors[count]; + CSSM_LIST_ELEMENT heads[count], tails[count]; + CSSM_ACL_ENTRY_INFO acls[count]; + // clear all the ACL objects + memset(heads, 0, sizeof(heads)); + memset(acls, 0, sizeof(acls)); + + uint32 i = count; + while (i--) + { + // make the "uid/gid" ACL subject + selectors[i].version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION; + selectors[i].mask = CSSM_ACL_MATCH_UID; // set mask: match uids (only) + selectors[i].uid = uids[i]; // uid to match + selectors[i].gid = 0; // gid (not matched here) + + // this is a CSSM_LIST_ELEMENT chain + heads[i].NextElement = &(tails[i]); + heads[i].WordID = CSSM_ACL_SUBJECT_TYPE_PROCESS; + heads[i].ElementType = CSSM_LIST_ELEMENT_WORDID; + // Element is unused + + tails[i].NextElement = NULL; + tails[i].WordID = CSSM_WORDID__NLU_; + tails[i].ElementType = CSSM_LIST_ELEMENT_DATUM; + tails[i].Element.Word.Data = (UInt8 *)&selectors[i]; + tails[i].Element.Word.Length = sizeof(selectors[i]); + + // ACL entry + acls[i].EntryPublicInfo.TypedSubject.ListType = CSSM_LIST_TYPE_UNKNOWN; + acls[i].EntryPublicInfo.TypedSubject.Head = &heads[i]; + acls[i].EntryPublicInfo.TypedSubject.Tail = &tails[i]; + acls[i].EntryPublicInfo.Delegate = CSSM_FALSE; + acls[i].EntryPublicInfo.Authorization.NumberOfAuthTags = (uint32) numRights; + + acls[i].EntryPublicInfo.Authorization.AuthTags = rights; + acls[i].EntryHandle = i; + } + + // owner component (right to change ACL) + CSSM_ACL_OWNER_PROTOTYPE owner; + owner.TypedSubject = acls[0].EntryPublicInfo.TypedSubject; + owner.Delegate = acls[0].EntryPublicInfo.Delegate; + + SecAccessRef access; + SecAccessCreateFromOwnerAndACL(&owner, count, acls, &access); + return access; +} +static void testMultipleUidAccess() { + char name[100]; + sprintf(name, "testMultipleUidAccess"); + secdebugfunc("integrity", "************************************* %s", name); + + uid_t uids[5]; + uids[0] = getuid(); + uids[1] = 0; + uids[2] = 500; + uids[3] = 501; + uids[4] = 502; + + SecAccessRef access = makeMultipleUidAccess(uids, 5); + + SecKeychainRef kc = newKeychain(name); + CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label")); + CFDictionarySetValue(query, kSecAttrAccess, access); + + CFTypeRef result = NULL; + ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name); + ok(result != NULL, "%s: SecItemAdd returned a result", name); + + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testMultipleUidAccessTests (newKeychainTests + checkNTests + 3) + +static void testRootUidAccess() { + char name[100]; + sprintf(name, "testRootUidAccess"); + secdebugfunc("integrity", "************************************* %s", name); + + SecAccessRef access = SecAccessCreateWithOwnerAndACL(getuid(), 0, (kSecUseOnlyUID | kSecHonorRoot), NULL, NULL); + + SecKeychainRef kc = newKeychain(name); + CFMutableDictionaryRef query = makeAddItemDictionary(kc, kSecClassGenericPassword, CFSTR("test label")); + CFDictionarySetValue(query, kSecAttrAccess, access); + + CFTypeRef result = NULL; + ok_status(SecItemAdd(query, &result), "%s: SecItemAdd", name); + ok(result != NULL, "%s: SecItemAdd returned a result", name); + + query = makeQueryItemDictionary(kc, kSecClassGenericPassword); + + SecKeychainItemRef item = checkN(name, query, 1); + + ok_status(SecKeychainItemSetAccess(item, access), "%s: SecKeychainItemSetAccess", name); + checkN(name, makeQueryItemDictionary(kc, kSecClassGenericPassword), 1); + + ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", name); +} +#define testRootUidAccessTests (newKeychainTests + checkNTests + 4 + checkNTests) + +#define kTestCount (0 \ + + testAddItemTests \ + + testAddItemTests \ + + testCopyMatchingItemTests \ + + testCopyMatchingItemTests \ + + testUpdateItemTests \ + + testUpdateItemTests \ + + testAddDuplicateItemTests \ + + testAddDuplicateItemTests \ + + testDeleteItemTests \ + + testDeleteItemTests \ + + testUpdateRetainedItemTests \ + + testUpdateRetainedItemTests \ + \ + + testAddKeyTests \ + + testAddFreeKeyTests \ + + testCopyMatchingKeyTests \ + + testUpdateKeyTests \ + + testAddDuplicateKeyTests \ + + testKeyPairTests \ + + testExportImportKeyPairTests \ + \ + + initializeDLTests \ + + testAttackItemTests \ + + testAttackKeyTests \ + + testAddAfterCorruptItemTests \ + + testAddAfterCorruptKeyTests \ + + unloadDLTests \ + \ + + testKeychainUpgradeTests \ + + testUidAccessTests \ + + testMultipleUidAccessTests \ + + testRootUidAccessTests \ + ) + +static void tests(void) +{ + const char *home_dir = getenv("HOME"); + sprintf(keychainFile, "%s/Library/Keychains/test.keychain", home_dir); + sprintf(keychainName, "test.keychain"); + + testAddItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); + testAddItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f")); + + testCopyMatchingItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); + testCopyMatchingItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f")); + + testUpdateItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4"), + CFSTR("7b7be2fd6ee9f81ba4c5575ea451f2c21117fc0f241625a6cf90c65180b8c9f5")); + testUpdateItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f"), + CFSTR("d71af9e4d54127a5dbc10c5ec097b828065cfbaf2b775caf1a3c4e3410f80851")); + + testAddDuplicateItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); + testAddDuplicateItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f")); + + testDeleteItem(kSecClassGenericPassword, CFSTR("265438ea6807b509c9c6962df3f5033fd1af118f76c5f550e3ed90cb0d3ffce4")); + testDeleteItem(kSecClassInternetPassword, CFSTR("be34c4562153063ce9cdefc2c34451d5e6e98a447f293d68a67349c1b5d1164f")); + + testUpdateRetainedItem(kSecClassGenericPassword); + testUpdateRetainedItem(kSecClassInternetPassword); + + testAddKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + testAddFreeKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + testCopyMatchingKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + testUpdateKey( CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b"), + CFSTR("a744ce6db8359ad264ed5f4a35ecfcc8b6599b89319e7ea316035acd3fb02c22")); + testAddDuplicateKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + testAddDuplicateFreeKey(CFSTR("44f10f6bb508d47f8905859efc06eaee500304bc4da408b1f4d2a58c6502147b")); + + testKeyPair(); + testExportImportKeyPair(); + + CSSM_DL_DB_HANDLE dldbHandle = initializeDL(); + testAttackItem(dldbHandle); + testAttackKey(dldbHandle); + + testAddAfterCorruptItem(dldbHandle); + testAddAfterCorruptKey(dldbHandle); + unloadDL(&dldbHandle); + + testKeychainUpgrade(); + testUidAccess(); + testMultipleUidAccess(); + testRootUidAccess(); + + //makeOldKeychainBlob(); +} + +#pragma clang pop +#else + +#define kTestCount (0) + + +static void tests(void) +{ +} + +#endif /* TARGET_OS_MAC */ + + +int kc_30_xara(int argc, char *const *argv) +{ + plan_tests(kTestCount); + + tests(); + + return 0; +} diff --git a/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c b/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c index 2996b5c8..77f288fb 100644 --- a/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c +++ b/OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c @@ -29,211 +29,221 @@ #include "utilities/SecCFRelease.h" #include "utilities/SecCFWrappers.h" -/* - 0 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 - G2 -*/ -unsigned char leaf_certificate[1750]={ - 0x30,0x82,0x06,0xD2,0x30,0x82,0x05,0xBA,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x07, - 0x64,0xF7,0xBA,0x2D,0x02,0x17,0x1F,0x9C,0x48,0x0D,0xFE,0x7B,0x65,0xBB,0x6F,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x77, - 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1D,0x30, - 0x1B,0x06,0x03,0x55,0x04,0x0A,0x13,0x14,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63, - 0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x1F,0x30,0x1D, - 0x06,0x03,0x55,0x04,0x0B,0x13,0x16,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20, - 0x54,0x72,0x75,0x73,0x74,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x28,0x30, - 0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1F,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63, - 0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x20, - 0x43,0x41,0x20,0x2D,0x20,0x47,0x32,0x30,0x1E,0x17,0x0D,0x31,0x35,0x30,0x34,0x32, - 0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x35,0x31,0x30,0x33,0x31, - 0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x82,0x01,0x09,0x31,0x13,0x30,0x11,0x06, - 0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x55,0x53, - 0x31,0x19,0x30,0x17,0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01, - 0x02,0x13,0x08,0x44,0x65,0x6C,0x61,0x77,0x61,0x72,0x65,0x31,0x1D,0x30,0x1B,0x06, - 0x03,0x55,0x04,0x0F,0x13,0x14,0x50,0x72,0x69,0x76,0x61,0x74,0x65,0x20,0x4F,0x72, - 0x67,0x61,0x6E,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03, - 0x55,0x04,0x05,0x13,0x07,0x33,0x30,0x31,0x34,0x32,0x36,0x37,0x31,0x0B,0x30,0x09, - 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55, - 0x04,0x11,0x14,0x0A,0x39,0x35,0x31,0x33,0x31,0x2D,0x32,0x30,0x32,0x31,0x31,0x13, - 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x13,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, - 0x6E,0x69,0x61,0x31,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x07,0x14,0x08,0x53,0x61, - 0x6E,0x20,0x4A,0x6F,0x73,0x65,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x09,0x14, - 0x0D,0x32,0x32,0x31,0x31,0x20,0x4E,0x20,0x31,0x73,0x74,0x20,0x53,0x74,0x31,0x15, - 0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x14,0x0C,0x50,0x61,0x79,0x50,0x61,0x6C,0x2C, - 0x20,0x49,0x6E,0x63,0x2E,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x14,0x0B, - 0x43,0x44,0x4E,0x20,0x53,0x75,0x70,0x70,0x6F,0x72,0x74,0x31,0x17,0x30,0x15,0x06, - 0x03,0x55,0x04,0x03,0x14,0x0E,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C, - 0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, - 0x02,0x82,0x01,0x01,0x00,0xC0,0xF8,0xAC,0x40,0xA6,0x91,0xBB,0xEE,0x11,0x15,0x61, - 0xE7,0xE1,0x3E,0x50,0x51,0xE7,0xA8,0x43,0x41,0xF9,0x53,0xA2,0x97,0x4D,0xD5,0xE9, - 0x11,0xF8,0xEF,0x74,0x20,0xE1,0x00,0x94,0x23,0x0C,0x0E,0x2A,0xC0,0x7C,0x39,0xD7, - 0x8C,0xC1,0x72,0x0A,0xD5,0x21,0x5F,0xDC,0xDB,0x6C,0x94,0xB2,0xBF,0x91,0x06,0x70, - 0x58,0x67,0xFA,0xDD,0x94,0x28,0x99,0x18,0xF4,0xF4,0x91,0x56,0x1A,0x97,0xDB,0x6C, - 0x5C,0x9C,0x81,0x15,0xFB,0xD2,0xDE,0xAD,0x97,0x30,0x0C,0xC1,0x83,0x92,0x35,0xEF, - 0x58,0x1E,0x3F,0xB1,0xB8,0xE9,0x56,0xCC,0x05,0x77,0xD5,0x90,0x0A,0x07,0xD7,0x33, - 0x43,0xEC,0xEE,0xC0,0x70,0xD8,0xDB,0xEF,0x3E,0x38,0xA0,0x98,0x04,0x2E,0xFC,0xA6, - 0x6A,0x59,0x90,0xCD,0x3A,0xDF,0x98,0xDE,0xD1,0x3E,0x3A,0x2C,0x7C,0x62,0x6B,0x43, - 0x30,0xA7,0x30,0x04,0xD3,0xD1,0x4A,0x7D,0xE3,0x22,0x2D,0xD4,0x89,0xAF,0xE7,0x20, - 0x9A,0xBD,0x6A,0xC8,0x63,0x52,0x26,0x72,0xE4,0xA3,0x50,0xCC,0x53,0x1D,0xA4,0x72, - 0x0F,0x78,0xED,0x9E,0x9D,0x9A,0x04,0x2F,0xA3,0x85,0xFA,0x19,0x60,0x9F,0x1A,0xDA, - 0xE3,0x3A,0xFA,0x3E,0x61,0xD2,0x06,0x29,0x68,0x4B,0x0B,0xAB,0x98,0xA5,0x15,0x6A, - 0x6F,0xB0,0x7A,0x0A,0x6B,0x56,0x50,0x8A,0xDD,0xBF,0xA7,0xFC,0x84,0xF7,0xEE,0x94, - 0xA0,0x20,0x2E,0x24,0x76,0x09,0x46,0x27,0x07,0x30,0xDB,0xF7,0x11,0xD6,0x4C,0xB7, - 0xBC,0x55,0x8B,0x93,0x0A,0x14,0x25,0xFB,0x1F,0xE6,0x4E,0x98,0x71,0xEE,0x66,0x27, - 0x43,0x78,0xBD,0x20,0x51,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x02,0xC4,0x30,0x82, - 0x02,0xC0,0x30,0x6E,0x06,0x03,0x55,0x1D,0x11,0x04,0x67,0x30,0x65,0x82,0x0C,0x63, - 0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D,0x82,0x0D,0x63,0x36,0x2E, - 0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D,0x82,0x14,0x64,0x65,0x76,0x65, - 0x6C,0x6F,0x70,0x65,0x72,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D, - 0x82,0x12,0x68,0x69,0x73,0x74,0x6F,0x72,0x79,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C, - 0x2E,0x63,0x6F,0x6D,0x82,0x0C,0x74,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63, - 0x6F,0x6D,0x82,0x0E,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63, - 0x6F,0x6D,0x30,0x09,0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, - 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06, - 0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, - 0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x66,0x06,0x03, - 0x55,0x1D,0x20,0x04,0x5F,0x30,0x5D,0x30,0x5B,0x06,0x0B,0x60,0x86,0x48,0x01,0x86, - 0xF8,0x45,0x01,0x07,0x17,0x06,0x30,0x4C,0x30,0x23,0x06,0x08,0x2B,0x06,0x01,0x05, - 0x05,0x07,0x02,0x01,0x16,0x17,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x64,0x2E, - 0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x70,0x73,0x30,0x25,0x06, - 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x19,0x1A,0x17,0x68,0x74,0x74, - 0x70,0x73,0x3A,0x2F,0x2F,0x64,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D, - 0x2F,0x72,0x70,0x61,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, - 0x14,0x4B,0xFA,0x2D,0xE4,0xEE,0x33,0x32,0xE2,0xDF,0x0D,0x01,0xA1,0x86,0xD3,0xA0, - 0x3B,0x3A,0xB9,0xAC,0xAE,0x30,0x2B,0x06,0x03,0x55,0x1D,0x1F,0x04,0x24,0x30,0x22, - 0x30,0x20,0xA0,0x1E,0xA0,0x1C,0x86,0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73, - 0x74,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x74,0x2E,0x63, - 0x72,0x6C,0x30,0x57,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4B, - 0x30,0x49,0x30,0x1F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x13, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x74,0x2E,0x73,0x79,0x6D,0x63,0x64,0x2E, - 0x63,0x6F,0x6D,0x30,0x26,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86, - 0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x74,0x2E,0x73,0x79,0x6D,0x63,0x62, - 0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x74,0x2E,0x63,0x72,0x74,0x30,0x82,0x01,0x03,0x06, - 0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x81,0xF4,0x04,0x81, - 0xF1,0x00,0xEF,0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14,0x87,0xBB, - 0x13,0xA2,0xCC,0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8,0xE3,0x77, - 0xCD,0x0E,0xC8,0x0D,0xDC,0x10,0x00,0x00,0x01,0x4C,0xE3,0x3F,0x9B,0x25,0x00,0x00, - 0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x20,0x5B,0xE3,0x52,0x37,0x1B,0x84,0xB4,0x48, - 0xD1,0xCD,0x8F,0x53,0x34,0xD5,0x31,0x22,0x2D,0x46,0xC1,0x91,0xB2,0x86,0x6A,0x77, - 0x3E,0x37,0xDF,0xFD,0xCC,0x9D,0x78,0xA5,0x02,0x21,0x00,0xDE,0x96,0x80,0x20,0xB6, - 0x82,0x09,0x1E,0x8E,0x4A,0x9F,0xC7,0xEE,0x3B,0x35,0x47,0x82,0x31,0xB1,0xD0,0xB1, - 0x63,0xF7,0x7D,0x52,0x1C,0xC5,0xC5,0x41,0x5E,0xBF,0x1A,0x00,0x75,0x00,0x56,0x14, - 0x06,0x9A,0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7,0x46,0x76, - 0xB9,0xBC,0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD,0x00,0x00, - 0x01,0x4C,0xE3,0x3F,0x9C,0x1A,0x00,0x00,0x04,0x03,0x00,0x46,0x30,0x44,0x02,0x20, - 0x27,0x1B,0x16,0x2D,0x4B,0xCF,0x0E,0x11,0xFA,0x9B,0x59,0x52,0x74,0xC1,0x1C,0x91, - 0x91,0x49,0x35,0x14,0x8E,0x9B,0x44,0x96,0x30,0xC0,0x54,0xD6,0x66,0x23,0xB5,0xE2, - 0x02,0x20,0x0C,0xFC,0x69,0x72,0xF6,0xAA,0x05,0xD7,0xC9,0x2A,0x68,0xF2,0x11,0x64, - 0x88,0x9B,0x4A,0x88,0x7E,0x26,0x76,0x18,0x16,0xE4,0xE9,0x79,0xCD,0xAF,0x36,0x2D, - 0x76,0x5F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05, - 0x00,0x03,0x82,0x01,0x01,0x00,0xA1,0x40,0x02,0x1A,0x1B,0x18,0xB8,0x03,0x04,0xB7, - 0xEE,0x36,0xD1,0x8F,0xAA,0xF7,0xB2,0xA9,0x18,0x11,0x9F,0x44,0x3C,0x3E,0xE6,0x62, - 0x45,0xB8,0x44,0x75,0x7B,0x7A,0x7A,0xF4,0xA0,0x2C,0x15,0x94,0x41,0xB9,0xF2,0x5B, - 0x06,0x32,0x42,0x6D,0x8D,0xF2,0x5A,0x0A,0xA7,0x35,0x3B,0xC5,0xFA,0x49,0x43,0xBE, - 0x89,0x38,0xF7,0xD8,0x3C,0x23,0x9D,0x7E,0xDD,0xFA,0x3F,0xC1,0xD4,0x4E,0x5F,0xE7, - 0xF2,0x7A,0x8A,0xFE,0xD1,0x6F,0x0D,0xBF,0xB4,0x3F,0xB4,0xD4,0x37,0x27,0x98,0x19, - 0x09,0xAA,0x0D,0x4F,0x8C,0x98,0x39,0xD4,0xF6,0xC3,0x2B,0x30,0x3B,0x31,0xCB,0x69, - 0x02,0x61,0x34,0xD7,0x13,0x95,0xBC,0x72,0xD2,0x51,0x21,0xDD,0xFD,0xD2,0xD3,0x83, - 0x27,0x86,0x90,0x78,0x8D,0x50,0x9A,0x91,0x1B,0xCE,0x46,0x55,0x34,0x14,0x3D,0x91, - 0x1B,0x8A,0x07,0x1A,0x13,0x49,0xAA,0xD8,0x49,0x73,0x9E,0x1F,0xE7,0x2B,0xE5,0xBE, - 0x15,0xE2,0xE5,0xA7,0x3D,0x84,0x77,0x7C,0x9F,0xE1,0xBC,0xE9,0xD4,0xBA,0x40,0x8F, - 0xD0,0x5A,0xF9,0x20,0xD8,0x45,0xE6,0xD3,0xFE,0xA1,0xB9,0x22,0xCF,0xD8,0x1B,0xED, - 0xCF,0xA0,0x92,0x6D,0x2F,0xAD,0x79,0xF5,0x46,0x55,0xE8,0xB4,0x86,0xF1,0x6F,0x94, - 0xCF,0xD9,0x56,0x46,0x96,0x1B,0x22,0x6F,0x41,0x79,0x62,0xF4,0xC9,0xD0,0x77,0x51, - 0x61,0xF8,0x29,0x21,0x1A,0x03,0x89,0x49,0xA1,0x89,0xDB,0xF3,0xCC,0xE3,0xBC,0xF3, - 0x1A,0x9D,0xCE,0x2E,0xA8,0x78,0x8C,0xC1,0x1B,0x34,0xBA,0x1B,0x90,0x87,0x4B,0x91, - 0x9D,0x85,0xF6,0x36,0x0C,0x0F, +/* 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 */ +/* EXPIRES Oct 30 23:59:59 2017 GMT */ + +unsigned char leaf_certificate[1873]={ + 0x30,0x82,0x07,0x4D,0x30,0x82,0x06,0x35,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x7F, + 0xC0,0x32,0xB3,0x6F,0x9F,0x9E,0x1A,0xC1,0xED,0xAB,0x97,0x13,0x65,0x29,0x35,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x77, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0A,0x13,0x14,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63, + 0x20,0x43,0x6F,0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x1F,0x30,0x1D, + 0x06,0x03,0x55,0x04,0x0B,0x13,0x16,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20, + 0x54,0x72,0x75,0x73,0x74,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x28,0x30, + 0x26,0x06,0x03,0x55,0x04,0x03,0x13,0x1F,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63, + 0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x20, + 0x43,0x41,0x20,0x2D,0x20,0x47,0x33,0x30,0x1E,0x17,0x0D,0x31,0x35,0x30,0x39,0x30, + 0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x31,0x37,0x31,0x30,0x33,0x30, + 0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x82,0x01,0x09,0x31,0x13,0x30,0x11,0x06, + 0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,0x13,0x02,0x55,0x53, + 0x31,0x19,0x30,0x17,0x06,0x0B,0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01, + 0x02,0x0C,0x08,0x44,0x65,0x6C,0x61,0x77,0x61,0x72,0x65,0x31,0x1D,0x30,0x1B,0x06, + 0x03,0x55,0x04,0x0F,0x13,0x14,0x50,0x72,0x69,0x76,0x61,0x74,0x65,0x20,0x4F,0x72, + 0x67,0x61,0x6E,0x69,0x7A,0x61,0x74,0x69,0x6F,0x6E,0x31,0x10,0x30,0x0E,0x06,0x03, + 0x55,0x04,0x05,0x13,0x07,0x33,0x30,0x31,0x34,0x32,0x36,0x37,0x31,0x0B,0x30,0x09, + 0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55, + 0x04,0x11,0x0C,0x0A,0x39,0x35,0x31,0x33,0x31,0x2D,0x32,0x30,0x32,0x31,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x11,0x30,0x0F,0x06,0x03,0x55,0x04,0x07,0x0C,0x08,0x53,0x61, + 0x6E,0x20,0x4A,0x6F,0x73,0x65,0x31,0x16,0x30,0x14,0x06,0x03,0x55,0x04,0x09,0x0C, + 0x0D,0x32,0x32,0x31,0x31,0x20,0x4E,0x20,0x31,0x73,0x74,0x20,0x53,0x74,0x31,0x15, + 0x30,0x13,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0C,0x50,0x61,0x79,0x50,0x61,0x6C,0x2C, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0B,0x0C,0x0B, + 0x43,0x44,0x4E,0x20,0x53,0x75,0x70,0x70,0x6F,0x72,0x74,0x31,0x17,0x30,0x15,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x0E,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C, + 0x2E,0x63,0x6F,0x6D,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, + 0x02,0x82,0x01,0x01,0x00,0xDC,0x6F,0x1C,0x60,0xDA,0x9C,0x32,0xF8,0x82,0x72,0x77, + 0xFD,0x51,0x80,0x59,0x6B,0xDB,0xC5,0x6A,0x36,0x4D,0x6E,0x8A,0x49,0x83,0xDE,0x75, + 0x1F,0x90,0xCB,0xB6,0x53,0xB9,0x3C,0x42,0xB9,0x1C,0xB5,0x53,0xAF,0x50,0x88,0x8D, + 0xE8,0xA8,0x7F,0xA6,0xA6,0x1F,0x0D,0x21,0xD4,0x5C,0x6F,0x0C,0x33,0x7E,0x3A,0x19, + 0x58,0xD9,0x5D,0x01,0xD3,0x08,0xE2,0xD2,0x59,0x54,0xA9,0xC7,0xAB,0x4D,0xC6,0xFF, + 0x05,0xA6,0x0B,0xBF,0xB6,0x11,0x12,0x34,0xEA,0xD7,0x23,0xCE,0x3E,0x60,0x21,0xBE, + 0xFE,0xCD,0xDB,0x65,0x1C,0xAF,0x62,0x96,0x3E,0x73,0xBD,0x08,0x05,0x6E,0xEA,0x33, + 0x1E,0xD5,0x59,0xC2,0x71,0xA5,0xE5,0x22,0xCE,0xD0,0x17,0xA5,0xD2,0xAC,0x7C,0xDC, + 0xEA,0xE8,0xBA,0x70,0x16,0x8B,0xE5,0x90,0x6C,0x7C,0xA0,0xB4,0x79,0x73,0x50,0x5E, + 0x26,0x88,0xA3,0x5F,0xF8,0x47,0x63,0x73,0x52,0x62,0x1F,0xC6,0xE2,0xEA,0xF5,0xF6, + 0x21,0x40,0x5D,0xF2,0x19,0xF2,0x73,0x05,0x25,0x39,0xEF,0x6F,0xCF,0xA0,0x84,0xE9, + 0xA4,0xEF,0x57,0xAC,0x6C,0x25,0xCD,0x7C,0x7C,0xD4,0x34,0x24,0x20,0x07,0xDD,0x0D, + 0x09,0x45,0xBD,0x98,0xA9,0xEE,0x83,0xD5,0xF2,0x8B,0x05,0xA2,0x29,0x37,0x0C,0xF4, + 0x62,0x17,0xC2,0x27,0x57,0x9D,0xE3,0x03,0xE3,0xAB,0x02,0x9D,0xFA,0xC9,0xFF,0x81, + 0x16,0xAB,0x2A,0x94,0x9B,0x3E,0x04,0xB7,0x78,0x2F,0xE9,0x7D,0x76,0x3B,0x22,0x85, + 0xB6,0x45,0x9F,0x42,0x55,0x36,0x2A,0xCB,0x49,0x0A,0xC0,0xFB,0xB8,0x0F,0x5B,0x85, + 0xD1,0x87,0x26,0x1B,0xE9,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x03,0x3F,0x30,0x82, + 0x03,0x3B,0x30,0x6E,0x06,0x03,0x55,0x1D,0x11,0x04,0x67,0x30,0x65,0x82,0x0C,0x63, + 0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D,0x82,0x0D,0x63,0x36,0x2E, + 0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D,0x82,0x14,0x64,0x65,0x76,0x65, + 0x6C,0x6F,0x70,0x65,0x72,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63,0x6F,0x6D, + 0x82,0x12,0x68,0x69,0x73,0x74,0x6F,0x72,0x79,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C, + 0x2E,0x63,0x6F,0x6D,0x82,0x0C,0x74,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63, + 0x6F,0x6D,0x82,0x0E,0x77,0x77,0x77,0x2E,0x70,0x61,0x79,0x70,0x61,0x6C,0x2E,0x63, + 0x6F,0x6D,0x30,0x09,0x06,0x03,0x55,0x1D,0x13,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x1D,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x01,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x66,0x06,0x03, + 0x55,0x1D,0x20,0x04,0x5F,0x30,0x5D,0x30,0x5B,0x06,0x0B,0x60,0x86,0x48,0x01,0x86, + 0xF8,0x45,0x01,0x07,0x17,0x06,0x30,0x4C,0x30,0x23,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x02,0x01,0x16,0x17,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F,0x64,0x2E, + 0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F,0x63,0x70,0x73,0x30,0x25,0x06, + 0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,0x30,0x19,0x1A,0x17,0x68,0x74,0x74, + 0x70,0x73,0x3A,0x2F,0x2F,0x64,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D, + 0x2F,0x72,0x70,0x61,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, + 0x14,0x01,0x59,0xAB,0xE7,0xDD,0x3A,0x0B,0x59,0xA6,0x64,0x63,0xD6,0xCF,0x20,0x07, + 0x57,0xD5,0x91,0xE7,0x6A,0x30,0x2B,0x06,0x03,0x55,0x1D,0x1F,0x04,0x24,0x30,0x22, + 0x30,0x20,0xA0,0x1E,0xA0,0x1C,0x86,0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73, + 0x72,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x72,0x2E,0x63, + 0x72,0x6C,0x30,0x57,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x4B, + 0x30,0x49,0x30,0x1F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x13, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x72,0x2E,0x73,0x79,0x6D,0x63,0x64,0x2E, + 0x63,0x6F,0x6D,0x30,0x26,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86, + 0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x72,0x2E,0x73,0x79,0x6D,0x63,0x62, + 0x2E,0x63,0x6F,0x6D,0x2F,0x73,0x72,0x2E,0x63,0x72,0x74,0x30,0x82,0x01,0x7E,0x06, + 0x0A,0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,0x04,0x82,0x01,0x6E,0x04, + 0x82,0x01,0x6A,0x01,0x68,0x00,0x76,0x00,0xA4,0xB9,0x09,0x90,0xB4,0x18,0x58,0x14, + 0x87,0xBB,0x13,0xA2,0xCC,0x67,0x70,0x0A,0x3C,0x35,0x98,0x04,0xF9,0x1B,0xDF,0xB8, + 0xE3,0x77,0xCD,0x0E,0xC8,0x0D,0xDC,0x10,0x00,0x00,0x01,0x4F,0x90,0x71,0x2A,0x7C, + 0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x21,0x00,0xB4,0x81,0x1F,0xE7,0x9F, + 0xB6,0xA2,0x06,0xC9,0x0B,0x93,0xBB,0x21,0x87,0x27,0x65,0x05,0x01,0x2D,0x66,0x40, + 0x64,0x14,0x1F,0x13,0x6D,0xF1,0x4B,0x9A,0x91,0x4F,0x53,0x02,0x20,0x37,0x17,0x0D, + 0xF8,0x66,0xBD,0xFD,0x6C,0xFE,0x55,0x62,0x2D,0xCD,0xBC,0x79,0x0B,0x0A,0x3F,0x81, + 0x91,0xCE,0xD5,0x86,0x27,0x11,0xA1,0x18,0x62,0x57,0x54,0xEB,0x8F,0x00,0x76,0x00, + 0x56,0x14,0x06,0x9A,0x2F,0xD7,0xC2,0xEC,0xD3,0xF5,0xE1,0xBD,0x44,0xB2,0x3E,0xC7, + 0x46,0x76,0xB9,0xBC,0x99,0x11,0x5C,0xC0,0xEF,0x94,0x98,0x55,0xD6,0x89,0xD0,0xDD, + 0x00,0x00,0x01,0x4F,0x90,0x71,0x2A,0xDB,0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45, + 0x02,0x21,0x00,0xE8,0xAA,0x58,0x90,0x87,0x74,0x96,0x5C,0xFB,0x69,0x28,0x83,0xEF, + 0x2E,0x40,0xD5,0x57,0xFF,0x5A,0x84,0x65,0x65,0x2E,0x27,0x4C,0x4C,0x91,0xE5,0x14, + 0xB1,0xBF,0xF8,0x02,0x20,0x0F,0x13,0x6B,0xF9,0x53,0x98,0xC9,0xAC,0x81,0xA0,0x09, + 0x52,0xDD,0x85,0x07,0xB7,0xD5,0x83,0x70,0xDF,0x68,0x96,0xA1,0x4D,0xFC,0x80,0x03, + 0xEC,0x68,0x88,0x5F,0xB5,0x00,0x76,0x00,0x68,0xF6,0x98,0xF8,0x1F,0x64,0x82,0xBE, + 0x3A,0x8C,0xEE,0xB9,0x28,0x1D,0x4C,0xFC,0x71,0x51,0x5D,0x67,0x93,0xD4,0x44,0xD1, + 0x0A,0x67,0xAC,0xBB,0x4F,0x4F,0xFB,0xC4,0x00,0x00,0x01,0x4F,0x90,0x71,0x2A,0x71, + 0x00,0x00,0x04,0x03,0x00,0x47,0x30,0x45,0x02,0x21,0x00,0xB5,0x0A,0x2B,0x5C,0x21, + 0x90,0x66,0x47,0x9C,0x12,0x8D,0xD4,0x5C,0x8E,0x98,0x5B,0x35,0x48,0x8D,0x0C,0xB9, + 0x77,0xB2,0x36,0xBB,0xEE,0x0C,0x62,0x7F,0x04,0x3D,0xBC,0x02,0x20,0x5A,0xCA,0xCD, + 0x03,0xF8,0x6D,0xAF,0x25,0x75,0x15,0x0B,0xA4,0x95,0x47,0x9A,0x04,0x24,0x49,0xCB, + 0x79,0x18,0x87,0xC1,0x28,0x75,0x5D,0x47,0x37,0x45,0x06,0x1B,0x6B,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01, + 0x00,0x9B,0x81,0x01,0x7F,0xE6,0x12,0x3B,0x64,0x51,0xBF,0x25,0xFF,0x1A,0xF9,0x2C, + 0x8F,0x11,0xEC,0x15,0x5B,0xC8,0x7C,0xA1,0x7C,0xCB,0xB9,0x37,0xA4,0xAA,0x8B,0xE5, + 0x15,0xAE,0x1F,0xCC,0x2E,0x6F,0xEA,0xA0,0xD0,0x22,0x97,0x04,0xAE,0x34,0xB8,0xC1, + 0x78,0xEE,0x67,0x06,0xE2,0x8E,0xDC,0x28,0x48,0xD8,0xDD,0x6A,0xF1,0xAE,0xEB,0xBA, + 0xB8,0xEF,0x1B,0x1B,0x6D,0xEE,0xF4,0xF9,0xF3,0x93,0x2F,0x48,0xD7,0x05,0xC7,0x08, + 0x49,0x42,0x5B,0x98,0xDA,0xFC,0xC6,0x7E,0xA0,0xAB,0xC8,0xC5,0xF6,0x0B,0x6C,0x1B, + 0x5F,0x43,0x56,0x8B,0x90,0x3E,0xF7,0xC7,0x23,0xF5,0xA8,0xC4,0x21,0xFA,0x80,0x70, + 0x8E,0xD9,0xF5,0xF5,0x41,0x9E,0xBF,0x5A,0x8B,0xBC,0xEA,0xE6,0xCA,0xE8,0x0A,0x0D, + 0x58,0xDC,0xB1,0xA3,0xFD,0x58,0x3D,0x4C,0xDD,0x65,0x1C,0x43,0x13,0xE9,0x38,0x9F, + 0x43,0xC7,0x72,0xB2,0x19,0xEF,0x2A,0x52,0xE3,0x87,0xD4,0x63,0xE9,0x5A,0x37,0xEB, + 0xDE,0x21,0xCF,0xC5,0x10,0xED,0x71,0xE8,0xEF,0x74,0xA2,0xD6,0xBC,0x1F,0xCA,0xDA, + 0x50,0x9F,0x79,0xFF,0x13,0x5D,0x28,0xDA,0xF9,0xAE,0x66,0x97,0x40,0x13,0x60,0xD4, + 0x03,0x44,0x9C,0x26,0x64,0x5C,0xE8,0x6C,0xCF,0xC6,0x2E,0xB9,0x78,0x9A,0x87,0x64, + 0x25,0xD2,0x06,0xB8,0x98,0x70,0x1A,0x3B,0xD8,0xBD,0x57,0xE0,0x94,0x9F,0x9D,0x5C, + 0x41,0x5C,0x4E,0x16,0xFB,0xEA,0x52,0x75,0xFC,0x0D,0xE9,0xE6,0x27,0x92,0x36,0x93, + 0xC2,0x8C,0x80,0x40,0x2B,0x44,0xE8,0xD5,0x14,0xBF,0x45,0x18,0x8D,0x59,0xC7,0xC8, + 0x9C, }; -/* - 1 s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 EV SSL CA - G2 - i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5 -*/ +/* s:/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 EV SSL CA - G3 */ +/* i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5 */ +/* SHA1 Fingerprint=E3:FC:0A:D8:4F:2F:5A:83:ED:6F:86:F5:67:F8:B1:4B:40:DC:BF:12 */ +/* EXPIRES: Oct 30 23:59:59 2023 GMT */ + unsigned char CA_certificate[1327]={ - 0x30,0x82,0x05,0x2B,0x30,0x82,0x04,0x13,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x36, - 0x65,0x85,0x07,0x7A,0x88,0x67,0xAB,0x58,0xF4,0xA0,0x94,0xF8,0x10,0x37,0x33,0x30, - 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x81, - 0xCA,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17, - 0x30,0x15,0x06,0x03,0x55,0x04,0x0A,0x13,0x0E,0x56,0x65,0x72,0x69,0x53,0x69,0x67, - 0x6E,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x0B, - 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x20,0x54,0x72,0x75,0x73,0x74, - 0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x3A,0x30,0x38,0x06,0x03,0x55,0x04, - 0x0B,0x13,0x31,0x28,0x63,0x29,0x20,0x32,0x30,0x30,0x36,0x20,0x56,0x65,0x72,0x69, - 0x53,0x69,0x67,0x6E,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x20,0x2D,0x20,0x46,0x6F,0x72, - 0x20,0x61,0x75,0x74,0x68,0x6F,0x72,0x69,0x7A,0x65,0x64,0x20,0x75,0x73,0x65,0x20, - 0x6F,0x6E,0x6C,0x79,0x31,0x45,0x30,0x43,0x06,0x03,0x55,0x04,0x03,0x13,0x3C,0x56, - 0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33,0x20, - 0x50,0x75,0x62,0x6C,0x69,0x63,0x20,0x50,0x72,0x69,0x6D,0x61,0x72,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,0x20,0x2D,0x20,0x47,0x35,0x30,0x1E,0x17,0x0D,0x31, - 0x33,0x31,0x30,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x33, - 0x31,0x30,0x33,0x30,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x77,0x31,0x0B,0x30, - 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1D,0x30,0x1B,0x06,0x03, - 0x55,0x04,0x0A,0x13,0x14,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20,0x43,0x6F, - 0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55, - 0x04,0x0B,0x13,0x16,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20,0x54,0x72,0x75, - 0x73,0x74,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x28,0x30,0x26,0x06,0x03, - 0x55,0x04,0x03,0x13,0x1F,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20,0x43,0x6C, - 0x61,0x73,0x73,0x20,0x33,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x20,0x43,0x41,0x20, - 0x2D,0x20,0x47,0x32,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, - 0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A, - 0x02,0x82,0x01,0x01,0x00,0xDA,0xEC,0xC5,0x6A,0x36,0x11,0x86,0xDB,0x20,0x21,0xA3, - 0xEC,0x4C,0x21,0xFD,0x0F,0xC5,0x5C,0x3A,0xBE,0xEC,0xA2,0x6E,0x98,0x0E,0x82,0x99, - 0x6B,0x7A,0x7A,0xEB,0x6E,0xF2,0x25,0xC9,0x2D,0x60,0x20,0x5D,0xD6,0x2B,0xE6,0xDD, - 0x99,0xD9,0xF1,0x54,0x5C,0x76,0x9B,0x0B,0xF9,0x27,0x42,0x24,0x7C,0xEA,0xD4,0xE6, - 0x3C,0x2A,0xCE,0x23,0x9F,0xFB,0x78,0xC9,0x15,0x44,0xF4,0x56,0x2C,0x55,0xCE,0x56, - 0xB7,0x30,0xF0,0x49,0x89,0xFE,0x0D,0xD8,0x6E,0x01,0x7C,0x61,0xD3,0x44,0x99,0x66, - 0x5E,0x96,0x48,0x18,0x87,0x09,0xC8,0xC3,0x49,0xE9,0x35,0xEC,0xBB,0x4C,0x7A,0x15, - 0x91,0x55,0xED,0x60,0x80,0x95,0x0B,0xD7,0x18,0xF3,0xA7,0x4B,0xE6,0xE8,0x74,0x0C, - 0x2E,0x6B,0x45,0xF4,0x17,0xF9,0xCB,0xBF,0x54,0x56,0xEE,0x36,0xD4,0x4E,0xE6,0xCF, - 0xAD,0x1F,0x4D,0x7D,0x8F,0xB3,0x55,0x35,0xDD,0x62,0xD2,0x6E,0x54,0x85,0x9E,0x45, - 0x53,0x7A,0xEE,0x60,0x96,0x22,0x7F,0xB8,0x1A,0xAF,0x6F,0xA0,0x0E,0xA6,0x8E,0x13, - 0xB6,0x85,0xA1,0xCC,0x5C,0x8C,0x9E,0xAD,0x1D,0x71,0xB8,0x08,0x94,0xE6,0xCE,0xBC, - 0x38,0xD0,0xD1,0xE9,0x3F,0x71,0x43,0xFB,0x97,0x23,0xA8,0x6C,0xF4,0x31,0xDC,0x02, - 0x3B,0xDE,0x29,0x55,0xF2,0xA0,0xBE,0x1E,0x21,0x6C,0xAF,0x1A,0x5C,0xDF,0x6A,0x37, - 0x64,0x02,0x9A,0xD0,0x51,0x71,0xA5,0x7F,0xBA,0x69,0xC5,0x2C,0x89,0x67,0x70,0x3B, - 0x13,0x05,0x72,0xED,0x21,0x23,0x10,0x2B,0x23,0x2A,0x1A,0xAE,0x3A,0x09,0x64,0x23, - 0x7A,0x27,0x62,0x12,0xD1,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x5D,0x30,0x82, - 0x01,0x59,0x30,0x2F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x23, - 0x30,0x21,0x30,0x1F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x13, - 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x32,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E, - 0x63,0x6F,0x6D,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30, - 0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x65,0x06,0x03,0x55,0x1D,0x20,0x04,0x5E, - 0x30,0x5C,0x30,0x5A,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x52,0x30,0x26,0x06,0x08, - 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F, - 0x2F,0x77,0x77,0x77,0x2E,0x73,0x79,0x6D,0x61,0x75,0x74,0x68,0x2E,0x63,0x6F,0x6D, - 0x2F,0x63,0x70,0x73,0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, - 0x30,0x1C,0x1A,0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x73, - 0x79,0x6D,0x61,0x75,0x74,0x68,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x70,0x61,0x30,0x30, - 0x06,0x03,0x55,0x1D,0x1F,0x04,0x29,0x30,0x27,0x30,0x25,0xA0,0x23,0xA0,0x21,0x86, - 0x1F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x31,0x2E,0x73,0x79,0x6D,0x63,0x62, - 0x2E,0x63,0x6F,0x6D,0x2F,0x70,0x63,0x61,0x33,0x2D,0x67,0x35,0x2E,0x63,0x72,0x6C, - 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06, - 0x30,0x29,0x06,0x03,0x55,0x1D,0x11,0x04,0x22,0x30,0x20,0xA4,0x1E,0x30,0x1C,0x31, - 0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x53,0x79,0x6D,0x61,0x6E,0x74, - 0x65,0x63,0x50,0x4B,0x49,0x2D,0x31,0x2D,0x35,0x33,0x32,0x30,0x1D,0x06,0x03,0x55, - 0x1D,0x0E,0x04,0x16,0x04,0x14,0x4B,0xFA,0x2D,0xE4,0xEE,0x33,0x32,0xE2,0xDF,0x0D, - 0x01,0xA1,0x86,0xD3,0xA0,0x3B,0x3A,0xB9,0xAC,0xAE,0x30,0x1F,0x06,0x03,0x55,0x1D, - 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x7F,0xD3,0x65,0xA7,0xC2,0xDD,0xEC,0xBB,0xF0, - 0x30,0x09,0xF3,0x43,0x39,0xFA,0x02,0xAF,0x33,0x31,0x33,0x30,0x0D,0x06,0x09,0x2A, - 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x46, - 0xA6,0xF5,0xB3,0xE8,0xA4,0x56,0xC9,0xB8,0x34,0xF0,0xF7,0xFE,0xF3,0x2C,0x2E,0x63, - 0x91,0x63,0x2C,0xE9,0xD5,0x14,0x7F,0x13,0x93,0xF6,0x4C,0xDE,0x4D,0x82,0x99,0xCC, - 0x6B,0xC9,0x78,0x61,0xFB,0x12,0x2D,0x48,0x0F,0x70,0xEA,0x27,0x6F,0x78,0xE8,0xF7, - 0x03,0x3E,0xCA,0xB8,0x3B,0xBA,0xC9,0xDF,0xB0,0x3A,0xE2,0xDE,0x22,0xD0,0x31,0x2D, - 0x66,0xDA,0x6E,0x11,0x25,0x42,0xF5,0x7B,0x24,0xC2,0xDE,0x4B,0x12,0x77,0xCD,0x56, - 0xD8,0xFB,0x86,0x80,0xBA,0x0A,0x53,0x6E,0xE5,0x01,0x08,0x1B,0xD1,0xC9,0xB2,0x75, - 0x9D,0xAB,0x06,0x27,0x2C,0xF2,0x52,0x8F,0x59,0xBD,0xAE,0x1D,0x74,0xFA,0xE3,0xC6, - 0xFC,0x44,0x4D,0x5B,0x4A,0x6C,0xC9,0xB8,0x39,0xD9,0xF7,0x5A,0x84,0xF9,0xA0,0x03, - 0xC2,0x38,0x4E,0x8B,0x32,0xA5,0x40,0xDA,0xC2,0x75,0xF4,0xBC,0xCA,0xF9,0x57,0xF9, - 0x86,0x07,0x75,0x5B,0xEE,0x76,0x35,0x30,0x85,0x07,0x73,0xD2,0x5C,0x46,0xED,0x0F, - 0x7A,0xE5,0x7F,0x6C,0x3D,0x37,0xC1,0xBD,0xE6,0x85,0x49,0x60,0xBA,0x8D,0xF9,0xEF, - 0xDA,0xAC,0x4A,0x31,0xE1,0x64,0xF6,0x79,0x67,0xBF,0x3F,0x6F,0xE2,0x95,0x52,0xDE, - 0x4F,0x8D,0xC9,0xD4,0x3D,0xFC,0xBD,0x3B,0xB8,0x31,0xF0,0xF5,0xD9,0xF5,0x41,0x04, - 0x54,0xE0,0x26,0x9F,0x99,0x83,0xF9,0x05,0x36,0x25,0x71,0xC4,0xCB,0xC1,0x2B,0x1E, - 0x83,0x50,0xA8,0x7B,0x0B,0x8C,0x56,0x0E,0xAA,0x5D,0xA6,0xE9,0x2F,0xA1,0x67,0xFE, - 0x37,0x20,0xC5,0x3E,0x9D,0xFC,0x9D,0xAC,0x20,0xFD,0x7B,0xBB,0x9C,0xB8,0x20, + 0x30,0x82,0x05,0x2B,0x30,0x82,0x04,0x13,0xA0,0x03,0x02,0x01,0x02,0x02,0x10,0x7E, + 0xE1,0x4A,0x6F,0x6F,0xEF,0xF2,0xD3,0x7F,0x3F,0xAD,0x65,0x4D,0x3A,0xDA,0xB4,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81, + 0xCA,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17, + 0x30,0x15,0x06,0x03,0x55,0x04,0x0A,0x13,0x0E,0x56,0x65,0x72,0x69,0x53,0x69,0x67, + 0x6E,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x0B, + 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x20,0x54,0x72,0x75,0x73,0x74, + 0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x3A,0x30,0x38,0x06,0x03,0x55,0x04, + 0x0B,0x13,0x31,0x28,0x63,0x29,0x20,0x32,0x30,0x30,0x36,0x20,0x56,0x65,0x72,0x69, + 0x53,0x69,0x67,0x6E,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x20,0x2D,0x20,0x46,0x6F,0x72, + 0x20,0x61,0x75,0x74,0x68,0x6F,0x72,0x69,0x7A,0x65,0x64,0x20,0x75,0x73,0x65,0x20, + 0x6F,0x6E,0x6C,0x79,0x31,0x45,0x30,0x43,0x06,0x03,0x55,0x04,0x03,0x13,0x3C,0x56, + 0x65,0x72,0x69,0x53,0x69,0x67,0x6E,0x20,0x43,0x6C,0x61,0x73,0x73,0x20,0x33,0x20, + 0x50,0x75,0x62,0x6C,0x69,0x63,0x20,0x50,0x72,0x69,0x6D,0x61,0x72,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,0x20,0x2D,0x20,0x47,0x35,0x30,0x1E,0x17,0x0D,0x31, + 0x33,0x31,0x30,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5A,0x17,0x0D,0x32,0x33, + 0x31,0x30,0x33,0x30,0x32,0x33,0x35,0x39,0x35,0x39,0x5A,0x30,0x77,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0A,0x13,0x14,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20,0x43,0x6F, + 0x72,0x70,0x6F,0x72,0x61,0x74,0x69,0x6F,0x6E,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55, + 0x04,0x0B,0x13,0x16,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20,0x54,0x72,0x75, + 0x73,0x74,0x20,0x4E,0x65,0x74,0x77,0x6F,0x72,0x6B,0x31,0x28,0x30,0x26,0x06,0x03, + 0x55,0x04,0x03,0x13,0x1F,0x53,0x79,0x6D,0x61,0x6E,0x74,0x65,0x63,0x20,0x43,0x6C, + 0x61,0x73,0x73,0x20,0x33,0x20,0x45,0x56,0x20,0x53,0x53,0x4C,0x20,0x43,0x41,0x20, + 0x2D,0x20,0x47,0x33,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,0xD8,0xA1,0x65,0x74,0x23,0xE8,0x2B,0x64,0xE2,0x32,0xD7, + 0x33,0x37,0x3D,0x8E,0xF5,0x34,0x16,0x48,0xDD,0x4F,0x7F,0x87,0x1C,0xF8,0x44,0x23, + 0x13,0x8E,0xFB,0x11,0xD8,0x44,0x5A,0x18,0x71,0x8E,0x60,0x16,0x26,0x92,0x9B,0xFD, + 0x17,0x0B,0xE1,0x71,0x70,0x42,0xFE,0xBF,0xFA,0x1C,0xC0,0xAA,0xA3,0xA7,0xB5,0x71, + 0xE8,0xFF,0x18,0x83,0xF6,0xDF,0x10,0x0A,0x13,0x62,0xC8,0x3D,0x9C,0xA7,0xDE,0x2E, + 0x3F,0x0C,0xD9,0x1D,0xE7,0x2E,0xFB,0x2A,0xCE,0xC8,0x9A,0x7F,0x87,0xBF,0xD8,0x4C, + 0x04,0x15,0x32,0xC9,0xD1,0xCC,0x95,0x71,0xA0,0x4E,0x28,0x4F,0x84,0xD9,0x35,0xFB, + 0xE3,0x86,0x6F,0x94,0x53,0xE6,0x72,0x8A,0x63,0x67,0x2E,0xBE,0x69,0xF6,0xF7,0x6E, + 0x8E,0x9C,0x60,0x04,0xEB,0x29,0xFA,0xC4,0x47,0x42,0xD2,0x78,0x98,0xE3,0xEC,0x0B, + 0xA5,0x92,0xDC,0xB7,0x9A,0xBD,0x80,0x64,0x2B,0x38,0x7C,0x38,0x09,0x5B,0x66,0xF6, + 0x2D,0x95,0x7A,0x86,0xB2,0x34,0x2E,0x85,0x9E,0x90,0x0E,0x5F,0xB7,0x5D,0xA4,0x51, + 0x72,0x46,0x70,0x13,0xBF,0x67,0xF2,0xB6,0xA7,0x4D,0x14,0x1E,0x6C,0xB9,0x53,0xEE, + 0x23,0x1A,0x4E,0x8D,0x48,0x55,0x43,0x41,0xB1,0x89,0x75,0x6A,0x40,0x28,0xC5,0x7D, + 0xDD,0xD2,0x6E,0xD2,0x02,0x19,0x2F,0x7B,0x24,0x94,0x4B,0xEB,0xF1,0x1A,0xA9,0x9B, + 0xE3,0x23,0x9A,0xEA,0xFA,0x33,0xAB,0x0A,0x2C,0xB7,0xF4,0x60,0x08,0xDD,0x9F,0x1C, + 0xCD,0xDD,0x2D,0x01,0x66,0x80,0xAF,0xB3,0x2F,0x29,0x1D,0x23,0xB8,0x8A,0xE1,0xA1, + 0x70,0x07,0x0C,0x34,0x0F,0x02,0x03,0x01,0x00,0x01,0xA3,0x82,0x01,0x5D,0x30,0x82, + 0x01,0x59,0x30,0x2F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x23, + 0x30,0x21,0x30,0x1F,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x13, + 0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x32,0x2E,0x73,0x79,0x6D,0x63,0x62,0x2E, + 0x63,0x6F,0x6D,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30, + 0x06,0x01,0x01,0xFF,0x02,0x01,0x00,0x30,0x65,0x06,0x03,0x55,0x1D,0x20,0x04,0x5E, + 0x30,0x5C,0x30,0x5A,0x06,0x04,0x55,0x1D,0x20,0x00,0x30,0x52,0x30,0x26,0x06,0x08, + 0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F, + 0x2F,0x77,0x77,0x77,0x2E,0x73,0x79,0x6D,0x61,0x75,0x74,0x68,0x2E,0x63,0x6F,0x6D, + 0x2F,0x63,0x70,0x73,0x30,0x28,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, + 0x30,0x1C,0x1A,0x1A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x77,0x77,0x77,0x2E,0x73, + 0x79,0x6D,0x61,0x75,0x74,0x68,0x2E,0x63,0x6F,0x6D,0x2F,0x72,0x70,0x61,0x30,0x30, + 0x06,0x03,0x55,0x1D,0x1F,0x04,0x29,0x30,0x27,0x30,0x25,0xA0,0x23,0xA0,0x21,0x86, + 0x1F,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x73,0x31,0x2E,0x73,0x79,0x6D,0x63,0x62, + 0x2E,0x63,0x6F,0x6D,0x2F,0x70,0x63,0x61,0x33,0x2D,0x67,0x35,0x2E,0x63,0x72,0x6C, + 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06, + 0x30,0x29,0x06,0x03,0x55,0x1D,0x11,0x04,0x22,0x30,0x20,0xA4,0x1E,0x30,0x1C,0x31, + 0x1A,0x30,0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x53,0x79,0x6D,0x61,0x6E,0x74, + 0x65,0x63,0x50,0x4B,0x49,0x2D,0x31,0x2D,0x35,0x33,0x33,0x30,0x1D,0x06,0x03,0x55, + 0x1D,0x0E,0x04,0x16,0x04,0x14,0x01,0x59,0xAB,0xE7,0xDD,0x3A,0x0B,0x59,0xA6,0x64, + 0x63,0xD6,0xCF,0x20,0x07,0x57,0xD5,0x91,0xE7,0x6A,0x30,0x1F,0x06,0x03,0x55,0x1D, + 0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x7F,0xD3,0x65,0xA7,0xC2,0xDD,0xEC,0xBB,0xF0, + 0x30,0x09,0xF3,0x43,0x39,0xFA,0x02,0xAF,0x33,0x31,0x33,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x42, + 0x01,0x55,0x7B,0xD0,0x16,0x1A,0x5D,0x58,0xE8,0xBB,0x9B,0xA8,0x4D,0xD7,0xF3,0xD7, + 0xEB,0x13,0x94,0x86,0xD6,0x7F,0x21,0x0B,0x47,0xBC,0x57,0x9B,0x92,0x5D,0x4F,0x05, + 0x9F,0x38,0xA4,0x10,0x7C,0xCF,0x83,0xBE,0x06,0x43,0x46,0x8D,0x08,0xBC,0x6A,0xD7, + 0x10,0xA6,0xFA,0xAB,0xAF,0x2F,0x61,0xA8,0x63,0xF2,0x65,0xDF,0x7F,0x4C,0x88,0x12, + 0x88,0x4F,0xB3,0x69,0xD9,0xFF,0x27,0xC0,0x0A,0x97,0x91,0x8F,0x56,0xFB,0x89,0xC4, + 0xA8,0xBB,0x92,0x2D,0x1B,0x73,0xB0,0xC6,0xAB,0x36,0xF4,0x96,0x6C,0x20,0x08,0xEF, + 0x0A,0x1E,0x66,0x24,0x45,0x4F,0x67,0x00,0x40,0xC8,0x07,0x54,0x74,0x33,0x3B,0xA6, + 0xAD,0xBB,0x23,0x9F,0x66,0xED,0xA2,0x44,0x70,0x34,0xFB,0x0E,0xEA,0x01,0xFD,0xCF, + 0x78,0x74,0xDF,0xA7,0xAD,0x55,0xB7,0x5F,0x4D,0xF6,0xD6,0x3F,0xE0,0x86,0xCE,0x24, + 0xC7,0x42,0xA9,0x13,0x14,0x44,0x35,0x4B,0xB6,0xDF,0xC9,0x60,0xAC,0x0C,0x7F,0xD9, + 0x93,0x21,0x4B,0xEE,0x9C,0xE4,0x49,0x02,0x98,0xD3,0x60,0x7B,0x5C,0xBC,0xD5,0x30, + 0x2F,0x07,0xCE,0x44,0x42,0xC4,0x0B,0x99,0xFE,0xE6,0x9F,0xFC,0xB0,0x78,0x86,0x51, + 0x6D,0xD1,0x2C,0x9D,0xC6,0x96,0xFB,0x85,0x82,0xBB,0x04,0x2F,0xF7,0x62,0x80,0xEF, + 0x62,0xDA,0x7F,0xF6,0x0E,0xAC,0x90,0xB8,0x56,0xBD,0x79,0x3F,0xF2,0x80,0x6E,0xA3, + 0xD9,0xB9,0x0F,0x5D,0x3A,0x07,0x1D,0x91,0x93,0x86,0x4B,0x29,0x4C,0xE1,0xDC,0xB5, + 0xE1,0xE0,0x33,0x9D,0xB3,0xCB,0x36,0x91,0x4B,0xFE,0xA1,0xB4,0xEE,0xF0,0xF9, }; unsigned char smime_leaf_certificate[1338]={ diff --git a/OSX/libsecurity_keychain/regressions/keychain_regressions.h b/OSX/libsecurity_keychain/regressions/keychain_regressions.h index e670b866..89ab2b02 100644 --- a/OSX/libsecurity_keychain/regressions/keychain_regressions.h +++ b/OSX/libsecurity_keychain/regressions/keychain_regressions.h @@ -4,9 +4,10 @@ */ #include -ONE_TEST(kc_42_trust_revocation) +ONE_TEST(kc_30_xara) ONE_TEST(kc_40_seckey) ONE_TEST(kc_41_sececkey) +ONE_TEST(kc_42_trust_revocation) ONE_TEST(si_20_sectrust_provisioning) ONE_TEST(si_33_keychain_backup) ONE_TEST(si_34_one_true_keychain) diff --git a/OSX/libsecurity_manifest/lib/ManifestInternal.cpp b/OSX/libsecurity_manifest/lib/ManifestInternal.cpp index 2c8abdcc..9ce1aedc 100644 --- a/OSX/libsecurity_manifest/lib/ManifestInternal.cpp +++ b/OSX/libsecurity_manifest/lib/ManifestInternal.cpp @@ -760,7 +760,7 @@ void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name, SHA1 if (bytesRead != st.st_size) { - delete buffer; + delete [] buffer; UnixError::throwMe (); } @@ -801,7 +801,7 @@ void ManifestFileItem::ComputeDigestForAppleDoubleResourceFork (char* name, SHA1 // compute the SHA1 hash CC_SHA1_Final (digest, &digestContext); - delete buffer; + delete [] buffer; } diff --git a/OSX/libsecurity_smime/lib/SecCmsBase.h b/OSX/libsecurity_smime/lib/SecCmsBase.h index c3c03690..cebe62ff 100644 --- a/OSX/libsecurity_smime/lib/SecCmsBase.h +++ b/OSX/libsecurity_smime/lib/SecCmsBase.h @@ -428,7 +428,7 @@ typedef enum { /* New PSM certificate management OIDs */ SEC_OID_CERT_RENEWAL_LOCATOR = 177, SEC_OID_NS_CERT_EXT_SCOPE_OF_USE = 178, - + /* CMS (RFC2630) OIDs */ SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN = 179, SEC_OID_CMS_3DES_KEY_WRAP = 180, @@ -449,34 +449,43 @@ typedef enum { SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE = 190, - SEC_OID_SHA256 = 191, - SEC_OID_SHA384 = 192, - SEC_OID_SHA512 = 193, + SEC_OID_SHA224 = 191, + SEC_OID_SHA256 = 192, + SEC_OID_SHA384 = 193, + SEC_OID_SHA512 = 194, - SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 194, - SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 195, - SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 196, + SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 195, + SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 196, + SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 197, - SEC_OID_AES_128_KEY_WRAP = 197, - SEC_OID_AES_192_KEY_WRAP = 198, - SEC_OID_AES_256_KEY_WRAP = 199, + SEC_OID_AES_128_KEY_WRAP = 198, + SEC_OID_AES_192_KEY_WRAP = 199, + SEC_OID_AES_256_KEY_WRAP = 200, /* eContentType set by client and not understood by this library; treated * like SEC_OID_PKCS7_DATA, except the caller's OID is encoded. */ - SEC_OID_OTHER = 200, - + SEC_OID_OTHER = 201, + /* ECDSA */ - SEC_OID_EC_PUBLIC_KEY = 201, - SEC_OID_ECDSA_WithSHA1 = 202, - SEC_OID_DH_SINGLE_STD_SHA1KDF = 203, - SEC_OID_SECP_256_R1 = 204, - SEC_OID_SECP_384_R1 = 205, - SEC_OID_SECP_521_R1 = 206, - + SEC_OID_EC_PUBLIC_KEY = 202, + SEC_OID_ECDSA_WithSHA1 = 203, + SEC_OID_DH_SINGLE_STD_SHA1KDF = 204, + SEC_OID_SECP_256_R1 = 205, + SEC_OID_SECP_384_R1 = 206, + SEC_OID_SECP_521_R1 = 207, + /* RFC 3161 Timestamping OIDs */ - SEC_OID_PKCS9_ID_CT_TSTInfo = 207, - SEC_OID_PKCS9_TIMESTAMP_TOKEN = 208, - SEC_OID_PKCS9_SIGNING_CERTIFICATE = 209, + SEC_OID_PKCS9_ID_CT_TSTInfo = 208, + SEC_OID_PKCS9_TIMESTAMP_TOKEN = 209, + SEC_OID_PKCS9_SIGNING_CERTIFICATE = 210, + + /* ECDSA with SHA2 */ + SEC_OID_ECDSA_WITH_SHA256 = 211, + SEC_OID_ECDSA_WITH_SHA384 = 212, + SEC_OID_ECDSA_WITH_SHA512 = 213, + + /* Apple CMS Attribute */ + SEC_OID_APPLE_HASH_AGILITY = 214, SEC_OID_TOTAL } SECOidTag; diff --git a/OSX/libsecurity_smime/lib/SecCmsSignerInfo.h b/OSX/libsecurity_smime/lib/SecCmsSignerInfo.h index ebacbf12..7c94cabb 100644 --- a/OSX/libsecurity_smime/lib/SecCmsSignerInfo.h +++ b/OSX/libsecurity_smime/lib/SecCmsSignerInfo.h @@ -141,6 +141,16 @@ SecCmsSignerInfoGetTimestampTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stim OSStatus SecCmsSignerInfoGetTimestampTimeWithPolicy(SecCmsSignerInfoRef sinfo, CFTypeRef timeStampPolicy, CFAbsoluteTime *stime); +/*! + @function + @abstract Return the data in the signed Codesigning Hash Agility attribute. + @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value + @discussion Returns a CFDataRef containing the value of the attribute + @result A return value of SECFailure is an error. + */ +OSStatus +SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata); + /*! @function @abstract Return the signing cert of a CMS signerInfo. @@ -223,6 +233,14 @@ extern OSStatus SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, SECOidTag digestalg, SecIdentityRef identity); +/*! + @function + @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed Apple code signatures. + */ + OSStatus + SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue); + /*! @function @abstract The following needs to be done in the S/MIME layer code after signature of a signerinfo has been verified. diff --git a/OSX/libsecurity_smime/lib/cmsattr.c b/OSX/libsecurity_smime/lib/cmsattr.c index f7c7cc81..39c72172 100644 --- a/OSX/libsecurity_smime/lib/cmsattr.c +++ b/OSX/libsecurity_smime/lib/cmsattr.c @@ -252,6 +252,7 @@ cms_attr_choose_attr_value_template(void *src_or_dest, Boolean encoding, const c theTemplate = SEC_ASN1_GET(kSecAsn1ObjectIDTemplate); break; case SEC_OID_PKCS9_MESSAGE_DIGEST: + case SEC_OID_APPLE_HASH_AGILITY: encoded = PR_FALSE; theTemplate = SEC_ASN1_GET(kSecAsn1OctetStringTemplate); break; diff --git a/OSX/libsecurity_smime/lib/cmssigdata.c b/OSX/libsecurity_smime/lib/cmssigdata.c index e5d8b6cf..6e85d7b5 100644 --- a/OSX/libsecurity_smime/lib/cmssigdata.c +++ b/OSX/libsecurity_smime/lib/cmssigdata.c @@ -756,7 +756,6 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, /* Find digest and contentType for signerinfo */ algiddata = SecCmsSignerInfoGetDigestAlg(signerinfo); if (algiddata == NULL) { - syslog(LOG_ERR,"SecCmsSignedDataVerifySignerInfo: could not get digest algorithm %d", PORT_GetError()); return errSecInternalError; // shouldn't have happened, this is likely due to corrupted data } @@ -768,7 +767,6 @@ SecCmsSignedDataVerifySignerInfo(SecCmsSignedDataRef sigd, int i, * FIXME: need some error return for this (as well as many * other places in this library). */ - syslog(LOG_ERR,"SecCmsSignedDataVerifySignerInfo: could not get digest using algorithm id"); return errSecDataNotAvailable; } contentType = SecCmsContentInfoGetContentTypeOID(cinfo); diff --git a/OSX/libsecurity_smime/lib/cmssiginfo.c b/OSX/libsecurity_smime/lib/cmssiginfo.c index d375f82d..c2111395 100644 --- a/OSX/libsecurity_smime/lib/cmssiginfo.c +++ b/OSX/libsecurity_smime/lib/cmssiginfo.c @@ -323,6 +323,11 @@ SecCmsSignerInfoDestroy(SecCmsSignerInfoRef si) (int)CFGetRetainCount(si->timestampCertList)); CFRelease(si->timestampCertList); } + if (si->hashAgilityAttrValue != NULL) { + dprintfRC("SecCmsSignerInfoDestroy top: hashAgilityAttrValue.rc %d\n", + (int)CFGetRetainCount(si->hashAgilityAttrValue)); + CFRelease(si->hashAgilityAttrValue); + } /* XXX storage ??? */ } @@ -607,8 +612,10 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt dprintfRC("SecCmsSignerInfoVerify top: cert %p cert.rc %d\n", cert, (int)CFGetRetainCount(cert)); debugShowSigningCertificate(signerinfo); - - if (SecCertificateCopyPublicKey(cert, &publickey)) { + + OSStatus status; + if ((status = SecCertificateCopyPublicKey(cert, &publickey))) { + syslog(LOG_ERR, "SecCmsSignerInfoVerifyWithPolicy: copy public key failed %d", (int)status); vs = SecCmsVSProcessingError; goto loser; } @@ -664,6 +671,7 @@ 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; } @@ -681,19 +689,18 @@ 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; } - SECStatus err = SECSuccess; - vs = ((err = VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length, + vs = (VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length, publickey, &(signerinfo->encDigest), digestAlgTag, digestEncAlgTag, - signerinfo->cmsg->pwfn_arg)) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; + signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; dprintf("VFY_VerifyData (authenticated attributes): %s\n", (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature"); - if (vs != SecCmsVSGoodSignature) syslog(LOG_ERR, "VFY_VerifyData (authenticated attributes) failed: %d", err); PORT_FreeArena(poolp, PR_FALSE); /* awkward memory management :-( */ @@ -705,14 +712,12 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt if (sig->Length == 0) goto loser; - SECStatus err = SECSuccess; - vs = ((err = VFY_VerifyDigest(digest, publickey, sig, + vs = (VFY_VerifyDigest(digest, publickey, sig, digestAlgTag, digestEncAlgTag, - signerinfo->cmsg->pwfn_arg)) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; + signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature; dprintf("VFY_VerifyData (plain message digest): %s\n", (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature"); - if (vs != SecCmsVSGoodSignature) syslog(LOG_ERR, "VFY_VerifyDigest (plain message digest) failed: %d", err); } if (!SecCmsArrayIsEmpty((void **)signerinfo->unAuthAttr)) @@ -721,7 +726,6 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt OSStatus rux = SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(signerinfo,timeStampPolicy); dprintf("SecCmsSignerInfoVerifyUnAuthAttrs Status: %ld\n", (long)rux); if (rux) { - syslog(LOG_ERR, "SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy failed: %d", (int)rux); goto loser; } } @@ -743,7 +747,6 @@ SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeSt * certificate signature check that failed during the cert * verification done above. Our error handling is really a mess. */ - syslog(LOG_ERR, "SecCmsSignerInforVerify bad signature PORT_GetError: %d", PORT_GetError()); if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); } @@ -923,6 +926,44 @@ xit: return status; } +/*! + @function + @abstract Return the data in the signed Codesigning Hash Agility attribute. + @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value + @discussion Returns a CFDataRef containing the value of the attribute + @result A return value of errSecInternal is an error trying to look up the oid. + A status value of success with null result data indicates the attribute was not present. + */ +OSStatus +SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata) +{ + SecCmsAttribute *attr; + CSSM_DATA_PTR value; + + if (sinfo == NULL || sdata == NULL) + return paramErr; + + *sdata = NULL; + + if (sinfo->hashAgilityAttrValue != NULL) { + *sdata = sinfo->hashAgilityAttrValue; /* cached copy */ + return SECSuccess; + } + + attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_APPLE_HASH_AGILITY, PR_TRUE); + + /* attribute not found */ + if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL) + return SECSuccess; + + sinfo->hashAgilityAttrValue = CFDataCreate(NULL, value->Data, value->Length); /* make cached copy */ + if (sinfo->hashAgilityAttrValue) { + *sdata = sinfo->hashAgilityAttrValue; + return SECSuccess; + } + return errSecAllocate; +} + /* * Return the signing cert of a CMS signerInfo. * @@ -1315,6 +1356,54 @@ SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, return SECFailure; } +/*! + @function + @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed Apple code signatures. + */ +OSStatus +SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue) +{ + SecCmsAttribute *attr; + PLArenaPool *poolp = signerinfo->cmsg->poolp; + void *mark = PORT_ArenaMark(poolp); + OSStatus status = SECFailure; + + /* The value is required for this attribute. */ + if (!attrValue) { + status = errSecParam; + goto loser; + } + + /* + * SecCmsAttributeCreate makes a copy of the data in value, so + * we don't need to copy into the CSSM_DATA struct. + */ + CSSM_DATA value; + value.Length = CFDataGetLength(attrValue); + value.Data = (uint8_t *)CFDataGetBytePtr(attrValue); + + if ((attr = SecCmsAttributeCreate(poolp, + SEC_OID_APPLE_HASH_AGILITY, + &value, + PR_FALSE)) == NULL) { + status = errSecAllocate; + goto loser; + } + + if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) { + status = errSecInternalError; + goto loser; + } + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease(poolp, mark); + return status; +} + /* * XXXX the following needs to be done in the S/MIME layer code * after signature of a signerinfo is verified diff --git a/OSX/libsecurity_smime/lib/cmstpriv.h b/OSX/libsecurity_smime/lib/cmstpriv.h index f2d10f49..012ff496 100644 --- a/OSX/libsecurity_smime/lib/cmstpriv.h +++ b/OSX/libsecurity_smime/lib/cmstpriv.h @@ -226,6 +226,7 @@ struct SecCmsSignerInfoStr { CFAbsoluteTime tsaLeafNotBefore; /* Start date for Timestamp Authority leaf */ CFAbsoluteTime tsaLeafNotAfter; /* Expiration date for Timestamp Authority leaf */ CFMutableArrayRef timestampCertList; + CFDataRef hashAgilityAttrValue; }; #define SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN 1 /* what we *create* */ #define SEC_CMS_SIGNER_INFO_VERSION_SUBJKEY 3 /* what we *create* */ diff --git a/OSX/libsecurity_smime/lib/secoid.c b/OSX/libsecurity_smime/lib/secoid.c index ac33842a..d5bdd5cc 100644 --- a/OSX/libsecurity_smime/lib/secoid.c +++ b/OSX/libsecurity_smime/lib/secoid.c @@ -159,10 +159,11 @@ #define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37 /* ECDSA OIDs from X9.62 */ -#define ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D -#define ANSI_X9_62_FIELD_TYPE ANSI_X9_62, 1 -#define ANSI_X9_62_PUBKEY_TYPE ANSI_X9_62, 2 -#define ANSI_X9_62_SIG_TYPE ANSI_X9_62, 4 +#define ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D +#define ANSI_X9_62_FIELD_TYPE ANSI_X9_62, 1 +#define ANSI_X9_62_PUBKEY_TYPE ANSI_X9_62, 2 +#define ANSI_X9_62_SIG_TYPE ANSI_X9_62, 4 +#define ECDSA_WITH_SHA2 ANSI_X9_62_SIG_TYPE, 3 /* X9.63 schemes */ #define ANSI_X9_63 0x2B, 0x81, 0x05, 0x10, 0x86, 0x48, 0x3F @@ -171,6 +172,12 @@ /* ECDH curves */ #define CERTICOM_ELL_CURVE 0x2B, 0x81, 0x04, 0x00 +/* Apple OID sapce */ +/* 1.2.840.113635 */ +#define APPLE_OID 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x63 +#define APPLE_DATA_SECURITY APPLE_OID, 0x64 +#define APPLE_CMS_ATTRIBUTES APPLE_DATA_SECURITY, 0x9 + #define CONST_OID static const unsigned char CONST_OID md2[] = { DIGEST, 0x02 }; @@ -446,8 +453,12 @@ CONST_OID aes256_KEY_WRAP[] = { AES, 45 }; CONST_OID sha256[] = { SHAXXX, 1 }; CONST_OID sha384[] = { SHAXXX, 2 }; CONST_OID sha512[] = { SHAXXX, 3 }; +CONST_OID sha224[] = { SHAXXX, 4 }; CONST_OID ecdsaWithSHA1[] = { ANSI_X9_62_SIG_TYPE, 1 }; +CONST_OID ecdsaWithSHA256[] = { ECDSA_WITH_SHA2, 2 }; +CONST_OID ecdsaWithSHA384[] = { ECDSA_WITH_SHA2, 3 }; +CONST_OID ecdsaWithSHA512[] = { ECDSA_WITH_SHA2, 4 }; CONST_OID ecPublicKey[] = { ANSI_X9_62_PUBKEY_TYPE, 1 }; /* This OID doesn't appear in a CMS msg */ CONST_OID ecdsaSig[] = { ANSI_X9_62_SIG_TYPE }; @@ -462,6 +473,9 @@ CONST_OID dhSinglePassStdDHsha1kdf[] = {ANSI_X9_63_SCHEME, 2 }; CONST_OID dhSinglePassCofactorDHsha1kdf[] = {ANSI_X9_63_SCHEME, 3 }; CONST_OID mqvSinglePassSha1kdf[] = {ANSI_X9_63_SCHEME, 4 }; +/* Apple Hash Agility */ +CONST_OID appleHashAgility[] = {APPLE_CMS_ATTRIBUTES, 1}; + /* a special case: always associated with a caller-specified OID */ CONST_OID noOid[] = { 0 }; @@ -473,7 +487,7 @@ CONST_OID noOid[] = { 0 }; #endif /* - * NOTE: the order of these entries must mach the SECOidTag enum in secoidt.h! + * NOTE: the order of these entries must match the SECOidTag enum in secoidt.h! */ const static SECOidData oids[] = { { { 0, NULL }, SEC_OID_UNKNOWN, @@ -1065,6 +1079,7 @@ const static SECOidData oids[] = { "Microsoft S/MIME Encryption Key Preference", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + OD( sha224, SEC_OID_SHA224, "SHA-224", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), OD( sha256, SEC_OID_SHA256, "SHA-256", CSSM_ALGID_SHA256, INVALID_CERT_EXTENSION), OD( sha384, SEC_OID_SHA384, "SHA-384", CSSM_ALGID_SHA384, INVALID_CERT_EXTENSION), OD( sha512, SEC_OID_SHA512, "SHA-512", CSSM_ALGID_SHA512, INVALID_CERT_EXTENSION), @@ -1121,6 +1136,22 @@ const static SECOidData oids[] = { "id-aa-signing-certificate", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + /* ECDSA with SHA2 */ + OD( ecdsaWithSHA256, SEC_OID_ECDSA_WITH_SHA256, + "ECDSA With SHA-256", CSSM_ALGID_SHA256WithECDSA, + INVALID_CERT_EXTENSION ), + OD( ecdsaWithSHA384, SEC_OID_ECDSA_WITH_SHA384, + "ECDSA With SHA-384", CSSM_ALGID_SHA384WithECDSA, + INVALID_CERT_EXTENSION ), + OD( ecdsaWithSHA512, SEC_OID_ECDSA_WITH_SHA512, + "ECDSA With SHA-512", CSSM_ALGID_SHA512WithECDSA, + INVALID_CERT_EXTENSION ), + + /* Apple Hash Agility */ + OD( appleHashAgility, SEC_OID_APPLE_HASH_AGILITY, + "appleCodesigningHashAgilityAttribute", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION), + }; /* diff --git a/OSX/libsecurity_smime/lib/security_smime.exp b/OSX/libsecurity_smime/lib/security_smime.exp index bfbea85a..ff2d9897 100644 --- a/OSX/libsecurity_smime/lib/security_smime.exp +++ b/OSX/libsecurity_smime/lib/security_smime.exp @@ -114,6 +114,7 @@ _SecCmsSignerInfoAddMSSMIMEEncKeyPrefs _SecCmsSignerInfoAddSMIMECaps _SecCmsSignerInfoAddSMIMEEncKeyPrefs _SecCmsSignerInfoAddSigningTime +_SecCmsSignerInfoAddAppleCodesigningHashAgility _SecCmsSignerInfoCreate _SecCmsSignerInfoCreateWithSubjKeyID _SecCmsSignerInfoDestroy @@ -125,6 +126,7 @@ _SecCmsSignerInfoGetSignerEmailAddress _SecCmsSignerInfoGetSigningCertificate _SecCmsSignerInfoGetSigningTime _SecCmsSignerInfoGetTimestampTime +_SecCmsSignerInfoGetAppleCodesigningHashAgility _SecCmsSignerInfoGetVerificationStatus _SecCmsSignerInfoGetEncDigest _SecCmsSignerInfoIncludeCerts diff --git a/OSX/libsecurity_transform/lib/SecCustomTransform.cpp b/OSX/libsecurity_transform/lib/SecCustomTransform.cpp index e8a243e8..9653f901 100644 --- a/OSX/libsecurity_transform/lib/SecCustomTransform.cpp +++ b/OSX/libsecurity_transform/lib/SecCustomTransform.cpp @@ -36,8 +36,6 @@ static const CFStringRef kSecCustom = CFSTR("CustomTransform"); const CFStringRef kSecTransformPreviousErrorKey = CFSTR("PreviousError"); const CFStringRef kSecTransformAbortOriginatorKey = CFSTR("Originating Transform"); const CFStringRef kSecTransformActionCanExecute = CFSTR("CanExecute"); -const CFStringRef kSecCustomTransformWhatIsRequired = CFSTR("WhatIsRequired"); -const CFStringRef kSecCustomTransformAttributesToExternalize = CFSTR("AttributesToExternalize"); const CFStringRef kSecTransformActionStartingExecution = CFSTR("ExecuteStarting"); const CFStringRef kSecTransformActionProcessData = CFSTR("TransformProcessData"); const CFStringRef kSecTransformActionAttributeNotification = CFSTR("GenericAttributeSetNotification"); diff --git a/OSX/libsecurity_transform/lib/c++utils.cpp b/OSX/libsecurity_transform/lib/c++utils.cpp index 6bc113e4..cb00ea23 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_utilities/lib/CSPDLTransaction.cpp b/OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp new file mode 100644 index 00000000..1cbe0d02 --- /dev/null +++ b/OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp @@ -0,0 +1,100 @@ +/* + * 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 "CSPDLTransaction.h" +#include +#include + +DLTransaction::DLTransaction(CSSM_DL_DB_HANDLE dldbh) + : mDldbh(dldbh), mSuccess(false), mFinalized(false), mAutoCommit(CSSM_TRUE) { + initialize(); +} + +DLTransaction::DLTransaction() + : mSuccess(false), mFinalized(false), mAutoCommit(CSSM_TRUE) { +} + +void DLTransaction::initialize() { + // Turn off autocommit on the underlying DL and remember the old state. + Security::CssmClient::ObjectImpl::check(CSSM_DL_PassThrough(mDldbh, + CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT, + NULL, reinterpret_cast(&mAutoCommit))); +} + +DLTransaction::~DLTransaction() { + finalize(); +} + +void DLTransaction::success() { + mSuccess = true; +} + +void DLTransaction::finalize() { + if(mFinalized) { + 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); + } + } + } + mFinalized = true; +} + + +CSPDLTransaction::CSPDLTransaction(Security::CssmClient::Db& db) + : DLTransaction(), mDb(db) { + // Get the handle of the DL underlying this CSPDL. + mDb->passThrough(CSSM_APPLECSPDL_DB_GET_HANDLE, NULL, + reinterpret_cast(&mDldbh)); + + initialize(); +} + +CSPDLTransaction::~CSPDLTransaction() { + finalize(); +} + diff --git a/OSX/libsecurity_utilities/lib/CSPDLTransaction.h b/OSX/libsecurity_utilities/lib/CSPDLTransaction.h new file mode 100644 index 00000000..2a5adce3 --- /dev/null +++ b/OSX/libsecurity_utilities/lib/CSPDLTransaction.h @@ -0,0 +1,77 @@ +/* + * 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 _H_CSPDLTRANSACTION +#define _H_CSPDLTRANSACTION + +#include + +// +// This class performs a transaction on a CSPDL database. +// +// It will commit when: +// +// 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... +// +class DLTransaction { +public: + DLTransaction(CSSM_DL_DB_HANDLE dldbh); + + ~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(); + +protected: + DLTransaction(); + + // Actually toggle autocommit using the dldbh + void initialize(); + + CSSM_DL_DB_HANDLE mDldbh; + + bool mSuccess; + bool mFinalized; + + CSSM_BOOL mAutoCommit; +}; + +class CSPDLTransaction : public DLTransaction { +public: + CSPDLTransaction(Security::CssmClient::Db& db); + ~CSPDLTransaction(); + +private: + Security::CssmClient::Db& mDb; +}; + +#endif // _H_CSPDLTRANSACTION diff --git a/OSX/libsecurity_utilities/lib/cfmunge.cpp b/OSX/libsecurity_utilities/lib/cfmunge.cpp index d2c6a4dc..b3776ed5 100644 --- a/OSX/libsecurity_utilities/lib/cfmunge.cpp +++ b/OSX/libsecurity_utilities/lib/cfmunge.cpp @@ -289,7 +289,18 @@ CFTypeRef CFMake::makearray() { ++format; // next '[' next('!'); // indicates mutable (currently always) - CFMutableArrayRef array = makeCFMutableArray(0); + CFMutableArrayRef array = NULL; + if (next('+')) { // {+%O, => copy array argument, then proceed + if (next('%') && next('O')) { + CFArrayRef source = va_arg(args, CFArrayRef); + array = CFArrayCreateMutableCopy(allocator, 0, source); + if (next('}')) + return array; + } else + return NULL; // bad syntax + } else { + array = makeCFMutableArray(0); + } while (next() != ']') { CFTypeRef value = make(); if (value == NULL) { diff --git a/OSX/libsecurity_utilities/lib/cfutilities.h b/OSX/libsecurity_utilities/lib/cfutilities.h index ad4fc80d..b8a38d3a 100644 --- a/OSX/libsecurity_utilities/lib/cfutilities.h +++ b/OSX/libsecurity_utilities/lib/cfutilities.h @@ -409,12 +409,17 @@ inline CFDataRef makeCFData(const void *data, size_t size) { return CFDataCreate(NULL, (const UInt8 *)data, size); } - + inline CFDataRef makeCFData(CFDictionaryRef dictionary) { return CFPropertyListCreateXMLData(NULL, dictionary); } +inline CFDataRef makeCFData(CFArrayRef array) +{ + return CFPropertyListCreateXMLData(NULL, array); +} + template inline CFDataRef makeCFData(const Data &source) { @@ -618,7 +623,7 @@ CFToVector::CFToVector(CFArrayRef arrayRef) // Make CFArrays from stuff. // template -inline CFArrayRef makeCFArray(Generator &generate, Iterator first, Iterator last) +inline CFArrayRef makeCFArrayFrom(const Generator &generate, Iterator first, Iterator last) { // how many elements? size_t size = distance(first, last); @@ -632,9 +637,9 @@ inline CFArrayRef makeCFArray(Generator &generate, Iterator first, Iterator last } template -inline CFArrayRef makeCFArray(Generator &generate, const Container &container) +inline CFArrayRef makeCFArrayFrom(const Generator &generate, const Container &container) { - return makeCFArray(generate, container.begin(), container.end()); + return makeCFArrayFrom(generate, container.begin(), container.end()); } CFArrayRef makeCFArray(CFIndex count, ...) CF_RETURNS_RETAINED; diff --git a/OSX/libsecurity_utilities/lib/debugging_internal.cpp b/OSX/libsecurity_utilities/lib/debugging_internal.cpp index 83d2624c..53aeecd7 100644 --- a/OSX/libsecurity_utilities/lib/debugging_internal.cpp +++ b/OSX/libsecurity_utilities/lib/debugging_internal.cpp @@ -45,3 +45,23 @@ void secdebug_internal(const char* scope, const char* format, ...) 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); + } +} diff --git a/OSX/libsecurity_utilities/lib/debugging_internal.h b/OSX/libsecurity_utilities/lib/debugging_internal.h index f4e7cb85..6f990296 100644 --- a/OSX/libsecurity_utilities/lib/debugging_internal.h +++ b/OSX/libsecurity_utilities/lib/debugging_internal.h @@ -43,8 +43,10 @@ typedef const void *DTException; // 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)) // diff --git a/OSX/libsecurity_utilities/lib/exports b/OSX/libsecurity_utilities/lib/exports index b799d116..d9e60230 100644 --- a/OSX/libsecurity_utilities/lib/exports +++ b/OSX/libsecurity_utilities/lib/exports @@ -1 +1,2 @@ _secdebug_internal +_secdebugfunc_internal diff --git a/OSX/libsecurity_utilities/lib/hashing.h b/OSX/libsecurity_utilities/lib/hashing.h index a54d2b4e..b9117998 100644 --- a/OSX/libsecurity_utilities/lib/hashing.h +++ b/OSX/libsecurity_utilities/lib/hashing.h @@ -31,6 +31,7 @@ #include #include #include +#include #include // SPI slated to become API namespace Security { @@ -52,7 +53,7 @@ public: // // If you write template code based on "any static hasher", you can directly tap here // (and learn the actual hash in use through the match on _HashType). But note that -// a DynamicHash is not a subclass of Hash, though a DynamicHashInstance will be, duck-like. +// a DynamicHash is not a subclass of Hash. // template class Hash : public Hashing { @@ -93,12 +94,14 @@ public: // This isn't a subclass of Hash (which is static-fast), but it's duck-typed to it. // Note that digestLength is a function here, not a constant. Obviously. // -class DynamicHash : public Hashing { +class DynamicHash : public RefCount, public Hashing { public: virtual ~DynamicHash(); virtual size_t digestLength() const = 0; virtual void update(const void *data, size_t length) = 0; + template + void update(const _Dataoid &doid) { this->update(doid.data(), doid.length()); } virtual void finish(Byte *digest) = 0; void operator () (const void *data, size_t length) @@ -109,30 +112,6 @@ public: }; -// -// Make a DynamicHash from a static Hash class. -// -template -class DynamicHashInstance : public DynamicHash, public _HashType { -public: - // (wish we had C++0x already...) - DynamicHashInstance() { } - template - DynamicHashInstance(const Arg1 &arg1) : _HashType(arg1) { } - template - DynamicHashInstance(const Arg1 &arg1, const Arg2 &arg2) : _HashType(arg1, arg2) { } - template - DynamicHashInstance(const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) : _HashType(arg1, arg2, arg3) { } - - size_t digestLength() const - { return _HashType::digestLength; } - void update(const void *data, size_t length) - { return _HashType::update(data, length); } - void finish(unsigned char *digest) - { return _HashType::finish(digest); } -}; - - // // Make a DynamicHash from a CommonCrypto hash algorithm identifier // @@ -159,9 +138,9 @@ private: // object out there by asking nicely (by default, calling its getHash() method). // template -class MakeHash : public std::auto_ptr { +class MakeHash : public RefPointer { public: - MakeHash(const _Giver *giver) : std::auto_ptr((giver->*_fetcher)()) { } + MakeHash(const _Giver *giver) : RefPointer((giver->*_fetcher)()) { } operator DynamicHash *() const { return this->get(); } }; diff --git a/OSX/libsecurity_utilities/lib/macho++.cpp b/OSX/libsecurity_utilities/lib/macho++.cpp index 97b2ea6c..ed3a2fea 100644 --- a/OSX/libsecurity_utilities/lib/macho++.cpp +++ b/OSX/libsecurity_utilities/lib/macho++.cpp @@ -412,6 +412,19 @@ const linkedit_data_command *MachOBase::findLibraryDependencies() const return reinterpret_cast(cmd); return NULL; // not found } + +const version_min_command *MachOBase::findMinVersion() const +{ + for (const load_command *command = loadCommands(); command; command = nextCommand(command)) + switch (flip(command->cmd)) { + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_WATCHOS: + case LC_VERSION_MIN_TVOS: + return reinterpret_cast(command); + } + return NULL; +} // diff --git a/OSX/libsecurity_utilities/lib/macho++.h b/OSX/libsecurity_utilities/lib/macho++.h index d75b0843..b9e9bc7b 100644 --- a/OSX/libsecurity_utilities/lib/macho++.h +++ b/OSX/libsecurity_utilities/lib/macho++.h @@ -108,6 +108,7 @@ public: const linkedit_data_command *findCodeSignature() const; const linkedit_data_command *findLibraryDependencies() const; + const version_min_command *findMinVersion() const; size_t signingOffset() const; // starting offset of CS section, or 0 if none size_t signingLength() const; // length of CS section, or 0 if none diff --git a/OSX/libsecurity_utilities/lib/memstreams.h b/OSX/libsecurity_utilities/lib/memstreams.h index 0c7ac496..f3287805 100644 --- a/OSX/libsecurity_utilities/lib/memstreams.h +++ b/OSX/libsecurity_utilities/lib/memstreams.h @@ -110,7 +110,7 @@ public: size_t operator () (const char *s) { align(); return totalSoFar += strlen(s) + 1; } void countedData(const void *, size_t length) - { insert(sizeof(length)); insert(length); } + { insert(sizeof(uint32_t)); insert(length); } template void countedData(const Data &data) @@ -121,6 +121,28 @@ private: }; +// A variant of Writer which returns offsets from the start of the buffer from the operator() functions. +class OffsetWriter : Writer { +public: + OffsetWriter() { } + OffsetWriter(void *base) : Writer(base), basePos(base) { } + void operator = (void *base) { basePos = base; Writer::operator = (base); } + + template + T *operator () (const T &obj) + { return Writer::operator() (obj) - basePos; } + + void *operator () (const void *addr, size_t size) + { return reinterpret_cast(uintptr_t(Writer::operator() (addr, size)) - uintptr_t(basePos)); } + + char *operator () (const char *s) + { return (char *)(*this)(s, strlen(s) + 1); } + +private: + void *basePos; // base address +}; + + // // The Reader counter-part for a Writer. // Again, Reader and Writer share alignment and representation rules, so what was diff --git a/OSX/libsecurity_utilities/lib/superblob.h b/OSX/libsecurity_utilities/lib/superblob.h index 785f51ce..e6b8edc8 100644 --- a/OSX/libsecurity_utilities/lib/superblob.h +++ b/OSX/libsecurity_utilities/lib/superblob.h @@ -6,6 +6,7 @@ #include #include +#include namespace Security { @@ -135,7 +136,8 @@ public: return (it == mPieces.end()) ? NULL : it->second; } - size_t size(size_t size1 = 0, ...) const; // size with optional additional blob sizes +// size_t size(size_t size1 = 0, ...) const; // size with optional additional blob sizes + size_t size(const std::vector &sizes, size_t size1 = 0, ...) const; // same with array-of-sizes input _BlobType *make() const; // create (malloc) and return SuperBlob _BlobType *operator () () const { return make(); } @@ -181,15 +183,20 @@ void SuperBlobCore<_BlobType, _magic, _Type>::Maker::add(const Maker &maker) // so far, plus additional blobs with the sizes given. // template -size_t SuperBlobCore<_BlobType, _magic, _Type>::Maker::size(size_t size1, ...) const +size_t SuperBlobCore<_BlobType, _magic, _Type>::Maker::size(const std::vector &sizes, size_t size1, ...) const { // count established blobs size_t count = mPieces.size(); size_t total = 0; - for (typename BlobMap::const_iterator it = mPieces.begin(); it != mPieces.end(); ++it) + for (auto it = mPieces.begin(); it != mPieces.end(); ++it) total += it->second->length(); + + // add more blobs from the sizes array + for (auto it = sizes.begin(); it != sizes.end(); ++it) + total += *it; + count += sizes.size(); - // add preview blob sizes to calculation (if any) + // add more blobs from individual sizes specified if (size1) { va_list args; va_start(args, size1); @@ -213,7 +220,7 @@ template _BlobType *SuperBlobCore<_BlobType, _magic, _Type>::Maker::make() const { Offset pc = (Offset)(sizeof(SuperBlobCore) + mPieces.size() * sizeof(Index)); - Offset total = (Offset)size(); + Offset total = (Offset)size(vector(), 0); _BlobType *result = (_BlobType *)malloc(total); if (!result) UnixError::throwMe(ENOMEM); diff --git a/OSX/libsecurity_utilities/lib/threading.cpp b/OSX/libsecurity_utilities/lib/threading.cpp index 9e0bed64..bfe6427c 100644 --- a/OSX/libsecurity_utilities/lib/threading.cpp +++ b/OSX/libsecurity_utilities/lib/threading.cpp @@ -194,6 +194,57 @@ void CountingMutex::finishExit() unlock(); } +// +// ReadWriteLock implementation +// +ReadWriteLock::ReadWriteLock() { + check(pthread_rwlock_init(&mLock, NULL)); +} + +bool ReadWriteLock::lock() { + check(pthread_rwlock_rdlock(&mLock)); + return true; +} + +bool ReadWriteLock::tryLock() { + return (pthread_rwlock_tryrdlock(&mLock) == 0); +} + +bool ReadWriteLock::writeLock() { + check(pthread_rwlock_wrlock(&mLock)); + return true; +} + +bool ReadWriteLock::tryWriteLock() { + return (pthread_rwlock_trywrlock(&mLock) == 0); +} + +void ReadWriteLock::unlock() { + check(pthread_rwlock_unlock(&mLock)); +} + +// +// StReadWriteLock implementation +// +bool StReadWriteLock::lock() { + switch(mType) { + case Read: mIsLocked = mRWLock.lock(); break; + case TryRead: mIsLocked = mRWLock.tryLock(); break; + case Write: mIsLocked = mRWLock.writeLock(); break; + case TryWrite: mIsLocked = mRWLock.tryWriteLock(); break; + } + return mIsLocked; +} + +void StReadWriteLock::unlock() { + mRWLock.unlock(); + mIsLocked = false; +} + +bool StReadWriteLock::isLocked() { + return mIsLocked; +} + // diff --git a/OSX/libsecurity_utilities/lib/threading.h b/OSX/libsecurity_utilities/lib/threading.h index a903dc10..60168536 100644 --- a/OSX/libsecurity_utilities/lib/threading.h +++ b/OSX/libsecurity_utilities/lib/threading.h @@ -197,7 +197,27 @@ public: private: unsigned int mCount; // counter level }; - + +// +// A ReadWriteLock is a wrapper around a pthread_rwlock +// +class ReadWriteLock : public Mutex { +public: + ReadWriteLock(); + ~ReadWriteLock() { check(pthread_rwlock_destroy(&mLock)); } + + // Takes the read lock + bool lock(); + bool tryLock(); + void unlock(); + + bool writeLock(); + bool tryWriteLock(); + +private: + pthread_rwlock_t mLock; +}; + // // A guaranteed-unlocker stack-based class. @@ -228,6 +248,31 @@ protected: bool mActive; }; +// Note: if you use the TryRead or TryWrite modes, you must check if you +// actually have the lock before proceeding +class StReadWriteLock { +public: + enum Type { + Read, + TryRead, + Write, + TryWrite + }; + StReadWriteLock(ReadWriteLock &lck, Type type) : mType(type), mIsLocked(false), mRWLock(lck) + { lock(); } + ~StReadWriteLock() { if(mIsLocked) mRWLock.unlock(); } + + bool lock(); + void unlock(); + bool isLocked(); + +protected: + Type mType; + bool mIsLocked; + ReadWriteLock& mRWLock; +}; + + template blobVersion = getCurrentVersion(); +} // // Initialize the blob header for a given version @@ -38,6 +66,8 @@ namespace SecurityServer { void CommonBlob::initialize(uint32 version) { magic = magicNumber; + + secdebugfunc("integrity", "creating a partition keychain with version %d", version); this->blobVersion = version; } diff --git a/OSX/libsecurityd/lib/ssblob.h b/OSX/libsecurityd/lib/ssblob.h index d05f2b73..e39414be 100644 --- a/OSX/libsecurityd/lib/ssblob.h +++ b/OSX/libsecurityd/lib/ssblob.h @@ -77,10 +77,13 @@ public: static const uint32 version_MacOS_10_0 = 0x00000100; // MacOS 10.0.x static const uint32 version_MacOS_10_1 = 0x00000101; // MacOS 10.1.x and on - static const uint32 currentVersion = version_MacOS_10_0; + static const uint32 version_partition = 0x00000200; // MacOS 10.11.2 and on, supporting partitioning + static const uint32 currentVersion = version_partition; + static uint32 getCurrentVersion(); public: - void initialize(uint32 version = currentVersion); + void initialize(); + void initialize(uint32 version); bool isValid() const; void validate(CSSM_RETURN failureCode) const; diff --git a/OSX/libsecurityd/lib/ssclient.h b/OSX/libsecurityd/lib/ssclient.h index 6af1fd97..5b4e2d78 100644 --- a/OSX/libsecurityd/lib/ssclient.h +++ b/OSX/libsecurityd/lib/ssclient.h @@ -183,6 +183,7 @@ public: DbHandle cloneDbForSync(const CssmData &secretsBlob, DbHandle srcDb, const CssmData &agentData); DbHandle recodeDbForSync(DbHandle dbToClone, DbHandle srcDb); + DbHandle recodeDbToVersion(uint32 newVersion, DbHandle srcDb); DbHandle authenticateDbsForSync(const CssmData &dbHandleArray, const CssmData &agentData); void commitDbForSync(DbHandle srcDb, DbHandle cloneDb, CssmData &blob, Allocator &alloc); DbHandle decodeDb(const DLDbIdentifier &dbId, diff --git a/OSX/libsecurityd/lib/transition.cpp b/OSX/libsecurityd/lib/transition.cpp index 58a20823..b34fa376 100644 --- a/OSX/libsecurityd/lib/transition.cpp +++ b/OSX/libsecurityd/lib/transition.cpp @@ -275,6 +275,15 @@ DbHandle ClientSession::recodeDbForSync(DbHandle dbToClone, return newDb; } +DbHandle ClientSession::recodeDbToVersion(uint32 newVersion, DbHandle srcDb) +{ + DbHandle newDb; + + IPC(ucsp_client_recodeDbToVersion(UCSP_ARGS, newVersion, srcDb, &newDb)); + + return newDb; +} + DbHandle ClientSession::authenticateDbsForSync(const CssmData &dbHandleArray, const CssmData &agentData) { diff --git a/OSX/libsecurityd/mig/ucsp.defs b/OSX/libsecurityd/mig/ucsp.defs index 0dc58dde..e7bb7348 100644 --- a/OSX/libsecurityd/mig/ucsp.defs +++ b/OSX/libsecurityd/mig/ucsp.defs @@ -333,3 +333,9 @@ routine stashDbCheck(UCSP_PORTS; in db: IPCDbHandle); routine verifyKeyStorePassphrase(UCSP_PORTS; in retries: uint32_t); routine resetKeyStorePassphrase(UCSP_PORTS; in passPhrase: Data); routine changeKeyStorePassphrase(UCSP_PORTS); + +// +// Keychain version change support calls +// +routine recodeDbToVersion(UCSP_PORTS; in newVersion: uint32; + in srcDb: IPCDbHandle; out newDb: IPCDbHandle); diff --git a/OSX/regressions/regressions.xcodeproj/project.pbxproj b/OSX/regressions/regressions.xcodeproj/project.pbxproj index 03fad3c9..d2c407cf 100644 --- a/OSX/regressions/regressions.xcodeproj/project.pbxproj +++ b/OSX/regressions/regressions.xcodeproj/project.pbxproj @@ -11,7 +11,7 @@ 4CC92ABC15A3B51100C6D578 /* test_regressions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92ABB15A3B51100C6D578 /* test_regressions.h */; settings = {ATTRIBUTES = (); }; }; 4CC92ABD15A3B8FB00C6D578 /* testlist_begin.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CC92AB715A3B19100C6D578 /* testlist_begin.h */; settings = {ATTRIBUTES = (); }; }; 4CC92B1715A3BD1E00C6D578 /* test-00-test.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CC92B1615A3BD1E00C6D578 /* test-00-test.c */; }; - E710C7371331938000F85568 /* testenv.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C25A6C412271FAF0050C2BD /* testenv.c */; }; + E710C7371331938000F85568 /* testenv.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C25A6C412271FAF0050C2BD /* testenv.m */; }; E710C7381331938000F85568 /* testmore.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C25A6C812271FAF0050C2BD /* testmore.c */; }; E710C7391331938000F85568 /* testcert.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C25A6CA12271FAF0050C2BD /* testcert.c */; }; E723A60F13DA18C50075AAC1 /* testcpp.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C25A6C312271FAF0050C2BD /* testcpp.h */; settings = {ATTRIBUTES = (); }; }; @@ -28,7 +28,7 @@ 0C25A69312271FAF0050C2BD /* MyHarness.pm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = MyHarness.pm; sourceTree = ""; }; 0C25A6C012271FAF0050C2BD /* security.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = security.pl; sourceTree = ""; }; 0C25A6C312271FAF0050C2BD /* testcpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testcpp.h; sourceTree = ""; }; - 0C25A6C412271FAF0050C2BD /* testenv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testenv.c; sourceTree = ""; }; + 0C25A6C412271FAF0050C2BD /* testenv.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = testenv.m; sourceTree = ""; }; 0C25A6C512271FAF0050C2BD /* testenv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testenv.h; sourceTree = ""; }; 0C25A6C812271FAF0050C2BD /* testmore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testmore.c; sourceTree = ""; }; 0C25A6C912271FAF0050C2BD /* testmore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testmore.h; sourceTree = ""; }; @@ -99,7 +99,7 @@ 4CC92AB715A3B19100C6D578 /* testlist_begin.h */, 4CC92AB815A3B19D00C6D578 /* testlist_end.h */, 0C25A6C312271FAF0050C2BD /* testcpp.h */, - 0C25A6C412271FAF0050C2BD /* testenv.c */, + 0C25A6C412271FAF0050C2BD /* testenv.m */, 0C25A6C512271FAF0050C2BD /* testenv.h */, 0C25A6C812271FAF0050C2BD /* testmore.c */, 0C25A6C912271FAF0050C2BD /* testmore.h */, @@ -183,7 +183,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E710C7371331938000F85568 /* testenv.c in Sources */, + E710C7371331938000F85568 /* testenv.m in Sources */, E710C7381331938000F85568 /* testmore.c in Sources */, E710C7391331938000F85568 /* testcert.c in Sources */, E76CA47913D8D5B4001B6A11 /* testpolicy.m in Sources */, diff --git a/OSX/regressions/test/testenv.c b/OSX/regressions/test/testenv.m similarity index 95% rename from OSX/regressions/test/testenv.c rename to OSX/regressions/test/testenv.m index bd85e157..4bdf4671 100644 --- a/OSX/regressions/test/testenv.c +++ b/OSX/regressions/test/testenv.m @@ -23,6 +23,15 @@ * testenv.c */ +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + + +#import #include #include #include @@ -224,7 +233,9 @@ static int tests_run_all(int argc, char * const *argv) for (i = 0; testlist[i].name; ++i) { if(!testlist[i].off) { - failcount+=tests_run_test(&testlist[i], argc, argv); + @autoreleasepool { + failcount+=tests_run_test(&testlist[i], argc, argv); + } optind = curroptind; } } @@ -325,10 +336,6 @@ tests_begin(int argc, char * const *argv) { #endif }; - // TODO Currently our callers do this, but we can move this here together with the build date info. - const char *progname = strrchr(argv[0], '/'); - progname = progname ? progname + 1 : argv[0]; - for (;;) { while (!testcase && (ch = getopt(argc, argv, "bklL1vwqs")) != -1) { @@ -382,7 +389,7 @@ tests_begin(int argc, char * const *argv) { } if (!list && !initialized && !test_onebatstest) - fprintf(stdout, "[TEST] %s\n", progname); + fprintf(stdout, "[TEST] %s\n", getprogname()); if (testix < 0) { if (!initialized) { tests_init(); @@ -402,8 +409,11 @@ tests_begin(int argc, char * const *argv) { } optind++; testlist[testix].off = 0; - if (!list) - failcount+=tests_run_test(&testlist[testix], argc, argv); + if (!list) { + @autoreleasepool { + failcount+=tests_run_test(&testlist[testix], argc, argv); + } + } testix = -1; } } @@ -414,7 +424,7 @@ tests_begin(int argc, char * const *argv) { } } } else { - tests_summary(progname); + tests_summary(getprogname()); } remove_security_log_handler(handle_logs); diff --git a/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h b/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h index 37360eda..91635b4f 100644 --- a/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h +++ b/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h @@ -73,6 +73,12 @@ @property (atomic) dispatch_queue_t calloutQueue; @property (atomic) dispatch_queue_t freshParamsQueue; +@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; + + (UbiqitousKVSProxy *) sharedKVSProxy; - (NSString *)description; - (id)init; @@ -116,6 +122,7 @@ - (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/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m b/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m index deef7548..bada77e5 100644 --- a/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m +++ b/OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m @@ -78,6 +78,28 @@ 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 *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; + enum { kCallbackMethodSecurityd = 0, @@ -130,6 +152,8 @@ static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms lee _calloutQueue = dispatch_queue_create("CKDCallout", DISPATCH_QUEUE_SERIAL); _freshParamsQueue = dispatch_queue_create("CKDFresh", DISPATCH_QUEUE_SERIAL); + _ckdkvsproxy_queue = dispatch_get_main_queue(); + _syncTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); dispatch_source_set_timer(_syncTimer, DISPATCH_TIME_FOREVER, DISPATCH_TIME_FOREVER, kSyncTimerLeeway); dispatch_source_set_event_handler(_syncTimer, ^{ @@ -137,6 +161,8 @@ static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms lee }); dispatch_resume(_syncTimer); + _monitor = [NSMutableDictionary dictionary]; + [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (iCloudAccountAvailabilityChanged:) @@ -147,7 +173,13 @@ static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms lee selector:@selector(cloudChanged:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:nil]; - + 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 @@ -229,6 +261,277 @@ static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms lee } } +-(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]; + } + //decrease timeout since we successfully wrote messages out + NSNumber *penalty_timeout = [keyEntry valueForKey:kMonitorPenaltyBoxKey]; + [self decreasePenalty:penalty_timeout key:key keyEntry:&keyEntry]; + + //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) + secnotice("backoff","still in timeout, shouldn't write anything to KVS in this time period"); + else + secnotice("backoff","monitor: keys have been written for 5 or more minutes, time to bump penalty timers"); + [self increasePenalty:penalty_timeout key:key keyEntry:&keyEntry]; + } + //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; +} + - (void)setObjectsFromDictionary:(NSDictionary *)values { NSUbiquitousKeyValueStore *store = [self cloudStore]; @@ -236,7 +539,8 @@ static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250); // 250ms lee { secnoticeq("dsid", "Ensure DSIDs match"); NSMutableDictionary *mutableValues = [NSMutableDictionary dictionaryWithCapacity:0]; - + + secnotice("backoff","!!writing these keys to KVS!!: %@", values); [values enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { if (obj == NULL || obj == [NSNull null]) @@ -455,12 +759,7 @@ static void wait_until(dispatch_time_t when) { return @{ kKeyAlwaysKeys:[_alwaysKeys allObjects], kKeyFirstUnlockKeys:[_firstUnlockKeys allObjects], kKeyUnlockedKeys:[_unlockedKeys allObjects], - -#if 0 - kKeyKeyParameterKeys: _keyParameterKeys, - kKeyMessageKeys : _messageKeys, - kKeyCircleKeys : _circleKeys, -#endif + kMonitorState:_monitor, kKeyPendingKeys:[_pendingKeys allObjects], kKeySyncWithPeersPending:[NSNumber numberWithBool:_syncWithPeersPending], kKeyEnsurePeerRegistration:[NSNumber numberWithBool:_ensurePeerRegistration], @@ -478,6 +777,9 @@ static void wait_until(dispatch_time_t when) { _syncWithPeersPending = [interests[kKeySyncWithPeersPending] boolValue]; _ensurePeerRegistration = [interests[kKeyEnsurePeerRegistration] boolValue]; _dsid = interests[kKeyDSID]; + _monitor = interests[kMonitorState]; + if(_monitor == nil) + _monitor = [NSMutableDictionary dictionary]; } - (NSMutableSet *)copyAllKeys diff --git a/OSX/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m b/OSX/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m index 0b2fe801..4b4e2d24 100644 --- a/OSX/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m +++ b/OSX/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m @@ -275,7 +275,11 @@ static bool operation_put_dictionary(xpc_object_t event) CFTypeRef cfvalue = _CFXPCCreateCFObjectFromXPCObject(xvalue); if (cfvalue && (CFGetTypeID(cfvalue)==CFDictionaryGetTypeID())) { - [[UbiqitousKVSProxy sharedKVSProxy] setObjectsFromDictionary:(__bridge NSDictionary *)cfvalue]; + [[UbiqitousKVSProxy sharedKVSProxy] recordWriteToKVS:(__bridge NSDictionary *)cfvalue]; + NSDictionary *safeValues = [[UbiqitousKVSProxy sharedKVSProxy] recordHaltedValuesAndReturnValuesToSafelyWrite:(__bridge NSDictionary *)cfvalue]; + if([safeValues count] !=0){ + [[UbiqitousKVSProxy sharedKVSProxy] setObjectsFromDictionary:safeValues]; + } CFReleaseSafe(cfvalue); return true; } diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.m b/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.m index c77de44d..2288fc56 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.m +++ b/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.m @@ -410,8 +410,8 @@ fail: IDSMessagePriority priority = IDSMessagePriorityHigh; IDSDevice *device = nil; BOOL encryptionOff = YES; - - NSDictionary *options = [ NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:encryptionOff], IDSSendMessageOptionForceEncryptionOffKey, nil ]; + NSError *localError = nil; + NSDictionary *options = @{IDSSendMessageOptionForceEncryptionOffKey : [NSNumber numberWithBool:encryptionOff] }; require_action_quiet(_service, fail, errorMessage = @"Could not send message: IDS delegate uninitialized, can't use IDS to send this message"; code = kSecIDSErrorNotRegistered); @@ -427,11 +427,12 @@ fail: [destinations addObject: IDSCopyIDForDevice(device)]; } } + require_action_quiet([destinations count] != 0, fail, errorMessage = @"Could not send message: IDS device ID for peer does not match any devices within an IDS Account"; code = kSecIDSErrorCouldNotFindMatchingAuthToken); - result = [_service sendMessage:data toDestinations:destinations priority:priority options:options identifier:&identifier error:error ] ; + result = [_service sendMessage:data toDestinations:destinations priority:priority options:options identifier:&identifier error:&localError ] ; - require_action_quiet(*error == nil, fail, errorMessage = @"Had an error sending IDS message"; code = kSecIDSErrorFailedToSend); + require_action_quiet(localError == nil, fail, errorMessage = @"Had an error sending IDS message"; code = kSecIDSErrorFailedToSend); secdebug("IDS Transport", "IDSKeychainSyncingProxy sent this message over IDS: %@", data); @@ -443,7 +444,9 @@ fail: *error = [NSError errorWithDomain:@"com.apple.security.ids.error" code:code userInfo:userInfo]; secerror("%@", *error); } - + if(localError != nil) + secerror("%@", localError); + return false; } @@ -528,14 +531,20 @@ fail: secdebug("IDS Transport", "IDSKeychainSyncingProxy handling this message sent over IDS%@", message); NSString *dataKey = [ NSString stringWithUTF8String: kMessageKeyIDSDataMessage ]; NSString *deviceIDKey = [ NSString stringWithUTF8String: kMessageKeyDeviceID ]; + NSString *peerIDKey = [ NSString stringWithUTF8String: kMessageKeyPeerID ]; NSString *ID = nil; uint32_t operationType; bool hadError = false; CFStringRef errorMessage = NULL; __block NSString* operation = nil; + __block NSString* myPeerID = @""; NSString *messageString = nil; __block NSData *messageData = nil; - + __block NSString *messageAsString = nil; + __block BOOL operationIsString = false; + __block BOOL messageStringIsString = false; + __block BOOL messageDataIsData = false; + NSArray *devices = [_service devices]; for(NSUInteger i = 0; i < [ devices count ]; i++){ IDSDevice *device = devices[i]; @@ -544,15 +553,34 @@ fail: break; } } + require_action_quiet(ID, fail, hadError = true; errorMessage = CFSTR("require the sender's device ID")); - require_action_quiet([message count] == 1, fail, hadError = true; errorMessage = CFSTR("message contained too many objects");); + require_action_quiet([message count] == 1, fail, hadError = true; errorMessage = CFSTR("message contained too many objects")); [message enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop){ operation = (NSString*)key; - messageData = (NSData*)obj; + operationIsString = (CFGetTypeID((__bridge CFTypeRef)(operation)) == CFStringGetTypeID()); + + if(CFGetTypeID((__bridge CFTypeRef)(obj)) == CFDataGetTypeID()){ + messageDataIsData = true; + messageData = (NSData*)obj; + } + else if(CFGetTypeID((__bridge CFTypeRef)(obj)) == CFStringGetTypeID()){ + messageStringIsString = true; + messageAsString = (NSString*)obj; + } }]; + require_action_quiet(operationIsString, fail, hadError = true; errorMessage = CFSTR("unexpected opeartion type");); + + if(messageData) + require_action_quiet(messageDataIsData, fail, hadError = true; errorMessage = CFSTR("unexpected message type");); + else if(messageAsString) + require_action_quiet(messageStringIsString, fail, hadError = true; errorMessage = CFSTR("unexpected message type");); + operationType = [operation intValue]; + if(operationType == 0) + myPeerID = operation; switch(operationType){ case kIDSPeerAvailabilityDone: @@ -594,7 +622,7 @@ fail: } default: { - NSDictionary *messageAndFromID = @{dataKey : messageData, deviceIDKey: ID}; + NSDictionary *messageAndFromID = @{dataKey : messageData, deviceIDKey: ID, peerIDKey: myPeerID}; if(_isLocked){ //hang on to the message and set the retry deadline [_unhandledMessageBuffer setObject: messageAndFromID forKey: fromID]; @@ -654,3 +682,4 @@ fail: @end + diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist b/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist index 66dcbf59..5282d8a1 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist +++ b/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist @@ -8,7 +8,7 @@ com.apple.private.ids.force-encryption-off - com.apple.security.idskeychainsyncingproxy + com.apple.private.alloy.keychainsync com.apple.private.ids.messaging.high-priority diff --git a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m b/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m index d882635c..365eedc4 100644 --- a/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m +++ b/OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m @@ -98,10 +98,17 @@ static void idskeychainsyncingproxy_peer_dictionary_handler(const xpc_connection NSString *deviceName = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xDeviceName)); NSString *peerID = (__bridge_transfer NSString*)(_CFXPCCreateCFObjectFromXPCObject(xPeerID)); - NSDictionary *messageData = (__bridge_transfer NSDictionary*)(_CFXPCCreateCFObjectFromXPCObject(xidsMessageData)); + 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); - BOOL object = [[IDSKeychainSyncingProxy idsProxy] sendIDSMessage:messageData name:deviceName peer:peerID error:&error]; + BOOL object = [[IDSKeychainSyncingProxy idsProxy] sendIDSMessage:messageDictionary name:deviceName peer:peerID error:&error]; xpc_object_t replyMessage = xpc_dictionary_create_reply(event); xpc_dictionary_set_bool(replyMessage, kMessageKeyValue, object); diff --git a/OSX/sec/SOSCircle/Regressions/SOSRegressionUtilities.c b/OSX/sec/SOSCircle/Regressions/SOSRegressionUtilities.c index 28dcbf74..21e6d66d 100644 --- a/OSX/sec/SOSCircle/Regressions/SOSRegressionUtilities.c +++ b/OSX/sec/SOSCircle/Regressions/SOSRegressionUtilities.c @@ -330,6 +330,8 @@ SOSFullPeerInfoRef SOSCreateFullPeerInfoFromName(CFStringRef name, SecKeyRef* ou //GeneratePermanentECPair(256, &publicKey, outSigningKey); *outSigningKey = GeneratePermanentFullECKey(256, name, error); + require(*outSigningKey, exit); + gestalt = SOSCreatePeerGestaltFromName(name); require(gestalt, exit); diff --git a/OSX/sec/SOSCircle/Regressions/SOSTestDataSource.c b/OSX/sec/SOSCircle/Regressions/SOSTestDataSource.c index 1f9b3dec..290aa985 100644 --- a/OSX/sec/SOSCircle/Regressions/SOSTestDataSource.c +++ b/OSX/sec/SOSCircle/Regressions/SOSTestDataSource.c @@ -343,7 +343,6 @@ SOSDataSourceRef SOSTestDataSourceCreate(void) { ds->ds.dsRestoreObject = dsRestoreObject; ds->ds.objectCopyDigest = copyDigest; - ds->ds.objectCopyPrimaryKey = copyPrimaryKey; ds->ds.objectCreateWithPropertyList = createWithPropertyList; ds->ds.objectCopyPropertyList = copyPropertyList; ds->ds.objectCopyBackup = objectCopyBackup; diff --git a/OSX/sec/SOSCircle/Regressions/SOSTestDevice.c b/OSX/sec/SOSCircle/Regressions/SOSTestDevice.c index 1ff76686..91375914 100644 --- a/OSX/sec/SOSCircle/Regressions/SOSTestDevice.c +++ b/OSX/sec/SOSCircle/Regressions/SOSTestDevice.c @@ -75,7 +75,9 @@ void SOSTestDeviceDestroyEngine(CFMutableDictionaryRef testDevices) { CFArrayForEach(deviceIDs, ^(const void *value) { CFStringRef sourceID = (CFStringRef)value; SOSTestDeviceRef source = (SOSTestDeviceRef)CFDictionaryGetValue(testDevices, sourceID); - SOSEngineClearCache(SOSDataSourceGetSharedEngine(source->ds, NULL)); + SOSEngineRef engine = SOSDataSourceGetSharedEngine(source->ds, NULL); + SOSEngineClearCache(engine); + SOSEngineDispose(engine); }); } diff --git a/OSX/sec/SOSCircle/Regressions/sc-130-resignationticket.c b/OSX/sec/SOSCircle/Regressions/sc-130-resignationticket.c index 006873d1..78222216 100644 --- a/OSX/sec/SOSCircle/Regressions/sc-130-resignationticket.c +++ b/OSX/sec/SOSCircle/Regressions/sc-130-resignationticket.c @@ -65,12 +65,6 @@ static inline bool retire_me(piStuff *pi, size_t seconds) { return SOSPeerInfoRetireRetirementTicket(seconds, pi->resignation_ticket); } -// Copied from SOSPeerInfo.c -static CFStringRef sFlatticket = CFSTR("flatticket"); -static CFStringRef sSignature = CFSTR("RetirementPsig"); -static CFStringRef sPeerid = CFSTR("peerid"); - - static inline bool chkBasicTicket(piStuff *pi) { return CFEqual(SOSPeerInfoInspectRetirementTicket(pi->resignation_ticket, NULL), SOSPeerInfoGetPeerID(pi->pi)); } diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.c index b04bb7ac..5edbc568 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.c @@ -35,7 +35,6 @@ const CFStringRef kSOSDSIDKey = CFSTR("AccountDSID"); const CFStringRef kSOSEscrowRecord = CFSTR("EscrowRecord"); const CFStringRef kSOSUnsyncedViewsKey = CFSTR("unsynced"); - #define DATE_LENGTH 25 const CFStringRef kSOSAccountDebugScope = CFSTR("Scope"); @@ -86,7 +85,7 @@ SOSAccountRef SOSAccountCreateBasic(CFAllocatorRef allocator, a->user_private_timer = NULL; a->change_blocks = CFArrayCreateMutableForCFTypes(allocator); - + a->waitForInitialSync_blocks = CFDictionaryCreateMutableForCFTypes(allocator); a->departure_code = kSOSNeverAppliedToCircle; a->key_transport = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(a, NULL); @@ -347,6 +346,7 @@ static void SOSAccountDestroy(CFTypeRef aObj) { dispatch_release(a->user_private_timer); CFReleaseNull(a->change_blocks); + CFReleaseNull(a->waitForInitialSync_blocks); CFReleaseNull(a->expansion); }); @@ -583,10 +583,6 @@ static bool SOSAccountIsThisPeerIDMe(SOSAccountRef account, CFStringRef peerID) return myPeerID && CFEqualSafe(myPeerID, peerID); } -static bool isDefaultsWriteSetupToSyncOverIDS(){ - return ((whichTransportType == kSOSTransportIDS || whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportPresent)); -} - bool SOSAccountSyncWithAllPeers(SOSAccountRef account, CFErrorRef *error) { bool result = true; @@ -603,13 +599,17 @@ bool SOSAccountSyncWithAllPeers(SOSAccountRef account, CFErrorRef *error) SOSCircleForEachValidPeer(circle, account->user_public, ^(SOSPeerInfoRef peer) { if (!SOSAccountIsThisPeerIDMe(account, SOSPeerInfoGetPeerID(peer))) { - if (isDefaultsWriteSetupToSyncOverIDS() && SOSPeerInfoShouldUseIDSTransport(SOSFullPeerInfoGetPeerInfo(account->my_identity), peer)) { + if (SOSPeerInfoShouldUseIDSTransport(SOSFullPeerInfoGetPeerInfo(account->my_identity), peer)) { secdebug("IDS Transport", "Syncing with IDS capable peers using IDS!"); CFMutableDictionaryRef circleToIdsId = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); CFMutableArrayRef ids = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); CFArrayAppendValue(ids, SOSPeerInfoGetPeerID(peer)); CFDictionaryAddValue(circleToIdsId, SOSCircleGetName(circle), ids); SyncingCompletedOverIDS = SOSTransportMessageSyncWithPeers(account->ids_message_transport, circleToIdsId, &localError); + if(!SyncingCompletedOverIDS){ + secerror("Failed to sync over IDS, falling back to KVS"); + SyncingCompletedOverIDS = SOSTransportMessageSyncWithPeers(account->kvs_message_transport, circleToIdsId, &localError); + } CFReleaseNull(circleToIdsId); } else { CFArrayAppendValue(peerIds, SOSPeerInfoGetPeerID(peer)); @@ -636,6 +636,11 @@ xit: if (!result) { secdebug("Account", "Could not sync with all peers: %@", localError); + // Tell account to update SOSEngine with current trusted peers + if (isSOSErrorCoded(localError, kSOSErrorPeerNotFound)) { + secnotice("Account", "Arming account to update SOSEngine with current trusted peers"); + account->circle_rings_retirements_need_attention = true; + } CFErrorPropagate(localError, error); localError = NULL; } @@ -1074,7 +1079,55 @@ bool SOSAccountResetToEmpty(SOSAccountRef account, CFErrorRef* error) { return result; } +// +// MARK: start backups +// +bool SOSAccountEnsureBackupStarts(SOSAccountRef account) { + + __block bool result = false; + __block CFErrorRef error = NULL; + secnotice("backup", "Starting new backups"); + + CFDataRef backupKey = SOSPeerInfoV2DictionaryCopyData(SOSAccountGetMyPeerInfo(account), sBackupKeyKey); + + if (CFEqualSafe(backupKey, account->backup_key)){ + CFReleaseNull(backupKey); + return true; + } + + if(account->backup_key != NULL){ + require_quiet(SOSBSKBIsGoodBackupPublic(account->backup_key, &error), exit); + require_quiet(SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), &error, + ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) { + return SOSFullPeerInfoUpdateBackupKey(fpi, account->backup_key, error); + }), exit); + CFErrorRef localError = NULL; + if (!SOSDeleteV0Keybag(&localError)) { + secerror("Failed to delete v0 keybag: %@", localError); + } + CFReleaseNull(localError); + + result = true; + + SOSAccountForEachBackupView(account, ^(const void *value) { + CFStringRef viewName = (CFStringRef)value; + result &= SOSAccountStartNewBackup(account, viewName, &error); + }); + } + else{ + if(account->backup_key == NULL){ + secerror("account backup key is NULL!"); + } + } + +exit: + if (!result) { + secnotice("backupkey", "Failed to setup backup public key: %@", error ? (CFTypeRef) error : (CFTypeRef) CFSTR("No error space provided")); + } + CFReleaseNull(backupKey); + return result; +} // // MARK: Waiting for in-sync @@ -1132,8 +1185,13 @@ static bool SOSAccountUpdateOutOfSyncViews(SOSAccountRef account, CFSetRef views CFSetRef waiting = (CFMutableSetRef) unsyncedObject; CFSetRef newViews = CFSetCreateIntersection(kCFAllocatorDefault, waiting, viewsToSync); if (!CFEqualSafe(waiting, newViews)) { - secnotice("initial-sync", "Pending views updated: %@", newViews); - SOSAccountSetValue(account, kSOSUnsyncedViewsKey, newViews, NULL); + if (CFSetGetCount(newViews) == 0) { + secnotice("initial-sync", "No views left to wait for."); + SOSAccountClearValue(account, kSOSUnsyncedViewsKey, NULL); + } else { + secnotice("initial-sync", "Pending views updated: %@", newViews); + SOSAccountSetValue(account, kSOSUnsyncedViewsKey, newViews, NULL); + } notifyOfChange = true; } CFReleaseNull(newViews); @@ -1143,12 +1201,22 @@ static bool SOSAccountUpdateOutOfSyncViews(SOSAccountRef account, CFSetRef views } if (notifyOfChange) { - secnotice("initial-sync-notify", "In sync: Posting: %s", kSOSCCInitialSyncChangedNotification); - notify_post(kSOSCCInitialSyncChangedNotification); + if(SOSAccountGetValue(account, kSOSUnsyncedViewsKey, NULL) == NULL){ + CFDictionaryRef syncBlocks = account->waitForInitialSync_blocks; + account->waitForInitialSync_blocks = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + CFDictionaryForEach(syncBlocks, ^(const void *key, const void *value) { + secnotice("updates", "calling in sync block [%@]", key); + ((SOSAccountWaitForInitialSyncBlock)value)(account); + }); + + CFReleaseNull(syncBlocks); + } + // Make sure we update the engine account->circle_rings_retirements_need_attention = true; } - + return SOSAccountHasBeenInSync(account); } @@ -1246,6 +1314,7 @@ bool SOSAccountCheckHasBeenInSync(SOSAccountRef account) { hasBeenInSync = SOSAccountUpdateOutOfSyncViews(account, NULL); if (hasBeenInSync) { // Cancel and declare victory + SOSAccountCancelSyncChecking(account); } else { // Make sure we're watching in case this is the fist attempt @@ -1532,12 +1601,13 @@ bool SOSAccountRemovePeersFromCircle(SOSAccountRef account, CFArrayRef peers, CF result &= SOSAccountModifyCircle(account, error, ^(SOSCircleRef circle) { bool success = false; - require_quiet(SOSCircleRemovePeers(circle, user_key, SOSAccountGetMyFullPeerInfo(account), peersToRemove, error), done); + if(CFSetGetCount(peersToRemove) != 0) { + require_quiet(SOSCircleRemovePeers(circle, user_key, SOSAccountGetMyFullPeerInfo(account), peersToRemove, error), done); + success = SOSAccountGenerationSignatureUpdate(account, error); + } else success = true; - if (leaveCircle) { + if (success && leaveCircle) { success = sosAccountLeaveCircle(account, circle, error); - } else { - success = SOSAccountGenerationSignatureUpdate(account, error); } done: @@ -1706,9 +1776,8 @@ bool SOSAccountEnsurePeerRegistration(SOSAccountRef account, CFErrorRef *error) }); //Initialize our device ID - if(whichTransportType == kSOSTransportIDS || whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportPresent){ - SOSTransportMessageIDSGetIDSDeviceID(account); - } + SOSTransportMessageIDSGetIDSDeviceID(account); + done: return result; @@ -1825,7 +1894,7 @@ bool SOSAccountCheckPeerAvailability(SOSAccountRef account, CFErrorRef *error) CFReleaseNull(intersectSets); } }); - + require_quiet(CFDictionaryGetCount(peerList) > 0 , fail); CFDictionaryAddValue(circleToPeerMessages, SOSCircleGetName(account->trusted_circle), peerList); result = SOSTransportMessageSendMessages(account->ids_message_transport, circleToPeerMessages, error); @@ -1872,10 +1941,10 @@ void SOSAccountFinishTransaction(SOSAccountRef account) { secerror("flush circle failed %@", localError); } CFReleaseSafe(localError); - + SOSAccountNotifyEngines(account); // For now our only rings are backup rings. } - + SOSAccountCheckHasBeenInSync(account); account->circle_rings_retirements_need_attention = false; diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.h index 97698c4c..2028f7fe 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.h @@ -58,6 +58,7 @@ typedef void (^SOSAccountCircleMembershipChangeBlock)(SOSCircleRef new_circle, CFSetRef added_peers, CFSetRef removed_peers, CFSetRef added_applicants, CFSetRef removed_applicants); typedef void (^SOSAccountSyncablePeersBlock)(CFArrayRef trustedPeers, CFArrayRef addedPeers, CFArrayRef removedPeers); +typedef bool (^SOSAccountWaitForInitialSyncBlock)(SOSAccountRef account); SOSAccountRef SOSAccountCreate(CFAllocatorRef allocator, CFDictionaryRef gestalt, @@ -223,6 +224,8 @@ bool SOSAccountSetBackupPublicKey(SOSAccountRef account, CFDataRef backupKey, CF bool SOSAccountRemoveBackupPublickey(SOSAccountRef account, CFErrorRef *error); bool SOSAccountSetBSKBagForAllSlices(SOSAccountRef account, CFDataRef backupSlice, bool setupV0Only, CFErrorRef *error); +SOSBackupSliceKeyBagRef SOSAccountBackupSliceKeyBagForView(SOSAccountRef account, CFStringRef viewName, CFErrorRef* error); + // // MARK: Private functions // diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountBackup.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountBackup.c index 3cfabdc6..c8b24a2c 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountBackup.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountBackup.c @@ -42,7 +42,7 @@ static CFDictionaryRef SOSCopyV0Attributes() { NULL); } -static bool SOSDeleteV0Keybag(CFErrorRef *error) { +bool SOSDeleteV0Keybag(CFErrorRef *error) { CFDictionaryRef attributes = SOSCopyV0Attributes(); OSStatus result = SecItemDelete(attributes); @@ -236,7 +236,7 @@ bool SOSAccountIsBackupRingEmpty(SOSAccountRef account, CFStringRef viewName) { return peercnt == 0; } -static bool SOSAccountUpdatePeerInfo(SOSAccountRef account, CFStringRef updateDescription, CFErrorRef *error, bool (^update)(SOSFullPeerInfoRef fpi, CFErrorRef *error)) { +bool SOSAccountUpdatePeerInfo(SOSAccountRef account, CFStringRef updateDescription, CFErrorRef *error, bool (^update)(SOSFullPeerInfoRef fpi, CFErrorRef *error)) { if (account->my_identity == NULL) return true; @@ -377,7 +377,6 @@ void SOSAccountForEachBackupRingName(SOSAccountRef account, void (^operation)(CF } } -static void SOSAccountForEachBackupView(SOSAccountRef account, void (^operation)(const void *value)) { SOSPeerInfoRef myPeer = SOSAccountGetMyPeerInfo(account); @@ -396,32 +395,18 @@ bool SOSAccountSetBackupPublicKey(SOSAccountRef account, CFDataRef backupKey, CF { __block bool result = false; + secnotice("backup", "setting backup public key"); require_quiet(SOSAccountIsInCircle(account, error), exit); if (CFEqualSafe(backupKey, account->backup_key)) return true; - require_quiet(SOSBSKBIsGoodBackupPublic(backupKey, error), exit); - require_quiet(SOSAccountUpdatePeerInfo(account, CFSTR("Backup public key"), error, - ^bool(SOSFullPeerInfoRef fpi, CFErrorRef *error) { - return SOSFullPeerInfoUpdateBackupKey(fpi, backupKey, error); - }), exit); - CFRetainAssign(account->backup_key, backupKey); - CFErrorRef localError = NULL; - if (!SOSDeleteV0Keybag(&localError)) { - secerror("Failed to delete v0 keybag: %@", localError); - } - CFReleaseNull(localError); - + SOSAccountEnsureBackupStarts(account); + result = true; - SOSAccountForEachBackupView(account, ^(const void *value) { - CFStringRef viewName = (CFStringRef)value; - result &= SOSAccountStartNewBackup(account, viewName, error); - }); - exit: if (!result) { secnotice("backupkey", "Failed to setup backup public key: %@", error ? (CFTypeRef) *error : (CFTypeRef) CFSTR("No error space provided")); @@ -566,3 +551,30 @@ bool SOSAccountRemoveBackupPeers(SOSAccountRef account, CFArrayRef peers, CFErro } +SOSBackupSliceKeyBagRef SOSAccountBackupSliceKeyBagForView(SOSAccountRef account, CFStringRef viewName, CFErrorRef* error){ + CFMutableDictionaryRef trusted_rings = NULL; + CFDataRef backupSliceData = NULL; + CFStringRef ringName = NULL; + SOSRingRef ring = NULL; + SOSBackupSliceKeyBagRef bskb = NULL; + + trusted_rings = SOSAccountGetRings(account, error); + require_action_quiet(trusted_rings, exit, secnotice("keybag", "failed to get trusted rings (%@)", *error)); + + ringName = SOSBackupCopyRingNameForView(viewName); + + ring = (SOSRingRef)CFDictionaryGetValue(trusted_rings, ringName); + require_action_quiet(ring, exit, SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("failed to get ring"))); + + //grab the backup slice from the ring + backupSliceData = SOSRingGetPayload(ring, error); + require_action_quiet(backupSliceData, exit, secnotice("backup", "failed to get backup slice (%@)", *error)); + + bskb = SOSBackupSliceKeyBagCreateFromData(kCFAllocatorDefault, backupSliceData, error); + +exit: + CFReleaseNull(ringName); + + return bskb; +} + diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c index 3b232f3d..c7293fe2 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c @@ -156,6 +156,77 @@ CFArrayRef SOSAccountCopyPeers(SOSAccountRef account, CFErrorRef *error) { }); } +CFDataRef SOSAccountCopyAccountStateFromKeychain(CFErrorRef *error){ + CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFTypeRef result = NULL; + CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); + CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dku")); + CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); + CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue); + + SecItemCopyMatching(query, &result); + + if(!isData(result)){ + SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result); + CFReleaseNull(result); + return NULL; + } + return result; +} + +bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef *error){ + CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + bool result = false; + CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); + CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dku")); + CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); + + result = SecItemDelete(query); + return result; +} + +CFDataRef SOSAccountCopyEngineStateFromKeychain(CFErrorRef *error){ + CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + CFTypeRef result = NULL; + CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("engine-state")); + CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); + CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dk")); + CFDictionaryAddValue(query, kSecAttrService, CFSTR("SOSDataSource-ak")); + CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); + CFDictionaryAddValue(query, kSecReturnData, kCFBooleanTrue); + + SecItemCopyMatching(query, &result); + + if(!isData(result)){ + SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result); + CFReleaseNull(result); + return NULL; + } + return result; +} + +bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef *error){ + CFMutableDictionaryRef query = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + bool result = false; + CFDictionaryAddValue(query, kSecClass, kSecClassGenericPassword); + CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("engine-state")); + CFDictionaryAddValue(query, kSecAttrAccessGroup, CFSTR("com.apple.security.sos")); + CFDictionaryAddValue(query, kSecAttrAccessible, CFSTR("dk")); + CFDictionaryAddValue(query, kSecAttrService, CFSTR("SOSDataSource-ak")); + CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanFalse); + CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanFalse); + + result = SecItemDelete(query); + return result; +} + + CFArrayRef SOSAccountCopyActivePeers(SOSAccountRef account, CFErrorRef *error) { return SOSAccountCopySortedPeerArray(account, error, ^(SOSCircleRef circle, CFMutableArrayRef appendPeersTo) { SOSCircleForEachActivePeer(circle, ^(SOSPeerInfoRef peer) { diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c index b76a40aa..037656b8 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c @@ -323,9 +323,9 @@ SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator, SOSAccountUpdateFullPeerInfo(account, viewsToEnsure, SOSViewsGetV0ViewSet()); // We don't permit V0 view proper, only sub-views CFReleaseNull(viewsToEnsure); } - + SOSAccountCheckHasBeenInSync(account); - + SOSUpdateKeyInterest(account); result = CFRetainSafe(account); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h index 9b901c2f..a405b064 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h @@ -87,6 +87,7 @@ struct __OpaqueSOSAccount { // Live Notification CFMutableArrayRef change_blocks; + CFMutableDictionaryRef waitForInitialSync_blocks; }; extern const CFStringRef kSOSEscrowRecord; @@ -181,6 +182,9 @@ CFStringRef SOSAccountGetMyPeerID(SOSAccountRef a); bool SOSAccountIsMyPeerInBackupAndCurrentInView(SOSAccountRef account, CFStringRef viewname); bool SOSAccountUpdateOurPeerInBackup(SOSAccountRef account, SOSRingRef oldRing, CFErrorRef *error); bool SOSAccountIsPeerInBackupAndCurrentInView(SOSAccountRef account, SOSPeerInfoRef testPeer, CFStringRef viewname); +bool SOSDeleteV0Keybag(CFErrorRef *error); +void SOSAccountForEachBackupView(SOSAccountRef account, void (^operation)(const void *value)); +bool SOSAccountUpdatePeerInfo(SOSAccountRef account, CFStringRef updateDescription, CFErrorRef *error, bool (^update)(SOSFullPeerInfoRef fpi, CFErrorRef *error)); // Currently permitted backup rings. void SOSAccountForEachBackupRingName(SOSAccountRef account, void (^operation)(CFStringRef value)); @@ -272,6 +276,7 @@ bool sosAccountLeaveRing(SOSAccountRef account, SOSRingRef ring, CFErrorRef* err CFMutableDictionaryRef SOSAccountGetRings(SOSAccountRef a, CFErrorRef *error); CFMutableDictionaryRef SOSAccountGetBackups(SOSAccountRef a, CFErrorRef *error); bool SOSAccountUpdateBackUp(SOSAccountRef account, CFStringRef viewname, CFErrorRef *error); +bool SOSAccountEnsureBackupStarts(SOSAccountRef account); bool SOSAccountEnsurePeerRegistration(SOSAccountRef account, CFErrorRef *error); @@ -283,6 +288,7 @@ extern const CFStringRef SOSTransportMessageTypeKVS; extern const CFStringRef kSOSUnsyncedViewsKey; typedef enum{ + kSOSTransportNone = 0, kSOSTransportIDS = 1, kSOSTransportKVS = 2, kSOSTransportFuture = 3, @@ -320,4 +326,14 @@ bool SOSAccountCheckPeerAvailability(SOSAccountRef account, CFErrorRef *error); CFStringRef SOSBackupCopyRingNameForView(CFStringRef viewName); +// +// Security tool test/debug functions +// + +CFDataRef SOSAccountCopyAccountStateFromKeychain(CFErrorRef *error); +bool SOSAccountDeleteAccountStateFromKeychain(CFErrorRef *error); +CFDataRef SOSAccountCopyEngineStateFromKeychain(CFErrorRef *error); +bool SOSAccountDeleteEngineStateFromKeychain(CFErrorRef *error); + + #endif diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.c index a6a006c9..d3159b9f 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.c @@ -121,6 +121,9 @@ fail: size_t der_sizeof_BackupSliceKeyBag(SOSBackupSliceKeyBagRef BackupSliceKeyBag, CFErrorRef *error) { size_t result = 0; + require_quiet(SecRequirementError(BackupSliceKeyBag != NULL, error, CFSTR("Null BackupSliceKeyBag")), fail); + require_quiet(SecRequirementError(BackupSliceKeyBag->aks_bag != NULL, error, CFSTR("null aks_bag in BackupSliceKeyBag")), fail); + size_t bag_size = der_sizeof_data(BackupSliceKeyBag->aks_bag, error); require_quiet(bag_size, fail); @@ -352,6 +355,40 @@ CFSetRef SOSBSKBGetPeers(SOSBackupSliceKeyBagRef backupSliceKeyBag){ return backupSliceKeyBag->peers; } +bskb_keybag_handle_t SOSBSKBLoadLocked(SOSBackupSliceKeyBagRef backupSliceKeyBag, + CFErrorRef *error) +{ +#if !TARGET_HAS_KEYSTORE + return bad_keybag_handle; +#else + keybag_handle_t result = bad_keybag_handle; + keybag_handle_t bag_handle = bad_keybag_handle; + + require_quiet(SecRequirementError(backupSliceKeyBag->aks_bag, error, + CFSTR("No aks bag to load")), exit); + require_quiet(SecRequirementError(CFDataGetLength(backupSliceKeyBag->aks_bag) < INT_MAX, error, + CFSTR("No aks bag to load")), exit); + + kern_return_t aks_result; + aks_result = aks_load_bag(CFDataGetBytePtr(backupSliceKeyBag->aks_bag), + (int) CFDataGetLength(backupSliceKeyBag->aks_bag), + &bag_handle); + require_quiet(SecKernError(aks_result, error, + CFSTR("aks_load_bag failed: %d"), aks_result), exit); + + result = bag_handle; + bag_handle = bad_keybag_handle; + +exit: + if (bag_handle != bad_keybag_handle) { + (void) aks_unload_bag(bag_handle); + } + + return result; +#endif + +} + static keybag_handle_t SOSBSKBLoadAndUnlockBagWithSecret(SOSBackupSliceKeyBagRef backupSliceKeyBag, size_t secretSize, const uint8_t *secret, CFErrorRef *error) diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.h index bfdd0378..8a361143 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.h @@ -65,6 +65,9 @@ size_t der_sizeof_BackupSliceKeyBag(SOSBackupSliceKeyBagRef BackupSliceKeyBag, C uint8_t* der_encode_BackupSliceKeyBag(SOSBackupSliceKeyBagRef BackupSliceKeyBag, CFErrorRef *error, const uint8_t *der, uint8_t *der_end); +bskb_keybag_handle_t SOSBSKBLoadLocked(SOSBackupSliceKeyBagRef backupSliceKeyBag, + CFErrorRef *error); + bskb_keybag_handle_t SOSBSKBLoadAndUnlockWithPeerIDAndSecret(SOSBackupSliceKeyBagRef backupSliceKeyBag, CFStringRef peerID, CFDataRef peerSecret, CFErrorRef *error); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSCircle.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSCircle.c index 152f232b..9d86a5f1 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSCircle.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSCircle.c @@ -470,10 +470,6 @@ static inline bool SOSCircleIsEmpty(SOSCircleRef circle) { return SOSCircleCountPeers(circle) == 0; } -static inline bool SOSCircleIsOffering(SOSCircleRef circle) { - return SOSCircleCountPeers(circle) == 1; -} - static inline bool SOSCircleHasDegenerateGeneration(SOSCircleRef deGenCircle){ int testPtr; CFNumberRef genCountTest = SOSCircleGetGeneration(deGenCircle); @@ -527,6 +523,15 @@ bool SOSCircleSharedTrustedPeers(SOSCircleRef current, SOSCircleRef proposed, SO return retval; } +static SOSConcordanceStatus GetOfferingStatus(SOSCircleRef circle, SecKeyRef user_pubKey, CFErrorRef *error) { + __block SOSConcordanceStatus status = kSOSConcordanceNoPeer; + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + status = CheckPeerStatus(circle, peer, user_pubKey, error); + if(status != kSOSConcordanceTrusted) status = kSOSConcordanceNoPeer; + }); + return status; +} + SOSConcordanceStatus SOSCircleConcordanceTrust(SOSCircleRef known_circle, SOSCircleRef proposed_circle, SecKeyRef known_pubkey, SecKeyRef user_pubkey, @@ -571,7 +576,7 @@ SOSConcordanceStatus SOSCircleConcordanceTrust(SOSCircleRef known_circle, SOSCir } if(SOSCircleIsOffering(proposed_circle)){ - return GetSignersStatus(proposed_circle, proposed_circle, user_pubkey, NULL, error); + return GetOfferingStatus(proposed_circle, user_pubkey, error); } return GetSignersStatus(known_circle, proposed_circle, user_pubkey, me, error); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSCirclePriv.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSCirclePriv.h index 8dd9e2b1..b673a2cf 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSCirclePriv.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSCirclePriv.h @@ -47,4 +47,9 @@ static inline SOSCircleRef SOSCircleConvertAndAssertStable(CFTypeRef circleAsTyp return circle; } + +static inline bool SOSCircleIsOffering(SOSCircleRef circle) { + return SOSCircleCountRetiredPeers(circle) == 0 && SOSCircleCountPeers(circle) == 1; +} + #endif diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c index 07d4cb39..701b5ad0 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c @@ -292,6 +292,28 @@ static SOSPeerInfoRef peer_info_error_request(enum SecXPCOperation op, CFErrorRe return result; } +static CFDataRef data_to_error_request(enum SecXPCOperation op, CFErrorRef *error) +{ + __block CFDataRef result = NULL; + + secdebug("sosops", "enter -- operation: %d", op); + secdebug("sosops","enter - operation: %d", op); + securityd_send_sync_and_do(op, error, NULL, ^bool(xpc_object_t response, CFErrorRef *error) { + xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCKeyResult); + if (response && (NULL != temp_result)) { + result = _CFXPCCreateCFObjectFromXPCObject(temp_result); + } + return result != NULL; + }); + + if (!isData(result)) { + SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), result); + return NULL; + } + + return result; +} + static CFArrayRef array_of_info_error_request(enum SecXPCOperation op, CFErrorRef* error) { __block CFArrayRef result = NULL; @@ -399,6 +421,46 @@ static bool uint64_t_to_bool_error_request(enum SecXPCOperation op, return result; } +static bool cfstring_and_cfdata_to_cfdata_cfdata_error_request(enum SecXPCOperation op, CFStringRef viewName, CFDataRef input, CFDataRef* data, CFDataRef* data2, CFErrorRef* error) { + secdebug("sosops", "enter - operation: %d", op); + __block bool result = false; + securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { + xpc_object_t xviewname = _CFXPCCreateXPCObjectFromCFObject(viewName); + xpc_object_t xinput = _CFXPCCreateXPCObjectFromCFObject(input); + bool success = false; + if (xviewname && xinput){ + xpc_dictionary_set_value(message, kSecXPCKeyViewName, xviewname); + xpc_dictionary_set_value(message, kSecXPCData, xinput); + success = true; + xpc_release(xviewname); + xpc_release(xinput); + } + return success; + }, ^bool(xpc_object_t response, __unused CFErrorRef *error) { + result = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + + xpc_object_t temp_result = xpc_dictionary_get_value(response, kSecXPCData); + if (response && (NULL != temp_result) && data) { + *data = _CFXPCCreateCFObjectFromXPCObject(temp_result); + } + temp_result = xpc_dictionary_get_value(response, kSecXPCKeyKeybag); + if (response && (NULL != temp_result) && data2) { + *data2 = _CFXPCCreateCFObjectFromXPCObject(temp_result); + } + + return result; + }); + + if (data &&!isData(*data)) { + SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), *data); + } + if (data2 &&!isData(*data2)) { + SOSErrorCreate(kSOSErrorUnexpectedType, error, NULL, CFSTR("Expected CFData, got: %@"), *data2); + } + + return result; +} + static bool set_hsa2_autoaccept_error_request(enum SecXPCOperation op, CFDataRef pubKey, CFErrorRef *error) { __block bool result = false; @@ -705,6 +767,43 @@ CFArrayRef SOSCCCopyViewUnawarePeerInfo(CFErrorRef* error) }, CFSTR("return=%@")); } +CFDataRef SOSCCCopyAccountState(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFDataRef, ^{ + do_if_registered(soscc_CopyAccountState, error); + + return data_to_error_request(kSecXPCOpCopyAccountData, error); + }, CFSTR("return=%@")); +} + +bool SOSCCDeleteAccountState(CFErrorRef *error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(bool, ^{ + do_if_registered(soscc_DeleteAccountState, error); + return simple_bool_error_request(kSecXPCOpDeleteAccountData, error); + }, NULL); +} +CFDataRef SOSCCCopyEngineData(CFErrorRef* error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(CFDataRef, ^{ + do_if_registered(soscc_CopyEngineData, error); + + return data_to_error_request(kSecXPCOpCopyEngineData, error); + }, CFSTR("return=%@")); +} + +bool SOSCCDeleteEngineState(CFErrorRef *error) +{ + sec_trace_enter_api(NULL); + sec_trace_return_api(bool, ^{ + do_if_registered(soscc_DeleteEngineState, error); + return simple_bool_error_request(kSecXPCOpDeleteEngineData, error); + }, NULL); +} + SOSPeerInfoRef SOSCCCopyMyPeerInfo(CFErrorRef *error) { sec_trace_enter_api(NULL); @@ -1242,3 +1341,11 @@ bool SOSCCCheckPeerAvailability(CFErrorRef *error){ } +bool SOSWrapToBackupSliceKeyBagForView(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error) { + sec_trace_enter_api(NULL); + sec_trace_return_bool_api(^{ + do_if_registered(sosbskb_WrapToBackupSliceKeyBagForView, viewName, input, output, bskbEncoded, error); + + return cfstring_and_cfdata_to_cfdata_cfdata_error_request(kSecXPCOpWrapToBackupSliceKeyBagForView, viewName, input, output, bskbEncoded, error); + }, NULL) +} diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h index 46c7a578..3ce34a30 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h @@ -54,6 +54,7 @@ enum { kSOSErrorNotReady = 4, // System not yet ready (before first unlock) kSOSErrorIncompatibleCircle = 5, // We saw an incompatible circle out there. + kSOSInitialSyncFailed =6, //we timed out when syncing during approving from another device }; // diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h index 2c467edb..4deffc24 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h @@ -116,6 +116,27 @@ bool SOSCCIDSPingTest(CFStringRef message, CFErrorRef *error); */ bool SOSCCIDSDeviceIDIsAvailableTest(CFErrorRef *error); +/*! + @function SOSWrapToBackupSliceKeyBagForView + @abstract Encrypts the given plaintext, and wraps the encryption key to the backup slice keybag for this view + @param viewName The view to wrap to + @param input The plaintext to encrypt + @param output The ciphertext + @param bskbEncoded The encoded backup slice keybag used to wrap the data + @param error What went wrong if we returned false + */ +bool SOSWrapToBackupSliceKeyBagForView(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error); + +// +// Security Tool calls +// +CFDataRef SOSCCCopyAccountState(CFErrorRef* error); +bool SOSCCDeleteAccountState(CFErrorRef *error); +CFDataRef SOSCCCopyEngineData(CFErrorRef* error); +bool SOSCCDeleteEngineState(CFErrorRef *error); + +char *SOSCCSysdiagnose(const char *directoryname); + __END_DECLS #endif diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c index 1e6317bf..6d8ff2d5 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c @@ -336,7 +336,7 @@ void SOSCoderReset(SOSCoderRef coder) CFDataRef SOSCoderCopyPendingResponse(SOSCoderRef coder) { - return CFRetainSafe(coder->pendingResponse); + return coder->pendingResponse ? CFDataCreateCopy(kCFAllocatorDefault, coder->pendingResponse) : NULL; } void SOSCoderConsumeResponse(SOSCoderRef coder) @@ -466,9 +466,8 @@ SOSCoderStatus SOSCoderUnwrap(SOSCoderRef coder, CFDataRef codedMessage, CFMutab case kOTRDataPacket: if(!SecOTRSGetIsReadyForMessages(coder->sessRef)) { - CFStringAppend(action, CFSTR("not ready, resending DH packet")); + CFStringAppend(action, CFSTR("not ready for data; resending DH packet")); SetCloudKeychainTraceValueForKey(kCloudKeychainNumberOfTimesSyncFailed, 1); - CFStringAppend(action, CFSTR("not ready for data; resending dh")); result = SOSCoderResendDH(coder, error); } else { if (coder->waitingForDataPacket) { diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSDataSource.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSDataSource.h index 93fdf220..d7792daa 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSDataSource.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSDataSource.h @@ -143,7 +143,6 @@ struct SOSDataSource { // SOSObject methods CFDataRef (*objectCopyDigest)(SOSObjectRef object, CFErrorRef *error); - CFDataRef (*objectCopyPrimaryKey)(SOSObjectRef object, CFErrorRef *error); SOSObjectRef (*objectCreateWithPropertyList)(CFDictionaryRef plist, CFErrorRef *error); CFDictionaryRef (*objectCopyPropertyList)(SOSObjectRef object, CFErrorRef *error); CFDictionaryRef (*objectCopyBackup)(SOSObjectRef object, uint64_t handle, CFErrorRef *error); @@ -216,10 +215,6 @@ static inline CFDataRef SOSObjectCopyDigest(SOSDataSourceRef ds, SOSObjectRef ob return ds->objectCopyDigest(object, error); } -static inline CFDataRef SOSObjectCopyPrimaryKey(SOSDataSourceRef ds, SOSObjectRef object, CFErrorRef *error) { - return ds->objectCopyPrimaryKey(object, error); -} - static inline SOSObjectRef SOSObjectCreateWithPropertyList(SOSDataSourceRef ds, CFDictionaryRef plist, CFErrorRef *error) { return ds->objectCreateWithPropertyList(plist, error); } diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c index 6ebdc0b0..2d2777ee 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c @@ -89,7 +89,6 @@ struct __OpaqueSOSEngine { CFDataRef localMinusUnreadableDigest; // or a digest (CFDataRef of the right size). CFMutableDictionaryRef manifestCache; // digest -> ( refcount, manifest ) - //CFMutableDictionaryRef peerState; // peerId -> mutable array of digests CFMutableDictionaryRef peerMap; // peerId -> SOSPeerRef CFDictionaryRef viewNameSet2ChangeTracker; // CFSetRef of CFStringRef -> SOSChangeTrackerRef CFDictionaryRef viewName2ChangeTracker; // CFStringRef -> SOSChangeTrackerRef @@ -211,6 +210,7 @@ static SOSPeerRef SOSEngineCopyPeerWithID_locked(SOSEngineRef engine, CFStringRe peer = SOSEngineCopyPeerWithMapEntry_locked(engine, peerID, mapEntry, error); } else { peer = NULL; + secerror("peer: %@ not found, peerMap: %@, engine: %@", peerID, engine->peerMap, engine); SOSErrorCreate(kSOSErrorPeerNotFound, error, NULL, CFSTR("peer: %@ not found"), peerID); } return peer; @@ -432,21 +432,23 @@ static void SOSEngineShouldSave(SOSEngineRef engine) { } // Schedule the timer to fire on a concurrent queue, so we can follow - // the proper procedure of aquiring a dataSource and then engine queues. + // the proper procedure of acquiring a dataSource and then engine queues. engine->save_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)); dispatch_source_set_event_handler(engine->save_timer, ^{ CFErrorRef dsWithError = NULL; - if (!SOSDataSourceWith(engine->dataSource, &dsWithError, ^(SOSTransactionRef txn, bool *commit) { - dispatch_sync(engine->queue, ^{ - CFErrorRef saveError = NULL; - if (!SOSEngineDoSave(engine, txn, &saveError)) { - secerrorq("Failed to save engine state: %@", saveError); - CFReleaseNull(saveError); - } - }); - })) { - secerrorq("Failed to open dataSource to save engine state: %@", dsWithError); - CFReleaseNull(dsWithError); + if (engine->dataSource) { + if (!SOSDataSourceWith(engine->dataSource, &dsWithError, ^(SOSTransactionRef txn, bool *commit) { + dispatch_sync(engine->queue, ^{ + CFErrorRef saveError = NULL; + if (!SOSEngineDoSave(engine, txn, &saveError)) { + secerrorq("Failed to save engine state: %@", saveError); + CFReleaseNull(saveError); + } + }); + })) { + secerrorq("Failed to open dataSource to save engine state: %@", dsWithError); + CFReleaseNull(dsWithError); + } } xpc_transaction_end(); }); @@ -462,6 +464,9 @@ static void SOSEngineShouldSave(SOSEngineRef engine) { #endif static bool SOSEngineSave(SOSEngineRef engine, SOSTransactionRef txn, CFErrorRef *error) { + // Don't save engine state from tests + if (!engine->dataSource) + return true; #if (TARGET_IPHONE_SIMULATOR) return SOSEngineDoSave(engine, txn, error); #else @@ -1056,7 +1061,7 @@ static void SOSEngineApplyPeerState(SOSEngineRef engine, CFDictionaryRef peerSta secerror("peer: %@: bad state: %@ in engine state: %@", peerID, localError, stateHex); CFReleaseSafe(stateHex); CFReleaseNull(localError); - // Possibly ask for an ensurePeerRegistration so we have a good list or peers again. + // Possibly ask for an ensurePeerRegistration so we have a good list of peers again. } } else { // Just record the state for non inflated peers for now. @@ -1214,8 +1219,6 @@ static bool SOSEngineLoad(SOSEngineRef engine, CFErrorRef *error) { return ok; } -static CFStringRef accountStatusFileName = CFSTR("accountStatus.plist"); - static bool SOSEngineCircleChanged_locked(SOSEngineRef engine, SOSPeerMetaRef myPeerMeta, CFArrayRef trustedPeers, CFArrayRef untrustedPeers) { // Sanity check params // SOSEngineCircleChanged_sanitycheck(engine, myPeerID, trustedPeers, untrustedPeers); @@ -1298,6 +1301,7 @@ static bool SOSEngineDoTxnOnQueue(SOSEngineRef engine, CFErrorRef *error, void(^ void SOSEngineDispose(SOSEngineRef engine) { // NOOP Engines stick around forever to monitor dataSource changes. + engine->dataSource = NULL; } void SOSEngineForEachPeer(SOSEngineRef engine, void (^with)(SOSPeerRef peer)) { @@ -1901,8 +1905,19 @@ CFDataRef SOSEngineCreateMessage_locked(SOSEngineRef engine, SOSPeerRef peer, CFReleaseNull(allExtra); } - if (!SOSMessageSetManifests(message, local, confirmed, proposed, proposed, confirmed ? objectsSent : NULL, error)) + SOSManifestRef sender = local; + // We actually send the remote peer its own digest. + // Note that both pendingObjects and unwanted may have been changed, so we get them again + if (SOSManifestGetCount(SOSPeerGetPendingObjects(peer))==0 && SOSManifestGetCount(extra)==0 && + SOSManifestGetCount(missing)==0 && SOSManifestGetCount(SOSPeerGetUnwantedManifest(peer))!=0) { + secnoticeq("engine", "%@:%@: only have differences in unwanted set; lying to peer to stop sync",engine->myID, SOSPeerGetID(peer)); + sender = confirmed; + } + + if (!SOSMessageSetManifests(message, sender, confirmed, proposed, proposed, confirmed ? objectsSent : NULL, error)) { + secnoticeq("engine", "%@:%@: failed to set message manifests",engine->myID, SOSPeerGetID(peer)); CFReleaseNull(message); + } CFReleaseNull(objectsSent); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.h index a3b3e507..a7e9b0ea 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.h @@ -70,10 +70,6 @@ CFMutableArrayRef SOSEngineCopyPersistedManifestArray(SOSEngineRef engine, CFDic void SOSEngineClearCache(SOSEngineRef engine); -//Set/Get coders -bool SOSEngineSetCoderData(SOSEngineRef engine, CFStringRef peer_id, CFDataRef data, CFErrorRef *error); -CFDataRef SOSEngineGetCoderData(SOSEngineRef engine, CFStringRef peer_id); - // Dispose of an engine when it's no longer needed. void SOSEngineDispose(SOSEngineRef engine); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in b/OSX/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in index b05d28b8..5a146182 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in @@ -51,6 +51,7 @@ _SOSCCSetLastDepartureReason _SOSCCSetUserCredentials _SOSCCSetUserCredentialsAndDSID _SOSCCSignedOut +_SOSCCSysdiagnose _SOSCCThisDeviceIsInCircle _SOSCCTryUserCredentials _SOSCCValidateUserPublic @@ -66,6 +67,10 @@ _SOSCCWaitForInitialSync _SOSCCSetEscrowRecord _SOSCCCopyEscrowRecord _SOSCCCheckPeerAvailability +_SOSCCCopyAccountState +_SOSCCDeleteAccountState +_SOSCCCopyEngineData +_SOSCCDeleteEngineState _UserParametersDescription @@ -173,6 +178,7 @@ _SOSBSKBCopyEncoded _SOSBSKBIsDirect _SOSBSKBGetPeers +_SOSBSKBLoadLocked _SOSBSKBLoadAndUnlockWithDirectSecret _SOSBSKBLoadAndUnlockWithPeerSecret _SOSBackupSliceKeyBagCreate @@ -183,6 +189,8 @@ _der_decode_BackupSliceKeyBag _der_encode_BackupSliceKeyBag _der_sizeof_BackupSliceKeyBag +_SOSWrapToBackupSliceKeyBagForView + // // View SPI // @@ -243,6 +251,9 @@ _kSecAttrViewHintAppleTV _kSecAttrViewHintHomeKit _kSecAttrViewHintThumper +_kSecUseSystemKeychain +_kSecUseSyncBubbleKeychain + // // Exported for testing/tools (?) // diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c index 40a1b7db..6abe081e 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c @@ -84,8 +84,6 @@ struct __OpaqueSOSFullPeerInfo { CFGiblisWithHashFor(SOSFullPeerInfo); -static CFStringRef sPublicKeyKey = CFSTR("PublicSigningKey"); - CFStringRef kSOSFullPeerInfoDescriptionKey = CFSTR("SOSFullPeerInfoDescription"); CFStringRef kSOSFullPeerInfoSignatureKey = CFSTR("SOSFullPeerInfoSignature"); CFStringRef kSOSFullPeerInfoNameKey = CFSTR("SOSFullPeerInfoName"); @@ -130,11 +128,18 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateWithViews(CFAllocatorRef allocator, SOSFullPeerInfoRef result = NULL; SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator); - bool useIDS = whichTransportType == kSOSTransportIDS || whichTransportType == kSOSTransportFuture; - - CFStringRef transportType = useIDS ? SOSTransportMessageTypeIDS : SOSTransportMessageTypeKVS; - CFBooleanRef preferIDS = useIDS ? kCFBooleanTrue : kCFBooleanFalse; + CFStringRef transportType = NULL; + CFBooleanRef preferIDS = NULL; CFStringRef IDSID = CFSTR(""); + + if (whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportIDS){ + transportType =SOSTransportMessageTypeIDS; + preferIDS = kCFBooleanTrue; + } + else{ + transportType =SOSTransportMessageTypeKVS; + preferIDS = kCFBooleanTrue; + } fpi->peer_info = SOSPeerInfoCreateWithTransportAndViews(allocator, gestalt, backupKey, IDSID, transportType, preferIDS, @@ -152,6 +157,23 @@ exit: return result; } +SOSFullPeerInfoRef SOSFullPeerInfoCopyFullPeerInfo(SOSFullPeerInfoRef toCopy) { + SOSFullPeerInfoRef retval = NULL; + SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, kCFAllocatorDefault); + SOSPeerInfoRef piToCopy = SOSFullPeerInfoGetPeerInfo(toCopy); + + require_quiet(piToCopy, errOut); + require_quiet(fpi, errOut); + fpi->peer_info = SOSPeerInfoCreateCopy(kCFAllocatorDefault, piToCopy, NULL); + require_quiet(fpi->peer_info, errOut); + fpi->key_ref = toCopy->key_ref; + CFTransferRetained(retval, fpi); + +errOut: + CFReleaseNull(fpi); + return retval; +} + bool SOSFullPeerInfoUpdateTransportType(SOSFullPeerInfoRef peer, CFStringRef transportType, CFErrorRef* error) { return SOSFullPeerInfoUpdate(peer, error, ^SOSPeerInfoRef(SOSPeerInfoRef peer, SecKeyRef key, CFErrorRef *error) { diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h index d647fb99..6df8afb7 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h @@ -47,6 +47,8 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateWithViews(CFAllocatorRef allocator, CFDictionaryRef gestalt, CFDataRef backupKey, CFSetRef enabledViews, SecKeyRef signingKey, CFErrorRef *error); +SOSFullPeerInfoRef SOSFullPeerInfoCopyFullPeerInfo(SOSFullPeerInfoRef toCopy); + SOSFullPeerInfoRef SOSFullPeerInfoCreateCloudIdentity(CFAllocatorRef allocator, SOSPeerInfoRef peer, CFErrorRef* error); SOSPeerInfoRef SOSFullPeerInfoGetPeerInfo(SOSFullPeerInfoRef fullPeer); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSInternal.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSInternal.h index d74ef8d0..0cf11582 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSInternal.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSInternal.h @@ -83,7 +83,6 @@ bool SOSCreateErrorWithFormatAndArguments(CFIndex errorCode, CFErrorRef previous CFDictionaryRef formatOptions, CFStringRef formatString, va_list args) CF_FORMAT_FUNCTION(5,0); - static inline bool isSOSErrorCoded(CFErrorRef error, CFIndex sosErrorCode) { return error && CFErrorGetCode(error) == sosErrorCode && CFEqualSafe(CFErrorGetDomain(error), kSOSErrorDomain); } diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c index 8f34dbcc..2e8d6600 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c @@ -61,10 +61,6 @@ // MARK: - SOSPeerPersistence code // static CFStringRef kSOSPeerSequenceNumberKey = CFSTR("sequence-number"); -static CFStringRef kSOSPeerGetObjectsKey = CFSTR("get-objects"); -static CFStringRef kSOSPeerReceivedUnknownConfirmedDigestKey = CFSTR("received-unknown"); -static CFStringRef kSOSPeerJoinRequestedKey = CFSTR("join-requested"); -static CFStringRef kSOSPeerSkipHelloKey = CFSTR("skip-hello"); CFStringRef kSOSPeerDataLabel = CFSTR("iCloud Peer Data Meta-data"); @@ -421,11 +417,7 @@ bool SOSPeerEnsureCoder(SOSPeerRef peer, SOSFullPeerInfoRef myPeerInfo, SOSPeerI if (!SOSPeerGetCoder(peer, NULL)) { secinfo("peer", "New coder for id %@.", peer->peer_id); CFErrorRef localError = NULL; - if(SOSPeerInfoShouldUseIDSTransport(SOSFullPeerInfoGetPeerInfo(myPeerInfo), peerInfo)) - peer->coder = SOSCoderCreate(peerInfo, myPeerInfo, kCFBooleanTrue, &localError); - else - peer->coder = SOSCoderCreate(peerInfo, myPeerInfo, kCFBooleanFalse, &localError); - + peer->coder = SOSCoderCreate(peerInfo, myPeerInfo, kCFBooleanFalse, &localError); if (!peer->coder) { secerror("Failed to create coder for %@: %@", peer->peer_id, localError); CFErrorPropagate(localError, error); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c index 5b6244c6..36e2c153 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c @@ -62,8 +62,9 @@ enum SOSCoderUnwrapStatus SOSPeerHandleCoderMessage(SOSPeerRef peer, CFStringRef break; case kSOSCoderStaleEvent: // We received an event we have already processed in the past. secinfo("engine", "%@ engine stale event ignored", peer_id); + result = SOSCoderUnwrapHandled; break; - case kSOSCoderTooNew: //We received an event from the future! + case kSOSCoderTooNew: // We received an event from the future! secnotice("engine", "%@ engine received a message too soon, time to restart", peer_id); SOSCoderReset(coder); if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){ diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h index e78897b6..8251d7cb 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h @@ -1,6 +1,6 @@ -#ifndef SOSTransportCoder_h -#define SOSTransportCoder_h +#ifndef SOSPeerCoder_h +#define SOSPeerCoder_h #include #include diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c index 127298f5..ab74681c 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c @@ -158,14 +158,15 @@ bool SOSPeerInfoUpdateToV2(SOSPeerInfoRef pi, CFErrorRef *error) { if(serialNumber) CFDictionaryAddValue(v2Dictionary, sSerialNumberKey, serialNumber); CFDictionaryAddValue(v2Dictionary, sViewsKey, views); CFDictionaryAddValue(v2Dictionary, sSecurityPropertiesKey, secproperties); - if(whichTransportType == kSOSTransportPresent){ + + if (whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportIDS){ CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR("")); - CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeKVS); + CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeIDS); CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanTrue); } - else if (whichTransportType == kSOSTransportFuture || whichTransportType == kSOSTransportIDS){ + else{ CFDictionaryAddValue(v2Dictionary, sDeviceID, CFSTR("")); - CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeIDS); + CFDictionaryAddValue(v2Dictionary, sTransportType, SOSTransportMessageTypeKVS); CFDictionaryAddValue(v2Dictionary, sPreferIDS, kCFBooleanTrue); } require_action_quiet((v2data = SOSCreateDERFromDictionary(v2Dictionary, error)), out, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("No Memory"), NULL, error)); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSSysdiagnose.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSSysdiagnose.c new file mode 100644 index 00000000..3becdc52 --- /dev/null +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSSysdiagnose.c @@ -0,0 +1,735 @@ +// +// SOSSysdiagnose.c +// sec +// +// Created by Richard Murphy on 1/27/16. +// +// + + +#include "SOSCloudCircleInternal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "keychain_log.h" +#include "secToolFileIO.h" + +#include + +/* Copied from CFPriv.h */ +// #include + +CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void); +CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey; +CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey; +CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey; + + + +static char *CFDictionaryCopyCString(CFDictionaryRef dict, const void *key) { + CFStringRef val = CFDictionaryGetValue(dict, key); + char *retval = CFStringToCString(val); + return retval; +} + + + +#define MAXKVSKEYTYPE kUnknownKey +#define DATE_LENGTH 18 + +// +// secToolFileIO.c +// sec +// +// Created by Richard Murphy on 1/22/16. +// +// + +#include +#include +#include + +#define printmsg(format, ...) _printcfmsg(outFile, NULL, format, __VA_ARGS__) +#define printmsgWithFormatOptions(formatOptions, format, ...) _printcfmsg(outFile, formatOptions, format, __VA_ARGS__) +#define printerr(format, ...) _printcfmsg(errFile, NULL, format, __VA_ARGS__) + + +FILE *outFile = NULL; +FILE *errFile = NULL; + +void _printcfmsg(FILE *ff, CFDictionaryRef formatOptions, CFStringRef format, ...) +{ + va_list args; + va_start(args, format); + CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, formatOptions, format, args); + va_end(args); + CFStringPerformWithCString(message, ^(const char *utf8String) { fprintf(ff, utf8String, ""); }); + CFRelease(message); +} + + +int setOutputTo(char *dir, char *filename) { + size_t pathlen = 0; + + if(dir && filename) { + pathlen = strlen(dir) + strlen(filename) + 2; + char path[pathlen]; + snprintf(path, pathlen, "%s/%s", dir, filename); + outFile = fopen(path, "a"); + } else if(dir || filename) { + outFile = stdout; + return -1; + } else { + outFile = stdout; + } + errFile = stderr; + return 0; +} + +void closeOutput(void) { + if(outFile != stdout) { + fclose(outFile); + } + outFile = stdout; +} + +int copyFileToOutputDir(char *dir, char *toCopy) { + char *bname = basename(toCopy); + char destpath[256]; + int status; + copyfile_state_t cpfilestate = copyfile_state_alloc(); + + status = snprintf(destpath, 256, "%s/%s", dir, bname); + if(status < 0 || status > 256) return -1; + + int retval = copyfile(toCopy, destpath, cpfilestate, COPYFILE_ALL); + + copyfile_state_free(cpfilestate); + return retval; +} + + + +static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus) +{ + switch (ccstatus) + { + case kSOSCCInCircle: return "In Circle"; + case kSOSCCNotInCircle: return "Not in Circle"; + case kSOSCCRequestPending: return "Request pending"; + case kSOSCCCircleAbsent: return "Circle absent"; + case kSOSCCError: return "Circle error"; + + default: + return ""; + break; + } +} + +static void printPeerInfos(char *label, CFArrayRef (^getArray)(CFErrorRef *error)) { + CFErrorRef error = NULL; + CFArrayRef ppi = getArray(&error); + SOSPeerInfoRef me = SOSCCCopyMyPeerInfo(NULL); + CFStringRef mypeerID = SOSPeerInfoGetPeerID(me); + + if(ppi) { + printmsg(CFSTR("%s count: %ld\n"), label, (long)CFArrayGetCount(ppi)); + CFArrayForEach(ppi, ^(const void *value) { + char buf[160]; + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFIndex version = SOSPeerInfoGetVersion(peer); + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + CFStringRef devtype = SOSPeerInfoGetPeerDeviceType(peer); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + CFStringRef transportType = CFSTR("KVS"); + CFStringRef deviceID = CFSTR(""); + CFDictionaryRef gestalt = SOSPeerInfoCopyPeerGestalt(peer); + CFStringRef osVersion = CFDictionaryGetValue(gestalt, CFSTR("OSVersion")); + CFReleaseNull(gestalt); + + + if(version >= 2){ + CFDictionaryRef v2Dictionary = peer->v2Dictionary; + transportType = CFDictionaryGetValue(v2Dictionary, sTransportType); + deviceID = CFDictionaryGetValue(v2Dictionary, sDeviceID); + } + char *pname = CFStringToCString(peerName); + char *dname = CFStringToCString(devtype); + char *tname = CFStringToCString(transportType); + char *iname = CFStringToCString(deviceID); + char *osname = CFStringToCString(osVersion); + const char *me = CFEqualSafe(mypeerID, peerID) ? "me>" : " "; + + + snprintf(buf, 160, "%s %s: %-16s %-16s %-16s %-16s", me, label, pname, dname, tname, iname); + + free(pname); + free(dname); + CFStringRef pid = SOSPeerInfoGetPeerID(peer); + CFIndex vers = SOSPeerInfoGetVersion(peer); + printmsg(CFSTR("%s %@ V%d OS:%s\n"), buf, pid, vers, osname); + free(osname); + }); + } else { + printmsg(CFSTR("No %s, error: %@\n"), label, error); + } + CFReleaseNull(ppi); + CFReleaseNull(error); +} + +static void dumpCircleInfo() +{ + CFErrorRef error = NULL; + CFArrayRef generations = NULL; + CFArrayRef confirmedDigests = NULL; + bool is_user_public_trusted = false; + __block int count = 0; + + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); + if(ccstatus == kSOSCCError) { + printmsg(CFSTR("End of Dump - unable to proceed due to ccstatus (%s) error: %@\n"), getSOSCCStatusDescription(ccstatus), error); + return; + } + printmsg(CFSTR("ccstatus: %s (%d)\n"), getSOSCCStatusDescription(ccstatus), ccstatus, error); + + is_user_public_trusted = SOSCCValidateUserPublic(&error); + if(is_user_public_trusted) + printmsg(CFSTR("Account user public is trusted%@"),CFSTR("\n")); + else + printmsg(CFSTR("Account user public is not trusted error:(%@)\n"), error); + CFReleaseNull(error); + + generations = SOSCCCopyGenerationPeerInfo(&error); + if(generations) { + CFArrayForEach(generations, ^(const void *value) { + count++; + if(count%2 == 0) + printmsg(CFSTR("Circle name: %@, "),value); + + if(count%2 != 0) { + CFStringRef genDesc = SOSGenerationCountCopyDescription(value); + printmsg(CFSTR("Generation Count: %@"), genDesc); + CFReleaseNull(genDesc); + } + printmsg(CFSTR("%s\n"), ""); + }); + } else { + printmsg(CFSTR("No generation count: %@\n"), error); + } + CFReleaseNull(generations); + CFReleaseNull(error); + + printPeerInfos(" Peers", ^(CFErrorRef *error) { return SOSCCCopyValidPeerPeerInfo(error); }); + printPeerInfos(" Invalid", ^(CFErrorRef *error) { return SOSCCCopyNotValidPeerPeerInfo(error); }); + printPeerInfos(" Retired", ^(CFErrorRef *error) { return SOSCCCopyRetirementPeerInfo(error); }); + printPeerInfos(" Concur", ^(CFErrorRef *error) { return SOSCCCopyConcurringPeerPeerInfo(error); }); + printPeerInfos("Applicants", ^(CFErrorRef *error) { return SOSCCCopyApplicantPeerInfo(error); }); + + confirmedDigests = SOSCCCopyEngineState(&error); + if(confirmedDigests) + { + count = 0; + CFArrayForEach(confirmedDigests, ^(const void *value) { + count++; + if(count % 2 != 0) + printmsg(CFSTR("%@"), value); + + if(count % 2 == 0) { + CFStringRef hexDigest = CFDataCopyHexString(value); + printmsg(CFSTR(" %@\n"), hexDigest); + CFReleaseSafe(hexDigest); + } + }); + } + else + printmsg(CFSTR("No engine peers: %@\n"), error); + CFReleaseNull(confirmedDigests); +} + +static CFTypeRef getObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup) +{ + __block CFTypeRef object = NULL; + + const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; + dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); + dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); + + dispatch_group_enter(dgroup); + + CloudKeychainReplyBlock replyBlock = + ^ (CFDictionaryRef returnedValues, CFErrorRef error) + { + secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues); + object = returnedValues; + if (object) + CFRetain(object); + if (error) + { + secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error); + // CFRelease(*error); + } + dispatch_group_leave(dgroup); + secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud block exit: %@", object); + dispatch_semaphore_signal(waitSemaphore); + }; + + if (!keysToGet) + SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock); + else + SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock); + + dispatch_semaphore_wait(waitSemaphore, finishTime); + dispatch_release(waitSemaphore); + if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull + { + CFRelease(object); + object = NULL; + } + secerror("returned: %@", object); + return object; +} + +static CFStringRef printFullDataString(CFDataRef data){ + __block CFStringRef fullData = NULL; + + BufferPerformWithHexString(CFDataGetBytePtr(data), CFDataGetLength(data), ^(CFStringRef dataHex) { + fullData = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), dataHex); + }); + + return fullData; +} + +static void displayLastKeyParameters(CFTypeRef key, CFTypeRef value) +{ + CFDataRef valueAsData = asData(value, NULL); + if(valueAsData){ + CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH)); + CFDataRef keyParameterData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData)); + CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8); + CFStringRef keyParameterDescription = UserParametersDescription(keyParameterData); + if(keyParameterDescription) + printmsg(CFSTR("%@: %@: %@\n"), key, dateString, keyParameterDescription); + else + printmsg(CFSTR("%@: %@\n"), key, printFullDataString(value)); + CFReleaseNull(dateString); + CFReleaseNull(keyParameterData); + CFReleaseNull(dateData); + CFReleaseNull(keyParameterDescription); + } + else{ + printmsg(CFSTR("%@: %@\n"), key, value); + } +} + +static void displayKeyParameters(CFTypeRef key, CFTypeRef value) +{ + if(isData(value)){ + CFStringRef keyParameterDescription = UserParametersDescription((CFDataRef)value); + + if(keyParameterDescription) + printmsg(CFSTR("%@: %@\n"), key, keyParameterDescription); + else + printmsg(CFSTR("%@: %@\n"), key, value); + + CFReleaseNull(keyParameterDescription); + } + else{ + printmsg(CFSTR("%@: %@\n"), key, value); + } +} + +static void displayLastCircle(CFTypeRef key, CFTypeRef value) +{ + CFDataRef valueAsData = asData(value, NULL); + if(valueAsData){ + CFErrorRef localError = NULL; + + CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH)); + CFDataRef circleData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData)); + CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8); + SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) circleData, &localError); + + if(circle){ + CFIndex size = 5; + CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size); + CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL); + printmsgWithFormatOptions(format, CFSTR("%@: %@: %@\n"), key, dateString, circle); + CFReleaseNull(idLength); + CFReleaseNull(format); + + } + else + printmsg(CFSTR("%@: %@\n"), key, printFullDataString(circleData)); + + CFReleaseNull(dateString); + CFReleaseNull(circleData); + CFReleaseSafe(circle); + CFReleaseNull(dateData); + CFReleaseNull(localError); + } + else{ + printmsg(CFSTR("%@: %@\n"), key, value); + } +} + +static void displayCircle(CFTypeRef key, CFTypeRef value) +{ + CFDataRef circleData = (CFDataRef)value; + + CFErrorRef localError = NULL; + if (isData(circleData)) + { + CFIndex size = 5; + CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size); + CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL); + SOSCircleRef circle = SOSCircleCreateFromData(NULL, circleData, &localError); + printmsgWithFormatOptions(format, CFSTR("%@: %@\n"), key, circle); + CFReleaseSafe(circle); + CFReleaseNull(idLength); + CFReleaseNull(format); + + } + else + printmsg(CFSTR("%@: %@\n"), key, value); +} + +static void displayMessage(CFTypeRef key, CFTypeRef value) +{ + CFDataRef message = (CFDataRef)value; + if(isData(message)){ + const char* messageType = SecOTRPacketTypeString(message); + printmsg(CFSTR("%@: %s: %ld\n"), key, messageType, CFDataGetLength(message)); + } + else + printmsg(CFSTR("%@: %@\n"), key, value); +} + +static void printEverything(CFTypeRef objects) +{ + CFDictionaryForEach(objects, ^(const void *key, const void *value) { + if (isData(value)) + { + printmsg(CFSTR("%@: %@\n\n"), key, printFullDataString(value)); + } + else + printmsg(CFSTR("%@: %@\n"), key, value); + }); + +} + +static void decodeForKeyType(CFTypeRef key, CFTypeRef value, SOSKVSKeyType type){ + switch (type) { + case kCircleKey: + displayCircle(key, value); + break; + case kRetirementKey: + case kMessageKey: + displayMessage(key, value); + break; + case kParametersKey: + displayKeyParameters(key, value); + break; + case kLastKeyParameterKey: + displayLastKeyParameters(key, value); + break; + case kLastCircleKey: + displayLastCircle(key, value); + break; + case kInitialSyncKey: + case kAccountChangedKey: + case kDebugInfoKey: + case kRingKey: + case kPeerInfoKey: + default: + printmsg(CFSTR("%@: %@\n"), key, value); + break; + } +} + +static void decodeAllTheValues(CFTypeRef objects){ + SOSKVSKeyType keyType = 0; + __block bool didPrint = false; + + for (keyType = 0; keyType <= MAXKVSKEYTYPE; keyType++){ + CFDictionaryForEach(objects, ^(const void *key, const void *value) { + if(SOSKVSKeyGetKeyType(key) == keyType){ + decodeForKeyType(key, value, keyType); + didPrint = true; + } + }); + if(didPrint) + printmsg(CFSTR("%@\n"), CFSTR("")); + didPrint = false; + } +} +static bool dumpKVS(char *itemName, CFErrorRef *err) +{ + CFArrayRef keysToGet = NULL; + if (itemName) + { + CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); + fprintf(outFile, "Retrieving %s from KVS\n", itemName); + keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL); + CFReleaseSafe(itemStr); + } + dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); + dispatch_group_t work_group = dispatch_group_create(); + CFTypeRef objects = getObjectsFromCloud(keysToGet, generalq, work_group); + CFReleaseSafe(keysToGet); + if (objects) + { + fprintf(outFile, "All keys and values straight from KVS\n"); + printEverything(objects); + fprintf(outFile, "\nAll values in decoded form...\n"); + decodeAllTheValues(objects); + } + fprintf(outFile, "\n"); + return true; +} + + +static struct foo { + const char *name; + const CFStringRef *viewspec; +} string2View[] = { + { + "keychain", &kSOSViewKeychainV0 + }, { + "masterkey", &kSOSViewPCSMasterKey, + }, { + "iclouddrive", &kSOSViewPCSiCloudDrive, + }, { + "photos", &kSOSViewPCSPhotos, + }, { + "escrow", &kSOSViewPCSEscrow, + }, { + "fde", &kSOSViewPCSFDE, + }, { + "maildrop", &kSOSViewPCSMailDrop, + }, { + "icloudbackup", &kSOSViewPCSiCloudBackup, + }, { + "notes", &kSOSViewPCSNotes, + }, { + "imessage", &kSOSViewPCSiMessage, + }, { + "feldspar", &kSOSViewPCSFeldspar, + }, { + "appletv", &kSOSViewAppleTV, + }, { + "homekit", &kSOSViewHomeKit, + }, { + "wifi", &kSOSViewWiFi, + }, { + "passwords", &kSOSViewAutofillPasswords, + }, { + "creditcards", &kSOSViewSafariCreditCards, + }, { + "icloudidentity", &kSOSViewiCloudIdentity, + }, { + "othersyncable", &kSOSViewOtherSyncable, + } +}; + +static CFStringRef convertViewReturnCodeToString(SOSViewActionCode ac) { + CFStringRef retval = NULL; + switch(ac) { + case kSOSCCGeneralViewError: + retval = CFSTR("General Error"); break; + case kSOSCCViewMember: + retval = CFSTR("Is Member of View"); break; + case kSOSCCViewNotMember: + retval = CFSTR("Is Not Member of View"); break; + case kSOSCCViewNotQualified: + retval = CFSTR("Is not qualified for View"); break; + case kSOSCCNoSuchView: + retval = CFSTR("No Such View"); break; + } + return retval; +} + +static bool listviewcmd(CFErrorRef *err) { + unsigned n; + + for (n = 0; n < sizeof(string2View)/sizeof(string2View[0]); n++) { + CFStringRef viewspec = *string2View[n].viewspec; + + SOSViewResultCode rc = SOSCCView(viewspec, kSOSCCViewQuery, err); + CFStringRef resultString = convertViewReturnCodeToString(rc); + + printmsg(CFSTR("View Result: %@ : %@\n"), resultString, viewspec); + }; + + return true; +} + + +static char *createDateStrNow() { + char *retval = NULL; + time_t clock; + + struct tm *tmstruct; + + time(&clock); + tmstruct = localtime(&clock); + + retval = malloc(15); + sprintf(retval, "%04d%02d%02d%02d%02d%02d", tmstruct->tm_year+1900, tmstruct->tm_mon+1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec); + return retval; +} + +#if !TARGET_OS_EMBEDDED +static char *assemblePath(char *dir, char *fname) { + size_t length = strlen(dir) + strlen(fname) + 2; + char *outputDir = malloc(length); + int status = snprintf(outputDir, length, "%s/%s", dir, fname); + if(status < 0) return NULL; + return outputDir; +} + +static char *homedirPath() { + char *homeDir = ""; + struct passwd* pwd = getpwuid(getuid()); + if (pwd) homeDir = pwd->pw_dir; + return homeDir; +} +#endif + +static char *sysdiagnose_dir(const char *passedIn, const char *hostname, const char *productVersion, const char *now) { + if(passedIn) return (char *) passedIn; + + // OUTPUTBASE=ckcdiagnose_snapshot_${HOSTNAME}_${PRODUCT_VERSION}_${NOW} + char *outputParent = NULL; + size_t length = strlen("ckcdiagnose_snapshot___") + strlen(hostname) + strlen(productVersion) + strlen(now) + 1; + char *outputBase = malloc(length); + int status = snprintf(outputBase, length, "ckcdiagnose_snapshot_%s_%s_%s", hostname, productVersion, now); + if(status < 0) outputBase = ""; + +#if TARGET_OS_EMBEDDED + outputParent = "/Library/Logs/CrashReporter"; +#else + outputParent = "/var/tmp"; +#endif + length = strlen(outputParent) + strlen(outputBase) + 2; + char *outputDir = malloc(length); + status = snprintf(outputDir, length, "%s/%s", outputParent, outputBase); + if(status < 0) return NULL; + return outputDir; +} + + + +static char *sysdiagnose_dump(const char *dirname) { + char *outputDir = NULL; + char hostname[80]; + char *productName = NULL; + char *productVersion = NULL; + char *buildVersion = NULL; + char *keysToRegister = NULL; + char *cloudkeychainproxy3 = NULL; + char *now = createDateStrNow(); + + CFDictionaryRef sysfdef = _CFCopySystemVersionDictionary(); + if(sysfdef) { + productName = CFDictionaryCopyCString(sysfdef, _kCFSystemVersionProductNameKey); + productVersion = CFDictionaryCopyCString(sysfdef, _kCFSystemVersionProductVersionKey); + buildVersion = CFDictionaryCopyCString(sysfdef, _kCFSystemVersionBuildVersionKey); + } + if (productName == NULL) + productName = strdup("unknownProduct"); + if (productVersion == NULL) + productVersion = strdup("unknownProductVersion"); + if (buildVersion) + buildVersion = strdup("unknownVersion"); + + if(gethostname(hostname, 80)) { + strcpy(hostname, "unknownhost"); + } + +#if TARGET_OS_EMBEDDED + keysToRegister = "/private/var/preferences/com.apple.security.cloudkeychainproxy3.keysToRegister.plist"; + cloudkeychainproxy3 = "/var/mobile/Library/SyncedPreferences/com.apple.security.cloudkeychainproxy3.plist"; +#else + char *homeDir = homedirPath(); + keysToRegister = assemblePath(homeDir, "Library/Preferences/com.apple.security.cloudkeychainproxy3.keysToRegister.plist"); + cloudkeychainproxy3 = assemblePath(homeDir, "Library/SyncedPreferences/com.apple.security.cloudkeychainproxy3.plist"); +#endif + + outputDir = sysdiagnose_dir(dirname, hostname, productVersion, now); + if(!outputDir) return NULL; + + mkdir(outputDir, 0700); + + setOutputTo(outputDir, "sw_vers.log"); + // report uname stuff + hostname + fprintf(outFile, "HostName: %s\n", hostname); + fprintf(outFile, "ProductName: %s\n", productName); + fprintf(outFile, "ProductVersion: %s\n", productVersion); + fprintf(outFile, "BuildVersion: %s\n", buildVersion); + closeOutput(); + + setOutputTo(outputDir, "syncD.log"); + // do sync -D + dumpKVS(optarg, NULL); + closeOutput(); + + setOutputTo(outputDir, "synci.log"); + // do sync -i + dumpCircleInfo(); + closeOutput(); + + setOutputTo(outputDir, "syncL.log"); + // do sync -L + listviewcmd(NULL); + closeOutput(); + + copyFileToOutputDir(outputDir, keysToRegister); + copyFileToOutputDir(outputDir, cloudkeychainproxy3); + + if(productName) free(productName); + if(productVersion) free(productVersion); + if(buildVersion) free(buildVersion); + + free(now); + CFReleaseNull(sysfdef); +#if ! TARGET_OS_EMBEDDED + free(keysToRegister); + free(cloudkeychainproxy3); +#endif + return outputDir; +} + + +char *SOSCCSysdiagnose(const char *directoryname) { + sysdiagnose_dump(directoryname); + return NULL; +} + diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c index 76fe9ec5..e001acb1 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c @@ -443,12 +443,8 @@ CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountRef account, CFDictiona if (handledPeers) { // We need to look for and send responses. - - CFErrorRef syncError = NULL; - if (!SOSTransportMessageSyncWithPeers((SOSTransportMessageRef)account->kvs_message_transport, handledPeers, &syncError)) { - secerror("Sync with peers failed: %@", syncError); - } - + SOSAccountSyncWithAllPeers(account, error); + CFDictionaryForEach(handledPeers, ^(const void *key, const void *value) { if (isString(key) && isArray(value)) { CFArrayForEach(value, ^(const void *value) { @@ -462,7 +458,6 @@ CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountRef account, CFDictiona }); } }); - CFErrorRef flushError = NULL; if (!SOSTransportMessageFlushChanges((SOSTransportMessageRef)account->kvs_message_transport, &flushError)) { secerror("Flush failed: %@", flushError); diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c deleted file mode 100644 index b1255f48..00000000 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c +++ /dev/null @@ -1,229 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - - -// For now transport (the abstract class) consumes the Transport data in engine to hold -// coder state. -static SOSCoderRef SOSTransportMessageCopyPeerCoder(SOSTransportMessageRef transport, CFStringRef peer_id){ - SOSCoderRef coder = NULL; - - CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id); - - if (coderData) { - CFErrorRef localError = NULL; - coder = SOSCoderCreateFromData(coderData, &localError); - - if (!coder) { - secerror("Failed to make coder from valid data for peer %@ (%@). THIS IS FATAL: WE CAN'T COMMUNICATE.", peer_id, localError); - } - - CFReleaseNull(localError); - } - else - secerror("Failed to get coderData from engine for peer %@. THIS IS FATAL: WE CAN'T COMMUNICATE.", peer_id); - - return coder; -} - -bool SOSTransportMessageSavePeerCoderData(SOSTransportMessageRef transport, SOSCoderRef coder, CFStringRef peer_id, CFErrorRef *error) { - CFDataRef coderData = NULL; - bool ok = true; - - if (coder) { - coderData = SOSCoderCopyDER(coder, error); - if (coderData == NULL) { - secerror("%@ coder data failed to export %@, zapping data", transport, error ? *error : 0); - } - } - require_action_quiet(coderData, exit, ok = SOSErrorCreate(kSOSErrorAllocationFailure, error, NULL, CFSTR("Creation of coder data failed"))); - - ok = SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error); - -exit: - CFReleaseNull(coderData); - return ok; -} - -bool SOSTransportCoderInitializeForPeer(SOSTransportMessageRef transport, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error){ - SOSCoderRef coder = NULL; - CFStringRef peer_id = SOSPeerInfoGetPeerID(peerInfo); - CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id); - if(coderData != NULL) { - CFErrorRef coderError = NULL; - coder = SOSCoderCreateFromData(coderData, &coderError); - - if (!coder) { - secerror("Found data but couldn't make coder for %@: %@", peer_id, coderError); - } - CFReleaseNull(coderError); - } - - bool haveGoodCoder = coder; - if (!haveGoodCoder) { - secnotice("transport", "New coder for id %@.", peer_id); - if(SOSPeerInfoShouldUseIDSTransport(SOSFullPeerInfoGetPeerInfo(myPeerInfo), peerInfo)) - coder = SOSCoderCreate(peerInfo, myPeerInfo, kCFBooleanTrue, error); - else - coder = SOSCoderCreate(peerInfo, myPeerInfo, kCFBooleanFalse, error); - if (coder) { - haveGoodCoder = SOSTransportMessageSavePeerCoderData(transport, coder, peer_id, error); - } else { - secerror("Couldn't make coder for %@", peer_id); - } - } - - if (coder) - SOSCoderDispose(coder); - return haveGoodCoder; -} - -enum SOSCoderUnwrapStatus SOSTransportMessageHandleCoderMessage(SOSTransportMessageRef transport, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, CFErrorRef *error){ - - enum SOSCoderUnwrapStatus result = SOSCoderUnwrapError; - CFMutableDataRef localDecodedMessage = NULL; - - SOSCoderStatus coderStatus = kSOSCoderDataReturned; - SOSCoderRef coder = SOSTransportMessageCopyPeerCoder(transport, peer_id); - if(!coder){ - SOSAccountEnsurePeerRegistration(SOSTransportMessageGetAccount(transport), error); - coder = SOSTransportMessageCopyPeerCoder(transport, peer_id); - secnotice("transport", "Building new coder!"); - } - CFErrorRef localError = NULL; - if (coder) { - coderStatus = SOSCoderUnwrap(coder, codedMessage, &localDecodedMessage, peer_id, error); - - switch(coderStatus) { - case kSOSCoderDataReturned: { - logRawMessage(localDecodedMessage, false, 0); - result = SOSCoderUnwrapDecoded; - break; - } - case kSOSCoderNegotiating: // Sent message already in Unwrap. - result = SOSCoderUnwrapHandled; - secnotice("transport", "%@ transport negotiating", peer_id); - break; - case kSOSCoderNegotiationCompleted: - if (SOSEnginePeerDidConnect(SOSTransportMessageGetEngine(transport), peer_id, error)) - result = SOSCoderUnwrapHandled; - secnotice("transport", "%@ transport negotiation complete", peer_id); - break; - case kSOSCoderFailure: // Probably restart coder - secnotice("transport", "%@ transport failed handling message %@", peer_id, error ? *error : NULL); - SOSCoderReset(coder); - if (SOSCoderStart(coder, &localError) == kSOSCoderFailure) { - secerror("Attempt to recover coder failed to restart: %@", localError); - } - break; - case kSOSCoderStaleEvent: // We received an event we have already processed in the past. - result = SOSCoderUnwrapHandled; - secinfo("transport", "%@ transport stale event ignored", peer_id); - break; - case kSOSCoderTooNew: //We received an event from the future! - secnotice("transport", "%@ transport received a message too soon, time to restart", peer_id); - SOSCoderReset(coder); - if(SOSCoderStart(coder, &localError) == kSOSCoderFailure){ - secerror("Attempt to recover coder failed to restart: %@", localError); - } - - default: - assert(false); - break; - } - if(decodedMessage) - *decodedMessage = CFRetainSafe(localDecodedMessage); - CFReleaseNull(localDecodedMessage); - - SOSTransportMessageSavePeerCoderData(transport, coder, peer_id, NULL); - SOSCoderDispose(coder); - } else { - secerror("SOSTransportMessageHandleCoderMessage: Could not make a new coder!"); - } - - CFReleaseNull(localError); - - return result; -} - -// TODO: This should be SOSTransportMessage and be split up into coder/message pieces -/* Send a message to peer if needed. Return false if there was an error, true otherwise. */ -bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) { - SOSCoderRef coder = SOSTransportMessageCopyPeerCoder(transport, peer_id); - - if(!coder){ - SOSAccountEnsurePeerRegistration(SOSTransportMessageGetAccount(transport), error); - coder = SOSTransportMessageCopyPeerCoder(transport, peer_id); - } - CFDataRef message_to_send = NULL; - bool ok = false; - SOSEnginePeerMessageSentBlock sent = NULL; - - require_action_quiet(coder, fail, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("SOSTransportMessageCopyPeerCoder failed"), *error, error)); - - if (SOSCoderCanWrap(coder)) { - secinfo("transport", "%@ Coder can wrap, getting message from engine", peer_id); - CFMutableDataRef codedMessage = NULL; - CFDataRef message = SOSEngineCreateMessageToSyncToPeer(SOSTransportMessageGetEngine(transport), peer_id, &sent, error); - if (!message) { - secnotice("transport", "%@ SOSEngineCreateMessageToSyncToPeer failed: %@",peer_id, *error); - } - ok = message && (SOSCoderWrap(coder, message, &codedMessage, peer_id, error) == kSOSCoderDataReturned); - if (!ok) { - secnotice("transport", "%@ SOSCoderWrap failed: %@",peer_id, *error); - } - - if (ok) - CFRetainAssign(message_to_send, codedMessage); - - CFReleaseNull(codedMessage); - CFReleaseNull(message); - } else { - message_to_send = SOSCoderCopyPendingResponse(coder); - secinfo("transport", "%@ negotiating, %@", peer_id, message_to_send ? CFSTR("sending negotiation message.") : CFSTR("waiting for negotiation message.")); - sent = Block_copy(^(bool wasSent){ - if (wasSent) - SOSCoderConsumeResponse(coder); - }); - ok = true; - } - - if (message_to_send) { - CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - peer_id, message_to_send, - NULL); - CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, - circle_id, peer_dict, - NULL); - - ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error); - - if (sent) - sent(ok); - - CFReleaseSafe(peer_dict); - CFReleaseSafe(circle_peers); - } - - Block_release(sent); - - CFReleaseSafe(message_to_send); - - SOSTransportMessageSavePeerCoderData(transport, coder, peer_id, NULL); - -fail: - if (coder) - SOSCoderDispose(coder); - return ok; -} diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h deleted file mode 100644 index 0a546259..00000000 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef SOSTransportCoder_h -#define SOSTransportCoder_h -#include -#include - -enum SOSCoderUnwrapStatus{ - SOSCoderUnwrapError = 0, - SOSCoderUnwrapDecoded = 1, - SOSCoderUnwrapHandled = 2 -}; - -enum SOSCoderUnwrapStatus SOSTransportMessageHandleCoderMessage(SOSTransportMessageRef transport, CFStringRef peer_id, CFDataRef codedMessage, CFDataRef *decodedMessage, CFErrorRef *error); - -bool SOSTransportMessageSavePeerCoderData(SOSTransportMessageRef transport, SOSCoderRef coder, CFStringRef peer_id, CFErrorRef *error); - -bool SOSTransportCoderInitializeForPeer(SOSTransportMessageRef transport, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error); -bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error); - - -#endif diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportMessageIDS.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportMessageIDS.c index 651f1412..9111aa48 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportMessageIDS.c +++ b/OSX/sec/SOSCircle/SecureObjectSync/SOSTransportMessageIDS.c @@ -100,7 +100,7 @@ HandleIDSMessageReason SOSTransportMessageIDSHandleMessage(SOSAccountRef account SOSCircleForEachPeer(account->trusted_circle, ^(SOSPeerInfoRef peer) { CFStringRef deviceID = SOSPeerInfoCopyDeviceID(peer); - if(CFStringCompare(deviceID, fromID, 0) == 0) + if(deviceID && CFStringCompare(deviceID, fromID, 0) == 0) peerID = SOSPeerInfoGetPeerID(peer); CFReleaseNull(deviceID); }); @@ -165,7 +165,7 @@ static bool sendToPeer(SOSTransportMessageRef transport, CFStringRef circleName, SOSCloudKeychainSendIDSMessage(message, deviceID, ourPeerID, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(CFDictionaryRef returnedValues, CFErrorRef sync_error) { success = (sync_error == NULL); - if (error) { + if (sync_error && error) { CFRetainAssign(*error, sync_error); } @@ -228,28 +228,40 @@ static bool syncWithPeers(SOSTransportMessageRef transport, CFDictionaryRef circ static bool sendMessages(SOSTransportMessageRef transport, CFDictionaryRef circleToPeersToMessage, CFErrorRef *error) { __block bool result = true; SOSCircleRef circle = SOSAccountGetCircle(transport->account, error); + SOSPeerInfoRef myPeer = SOSAccountGetMyPeerInfo(transport->account); + __block CFDictionaryRef message = NULL; + __block CFStringRef peerID = NULL; + require_quiet(myPeer, fail); + CFDictionaryForEach(circleToPeersToMessage, ^(const void *key, const void *value) { if (isString(key) && isDictionary(value)) { CFStringRef circleName = (CFStringRef) key; - CFDictionaryForEach(value, ^(const void *key, const void *value) { - if (isString(key) && isDictionary(value)) { - CFStringRef peerID = (CFStringRef) key; - CFDictionaryRef message = (CFDictionaryRef) value; - SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + + CFDictionaryForEach(value, ^(const void *key1, const void *value1) { + if (isString(key1) && isDictionary(value1)) { + peerID = (CFStringRef) key1; + message = CFRetainSafe((CFDictionaryRef) value1); + } + else{ + peerID = (CFStringRef) key1; + message = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, key1, value1, NULL); + } + SOSCircleForEachPeer(circle, ^(SOSPeerInfoRef peer) { + if(!CFEqualSafe(myPeer, peer)){ CFStringRef deviceID = SOSPeerInfoCopyDeviceID(peer); - if(CFEqualSafe(SOSPeerInfoGetPeerID(peer), peerID) || CFEqualSafe(deviceID, peerID)){ + if(CFStringCompare(SOSPeerInfoGetPeerID(peer), peerID, 0) == 0){ bool rx = false; rx = sendToPeer(transport, circleName, deviceID, peerID, message, error); result &= rx; } CFReleaseNull(deviceID); - }); - } + } + }); }); } }); - +fail: return result; } diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c deleted file mode 100644 index 7fab73ab..00000000 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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@ - */ - -/* - * SOSViewManager.c - Implementation of a view manager - */ - -#include -#include - -#if 0 -/* SOSViewManager implementation. */ -struct __OpaqueSOSViewManager { - CFRuntimeBase _base; - CFMutableDictionaryRef views; -}; - -const CFStringRef kSOSContextChildInfoKey = CFSTR("cntx"); -const CFStringRef kSOSFunctionChildInfoKey = CFSTR("fctn"); -const CFStringRef kSOSViewNamesChildInfoKey = CFSTR("vwns"); - - -static CFStringRef SOSViewManagerCopyFormatDescription(CFTypeRef cf, CFDictionaryRef formatOptions) { - SOSViewManagerRef vmgr = (SOSViewManagerRef)cf; - CFStringRef desc = CFStringCreateWithFormat(kCFAllocatorDefault, formatOptions, CFSTR(""), vmgr->views); - return desc; -} - -static void SOSViewManagerDestroy(CFTypeRef cf) { - SOSViewManagerRef vmgr = (SOSViewManagerRef)cf; - CFReleaseSafe(vmgr->views); -} - -CFGiblisFor(SOSViewManager); - - -static SOSViewManagerRef SOSViewManagerCreate(CFAllocatorRef allocator, CFErrorRef *error) { - SOSViewManagerRef vmgr = NULL; - vmgr = CFTypeAllocate(SOSViewManager, struct __OpaqueSOSViewManager, allocator); - if (vmgr) - vmgr->views = CFDictionaryCreateMutableForCFTypes(allocator); - return vmgr; -} - -CFGiblisGetSingleton(SOSViewManagerRef, SOSGetViewManager, sSOSViewManager, ^{ - *sSOSViewManager = SOSViewManagerCreate(kCFAllocatorDefault, NULL); -}); - - -static CFStringRef CFStringCreateWithViewNames(CFArrayRef viewNames) { - CFIndex count = CFArrayGetCount(viewNames); - CFMutableArrayRef mvn = CFArrayCreateMutableCopy(kCFAllocatorDefault, count, viewNames); - CFArraySortValues(mvn, CFRangeMake(0, count), (CFComparatorFunction)CFStringCompare, 0); - CFStringRef string = CFStringCreateByCombiningStrings(kCFAllocatorDefault, mvn, CFSTR(":")); - CFRelease(mvn); - return string; -} - -static SOSViewRef SOSViewManangerCopyViewWithName(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFStringRef viewName, bool isConcrete, CFErrorRef *error) { - SOSViewRef view = (SOSViewRef)CFDictionaryGetValue(vmgr->views, viewName); - if (view) { - if (isConcrete) - SOSViewSetConcrete(view, true); - CFRetain(view); - } else { - view = SOSViewCreate(CFGetAllocator(vmgr), isConcrete, NULL, error); - if (view) { - CFDictionarySetValue(vmgr->views, viewName, view); - } - // TODO: Query for the initial manifest. - } - if (view) { - if (isConcrete) - CFDictionarySetValue(referencedViews, viewName, kCFBooleanTrue); - else if (!CFDictionaryContainsKey(referencedViews, viewName)) - CFDictionarySetValue(referencedViews, viewName, kCFBooleanFalse); - } - return view; -} - -static SOSViewRef SOSViewManangerCopyCompositeViewWithNames(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFArrayRef viewNames, CFErrorRef *error) { - CFStringRef compositeName = CFStringCreateWithViewNames(viewNames); - SOSViewRef compositeView = (SOSViewRef)CFDictionaryGetValue(vmgr->views, compositeName); - if (compositeView) { - CFDictionarySetValue(referencedViews, compositeName, kCFBooleanTrue); - CFRetain(compositeView); - } else { - compositeView = SOSViewCreate(CFGetAllocator(vmgr), true, NULL, error); - if (compositeView) { - // Find the views for each name, and add the new view as a child to each one. - CFStringRef viewName; - CFArrayForEachC(viewNames, viewName) { - SOSViewRef parent = SOSViewManangerCopyViewWithName(vmgr, referencedViews, viewName, false, error); - if (!parent) { - CFReleaseNull(compositeView); - break; - } - SOSViewAddChild(parent, compositeView); - // Update the composite view's manifest by adding each parents manifest. - // TODO: Potentially move this out of the loop and create a single multi way manifest union operation - SOSManifestRef pmf = SOSViewCopyManifest(parent, error); - SOSViewUpdateManifest(compositeView, kSOSDataSourceSOSTransaction, NULL, pmf, error); - CFReleaseSafe(pmf); - } - CFDictionarySetValue(vmgr->views, viewName, compositeView); - } - } - CFReleaseSafe(compositeName); - return compositeView; -} - -static bool SOSViewManangerAddChildWithInfo(SOSViewManagerRef vmgr, CFMutableDictionaryRef referencedViews, CFDictionaryRef childInfo, CFErrorRef *error) { - CFArrayRef viewNames = (CFArrayRef)CFDictionaryGetValue(childInfo, kSOSViewNamesChildInfoKey); -// const void *context = (const void *)CFDictionaryGetValue(childInfo, kSOSContextChildInfoKey); -// const void *func = (const void *)CFDictionaryGetValue(childInfo, kSOSFunctionChildInfoKey); - - CFIndex count = CFArrayGetCount(viewNames); - if (count == 1) { - CFStringRef key = CFArrayGetValueAtIndex(viewNames, 0); - SOSViewRef view = SOSViewManangerCopyViewWithName(vmgr, referencedViews, key, true, error); - // TODO: Fix this... - //SOSViewAddClient(view, context, func); - if (view) count++; // TODO: REMOVE MOVE -- HERE ONLY FOR COMPILER WARNING - } else if (count > 1) { - SOSViewRef view = SOSViewManangerCopyCompositeViewWithNames(vmgr, referencedViews, viewNames, error); - // TODO: Fix this... - //SOSViewAddClient(view, context, func); - if (view) count++; // TODO: REMOVE MOVE -- HERE ONLY FOR COMPILER WARNING - } - - return true; -} - -struct SOSViewManagerContext { - SOSViewManagerRef vmgr; - CFDictionaryRef referencedViews; -}; - -static void SOSViewManagerUpdateView(const void *key, const void *value, void *context) { - struct SOSViewManagerContext *vmc = context; - CFBooleanRef isConcrete = CFDictionaryGetValue(vmc->referencedViews, key); - if (!isConcrete) { - CFDictionaryRemoveValue(vmc->vmgr->views, key); - } else if (CFBooleanGetValue(isConcrete) == 0) { - SOSViewRef view = (SOSViewRef)CFDictionaryGetValue(vmc->vmgr->views, key); - SOSViewSetConcrete(view, false); - } -} - -bool SOSViewManagerSetChildren(SOSViewManagerRef vmgr, CFArrayRef children, CFErrorRef *error) { - bool ok = true; - CFMutableDictionaryRef referencedViews = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); - CFDictionaryRef childInfo; - CFArrayForEachC(children, childInfo) { - ok &= SOSViewManangerAddChildWithInfo(vmgr, referencedViews, childInfo, error); - } - - // Potentially populate all views here. - - // Cleanup, remove any views we no longer reference, and set any views which need not be concrete as such. - struct SOSViewManagerContext vmc = { - .vmgr = vmgr, - .referencedViews = referencedViews, - }; - CFDictionaryApplyFunction(vmgr->views, SOSViewManagerUpdateView, &vmc); - CFRetainSafe(referencedViews); - - return ok; -} -#endif diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c deleted file mode 100644 index 35719330..00000000 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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@ - */ - -/* - * SOSViewQueries.c - Implementation of a manifest caching views and children - */ - -#include - -// Views for backup -const CFStringRef kSOSViewiCloudBackupV0 = CFSTR("iCloudBackupV0"); -const CFStringRef kSOSViewiTunesBackupV0 = CFSTR("iTunesBackupV0"); - -// Query syntax: -// orquery ::= (or andquery,...) -// andquery ::= (and attrquery, ...) -// attrquery ::= (attrname optail) -// optail ::= [ null | any | true | false | eq value... | neq value... ] -// attrname ::= string -// value ::= string | data | number | digest -// string ::= identifer -// number ::= [0-9]+ -// digest ::= hexdata -// hexdata ::= X' hexwords... ' -// hexwords ::= hexdigit hexdigit -// hexdigit ::= [0-9A-F] - -// Keychain Sync View Queries -const CFStringRef kSOSViewQueryKeychainV0 = -CFSTR("(and (class eq genp inet keys) (sync true) (pdmn ak ck dk aku cku dku) (tkid null) (vwht null) (any genpv6 inetv6 keysv6)"); -const CFStringRef kSOSViewQueryKeychainV2 = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht null) (all genpv8 ))"); - -// Backup View Queries -const CFStringRef kSOSViewQueryiCloudBackupV0 = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (tkid null) (vwht null))"); -const CFStringRef kSOSViewQueryiCloudBackupV2 = -CFSTR("(and (class eq genp inet keys cert) (pdmn ak ck dk aku cku dku) (tkid null) (vwht null))"); -const CFStringRef kSOSViewQueryiTunesBackupV0 = -CFSTR("(and (class eq genp inet keys cert) (pdmn ak ck dk aku cku dku) (tkid null) (vwht null))"); -const CFStringRef kSOSViewQueryiTunesBackupV2 = -CFSTR("(and (class eq genp inet keys cert) (pdmn ak ck dk aku cku dku) (tkid null) (vwht null))"); - -// General View Queries -const CFStringRef kSOSViewQueryAppleTV = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq AppleTV))"); -const CFStringRef kSOSViewQueryHomeKit = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq HomeKit))"); - -// PCS View Queries -const CFStringRef kSOSViewQueryPCSMasterKey = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-MasterKey))"); -const CFStringRef kSOSViewQueryPCSiCloudDrive = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-iCloudDrive))"); -const CFStringRef kSOSViewQueryPCSPhotos = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-Photos))"); -const CFStringRef kSOSViewQueryPCSCloudKit = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-CloudKit))"); -const CFStringRef kSOSViewQueryPCSEscrow = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-Escrow))"); -const CFStringRef kSOSViewQueryPCSFDE = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-FDE))"); -const CFStringRef kSOSViewQueryPCSMailDrop = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-Maildrop))"); -const CFStringRef kSOSViewQueryPCSiCloudBackup = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-Backup))"); -const CFStringRef kSOSViewQueryPCSNotes = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-Notes))"); -const CFStringRef kSOSViewQueryPCSiMessage = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-iMessage))"); -const CFStringRef kSOSViewQueryPCSFeldspar = -CFSTR("(and (class eq genp inet keys cert) (sync true) (pdmn ak ck dk aku cku dku) (vwht eq PCS-Feldspar))"); - diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.h deleted file mode 100644 index ead3afd6..00000000 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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@ - */ - -/*! - @header SOSViewQueries.h - view queries - */ - -#ifndef _sec_SOSViewQueries_ -#define _sec_SOSViewQueries_ - -#include - -__BEGIN_DECLS - -// General View Queries -extern const CFStringRef kSOSViewQueryAppleTV; -extern const CFStringRef kSOSViewQueryHomeKit; - -// Synced View Queries -extern const CFStringRef kSOSViewQueryKeychainV0; -extern const CFStringRef kSOSViewQueryKeychainV2; - -// PCS View Queries -extern const CFStringRef kSOSViewQueryPCSMasterKey; -extern const CFStringRef kSOSViewQueryPCSiCloudDrive; -extern const CFStringRef kSOSViewQueryPCSPhotos; -extern const CFStringRef kSOSViewQueryPCSCloudKit; -extern const CFStringRef kSOSViewQueryPCSEscrow; -extern const CFStringRef kSOSViewQueryPCSFDE; -extern const CFStringRef kSOSViewQueryPCSMailDrop; -extern const CFStringRef kSOSViewQueryPCSiCloudBackup; -extern const CFStringRef kSOSViewQueryPCSNotes; -extern const CFStringRef kSOSViewQueryPCSiMessage; -extern const CFStringRef kSOSViewQueryPCSFeldspar; - -// Backup Views -// - these are not sync views - supported by backup peers -extern const CFStringRef kSOSViewiCloudBackupV0; -extern const CFStringRef kSOSViewiTunesBackupV0; - -// Backup View Queries -// - these are not sync view queries - -extern const CFStringRef kSOSViewQueryiCloudBackupV0; -extern const CFStringRef kSOSViewQueryiCloudBackupV2; -extern const CFStringRef kSOSViewQueryiTunesBackupV0; -extern const CFStringRef kSOSViewQueryiTunesBackupV2; - -__END_DECLS - -#endif /* defined(_sec_SOSViewQueries_) */ diff --git a/OSX/sec/SOSCircle/Tool/keychain_log.c b/OSX/sec/SOSCircle/Tool/keychain_log.c new file mode 100644 index 00000000..ca9339c3 --- /dev/null +++ b/OSX/sec/SOSCircle/Tool/keychain_log.c @@ -0,0 +1,716 @@ +// +// keychain_log.c +// sec +// +// Created by Richard Murphy on 1/26/16. +// +// + +#include "keychain_log.h" + +/* + * Copyright (c) 2003-2007,2009-2010,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@ + * + * keychain_add.c + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "keychain_log.h" +#include "secToolFileIO.h" +#include + +#define MAXKVSKEYTYPE kUnknownKey +#define DATE_LENGTH 18 + + +static const char *getSOSCCStatusDescription(SOSCCStatus ccstatus) +{ + switch (ccstatus) + { + case kSOSCCInCircle: return "In Circle"; + case kSOSCCNotInCircle: return "Not in Circle"; + case kSOSCCRequestPending: return "Request pending"; + case kSOSCCCircleAbsent: return "Circle absent"; + case kSOSCCError: return "Circle error"; + + default: + return ""; + break; + } +} + +static void printPeerInfos(char *label, CFArrayRef (^getArray)(CFErrorRef *error)) { + CFErrorRef error = NULL; + CFArrayRef ppi = getArray(&error); + SOSPeerInfoRef me = SOSCCCopyMyPeerInfo(NULL); + CFStringRef mypeerID = SOSPeerInfoGetPeerID(me); + + if(ppi) { + printmsg(CFSTR("%s count: %ld\n"), label, (long)CFArrayGetCount(ppi)); + CFArrayForEach(ppi, ^(const void *value) { + char buf[160]; + SOSPeerInfoRef peer = (SOSPeerInfoRef)value; + CFIndex version = SOSPeerInfoGetVersion(peer); + CFStringRef peerName = SOSPeerInfoGetPeerName(peer); + CFStringRef devtype = SOSPeerInfoGetPeerDeviceType(peer); + CFStringRef peerID = SOSPeerInfoGetPeerID(peer); + CFStringRef transportType = CFSTR("KVS"); + CFStringRef deviceID = CFSTR(""); + CFDictionaryRef gestalt = SOSPeerInfoCopyPeerGestalt(peer); + CFStringRef osVersion = CFDictionaryGetValue(gestalt, CFSTR("OSVersion")); + CFReleaseNull(gestalt); + + + if(version >= 2){ + CFDictionaryRef v2Dictionary = peer->v2Dictionary; + transportType = CFDictionaryGetValue(v2Dictionary, sTransportType); + deviceID = CFDictionaryGetValue(v2Dictionary, sDeviceID); + } + char *pname = CFStringToCString(peerName); + char *dname = CFStringToCString(devtype); + char *tname = CFStringToCString(transportType); + char *iname = CFStringToCString(deviceID); + char *osname = CFStringToCString(osVersion); + const char *me = CFEqualSafe(mypeerID, peerID) ? "me>" : " "; + + + snprintf(buf, 160, "%s %s: %-16s %-16s %-16s %-16s", me, label, pname, dname, tname, iname); + + free(pname); + free(dname); + CFStringRef pid = SOSPeerInfoGetPeerID(peer); + CFIndex vers = SOSPeerInfoGetVersion(peer); + printmsg(CFSTR("%s %@ V%d OS:%s\n"), buf, pid, vers, osname); + free(osname); + }); + } else { + printmsg(CFSTR("No %s, error: %@\n"), label, error); + } + CFReleaseNull(ppi); + CFReleaseNull(error); +} + +static void dumpCircleInfo() +{ + CFErrorRef error = NULL; + CFArrayRef generations = NULL; + CFArrayRef confirmedDigests = NULL; + bool is_user_public_trusted = false; + __block int count = 0; + + SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error); + if(ccstatus == kSOSCCError) { + printmsg(CFSTR("End of Dump - unable to proceed due to ccstatus (%s) error: %@\n"), getSOSCCStatusDescription(ccstatus), error); + return; + } + printmsg(CFSTR("ccstatus: %s (%d)\n"), getSOSCCStatusDescription(ccstatus), ccstatus, error); + + is_user_public_trusted = SOSCCValidateUserPublic(&error); + if(is_user_public_trusted) + printmsg(CFSTR("Account user public is trusted%@"),CFSTR("\n")); + else + printmsg(CFSTR("Account user public is not trusted error:(%@)\n"), error); + CFReleaseNull(error); + + generations = SOSCCCopyGenerationPeerInfo(&error); + if(generations) { + CFArrayForEach(generations, ^(const void *value) { + count++; + if(count%2 == 0) + printmsg(CFSTR("Circle name: %@, "),value); + + if(count%2 != 0) { + CFStringRef genDesc = SOSGenerationCountCopyDescription(value); + printmsg(CFSTR("Generation Count: %@"), genDesc); + CFReleaseNull(genDesc); + } + printmsg(CFSTR("%s\n"), ""); + }); + } else { + printmsg(CFSTR("No generation count: %@\n"), error); + } + CFReleaseNull(generations); + CFReleaseNull(error); + + printPeerInfos(" Peers", ^(CFErrorRef *error) { return SOSCCCopyValidPeerPeerInfo(error); }); + printPeerInfos(" Invalid", ^(CFErrorRef *error) { return SOSCCCopyNotValidPeerPeerInfo(error); }); + printPeerInfos(" Retired", ^(CFErrorRef *error) { return SOSCCCopyRetirementPeerInfo(error); }); + printPeerInfos(" Concur", ^(CFErrorRef *error) { return SOSCCCopyConcurringPeerPeerInfo(error); }); + printPeerInfos("Applicants", ^(CFErrorRef *error) { return SOSCCCopyApplicantPeerInfo(error); }); + + confirmedDigests = SOSCCCopyEngineState(&error); + if(confirmedDigests) + { + count = 0; + CFArrayForEach(confirmedDigests, ^(const void *value) { + count++; + if(count % 2 != 0) + printmsg(CFSTR("%@"), value); + + if(count % 2 == 0) { + CFStringRef hexDigest = CFDataCopyHexString(value); + printmsg(CFSTR(" %@\n"), hexDigest); + CFReleaseSafe(hexDigest); + } + }); + } + else + printmsg(CFSTR("No engine peers: %@\n"), error); + CFReleaseNull(confirmedDigests); +} + +static CFTypeRef getObjectsFromCloud(CFArrayRef keysToGet, dispatch_queue_t processQueue, dispatch_group_t dgroup) +{ + __block CFTypeRef object = NULL; + + const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC; + dispatch_semaphore_t waitSemaphore = dispatch_semaphore_create(0); + dispatch_time_t finishTime = dispatch_time(DISPATCH_TIME_NOW, maxTimeToWaitInSeconds); + + dispatch_group_enter(dgroup); + + CloudKeychainReplyBlock replyBlock = + ^ (CFDictionaryRef returnedValues, CFErrorRef error) + { + secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud returned: %@", returnedValues); + object = returnedValues; + if (object) + CFRetain(object); + if (error) + { + secerror("SOSCloudKeychainGetObjectsFromCloud returned error: %@", error); + // CFRelease(*error); + } + dispatch_group_leave(dgroup); + secinfo("sync", "SOSCloudKeychainGetObjectsFromCloud block exit: %@", object); + dispatch_semaphore_signal(waitSemaphore); + }; + + if (!keysToGet) + SOSCloudKeychainGetAllObjectsFromCloud(processQueue, replyBlock); + else + SOSCloudKeychainGetObjectsFromCloud(keysToGet, processQueue, replyBlock); + + dispatch_semaphore_wait(waitSemaphore, finishTime); + dispatch_release(waitSemaphore); + if (object && (CFGetTypeID(object) == CFNullGetTypeID())) // return a NULL instead of a CFNull + { + CFRelease(object); + object = NULL; + } + secerror("returned: %@", object); + return object; +} + +static CFStringRef printFullDataString(CFDataRef data){ + __block CFStringRef fullData = NULL; + + BufferPerformWithHexString(CFDataGetBytePtr(data), CFDataGetLength(data), ^(CFStringRef dataHex) { + fullData = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@"), dataHex); + }); + + return fullData; +} + +static void displayLastKeyParameters(CFTypeRef key, CFTypeRef value) +{ + CFDataRef valueAsData = asData(value, NULL); + if(valueAsData){ + CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH)); + CFDataRef keyParameterData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData)); + CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8); + CFStringRef keyParameterDescription = UserParametersDescription(keyParameterData); + if(keyParameterDescription) + printmsg(CFSTR("%@: %@: %@\n"), key, dateString, keyParameterDescription); + else + printmsg(CFSTR("%@: %@\n"), key, printFullDataString(value)); + CFReleaseNull(dateString); + CFReleaseNull(keyParameterData); + CFReleaseNull(dateData); + CFReleaseNull(keyParameterDescription); + } + else{ + printmsg(CFSTR("%@: %@\n"), key, value); + } +} + +static void displayKeyParameters(CFTypeRef key, CFTypeRef value) +{ + if(isData(value)){ + CFStringRef keyParameterDescription = UserParametersDescription((CFDataRef)value); + + if(keyParameterDescription) + printmsg(CFSTR("%@: %@\n"), key, keyParameterDescription); + else + printmsg(CFSTR("%@: %@\n"), key, value); + + CFReleaseNull(keyParameterDescription); + } + else{ + printmsg(CFSTR("%@: %@\n"), key, value); + } +} + +static void displayLastCircle(CFTypeRef key, CFTypeRef value) +{ + CFDataRef valueAsData = asData(value, NULL); + if(valueAsData){ + CFErrorRef localError = NULL; + + CFDataRef dateData = CFDataCreateCopyFromRange(kCFAllocatorDefault, valueAsData, CFRangeMake(0, DATE_LENGTH)); + CFDataRef circleData = CFDataCreateCopyFromPositions(kCFAllocatorDefault, valueAsData, DATE_LENGTH, CFDataGetLength(valueAsData)); + CFStringRef dateString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, dateData, kCFStringEncodingUTF8); + SOSCircleRef circle = SOSCircleCreateFromData(NULL, (CFDataRef) circleData, &localError); + + if(circle){ + CFIndex size = 5; + CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size); + CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL); + printmsgWithFormatOptions(format, CFSTR("%@: %@: %@\n"), key, dateString, circle); + CFReleaseNull(idLength); + CFReleaseNull(format); + + } + else + printmsg(CFSTR("%@: %@\n"), key, printFullDataString(circleData)); + + CFReleaseNull(dateString); + CFReleaseNull(circleData); + CFReleaseSafe(circle); + CFReleaseNull(dateData); + CFReleaseNull(localError); + } + else{ + printmsg(CFSTR("%@: %@\n"), key, value); + } +} + +static void displayCircle(CFTypeRef key, CFTypeRef value) +{ + CFDataRef circleData = (CFDataRef)value; + + CFErrorRef localError = NULL; + if (isData(circleData)) + { + CFIndex size = 5; + CFNumberRef idLength = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &size); + CFDictionaryRef format = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, CFSTR("SyncD"), CFSTR("SyncD"), CFSTR("idLength"), idLength, NULL); + SOSCircleRef circle = SOSCircleCreateFromData(NULL, circleData, &localError); + printmsgWithFormatOptions(format, CFSTR("%@: %@\n"), key, circle); + CFReleaseSafe(circle); + CFReleaseNull(idLength); + CFReleaseNull(format); + + } + else + printmsg(CFSTR("%@: %@\n"), key, value); +} + +static void displayMessage(CFTypeRef key, CFTypeRef value) +{ + CFDataRef message = (CFDataRef)value; + if(isData(message)){ + const char* messageType = SecOTRPacketTypeString(message); + printmsg(CFSTR("%@: %s: %ld\n"), key, messageType, CFDataGetLength(message)); + } + else + printmsg(CFSTR("%@: %@\n"), key, value); +} + +static void printEverything(CFTypeRef objects) +{ + CFDictionaryForEach(objects, ^(const void *key, const void *value) { + if (isData(value)) + { + printmsg(CFSTR("%@: %@\n\n"), key, printFullDataString(value)); + } + else + printmsg(CFSTR("%@: %@\n"), key, value); + }); + +} + +static void decodeForKeyType(CFTypeRef key, CFTypeRef value, SOSKVSKeyType type){ + switch (type) { + case kCircleKey: + displayCircle(key, value); + break; + case kRetirementKey: + case kMessageKey: + displayMessage(key, value); + break; + case kParametersKey: + displayKeyParameters(key, value); + break; + case kLastKeyParameterKey: + displayLastKeyParameters(key, value); + break; + case kLastCircleKey: + displayLastCircle(key, value); + break; + case kInitialSyncKey: + case kAccountChangedKey: + case kDebugInfoKey: + case kRingKey: + case kPeerInfoKey: + default: + printmsg(CFSTR("%@: %@\n"), key, value); + break; + } +} + +static void decodeAllTheValues(CFTypeRef objects){ + SOSKVSKeyType keyType = 0; + __block bool didPrint = false; + + for (keyType = 0; keyType <= MAXKVSKEYTYPE; keyType++){ + CFDictionaryForEach(objects, ^(const void *key, const void *value) { + if(SOSKVSKeyGetKeyType(key) == keyType){ + decodeForKeyType(key, value, keyType); + didPrint = true; + } + }); + if(didPrint) + printmsg(CFSTR("%@\n"), CFSTR("")); + didPrint = false; + } +} +static bool dumpKVS(char *itemName, CFErrorRef *err) +{ + CFArrayRef keysToGet = NULL; + if (itemName) + { + CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); + fprintf(outFile, "Retrieving %s from KVS\n", itemName); + keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL); + CFReleaseSafe(itemStr); + } + dispatch_queue_t generalq = dispatch_queue_create("general", DISPATCH_QUEUE_SERIAL); + dispatch_group_t work_group = dispatch_group_create(); + CFTypeRef objects = getObjectsFromCloud(keysToGet, generalq, work_group); + CFReleaseSafe(keysToGet); + if (objects) + { + fprintf(outFile, "All keys and values straight from KVS\n"); + printEverything(objects); + fprintf(outFile, "\nAll values in decoded form...\n"); + decodeAllTheValues(objects); + } + fprintf(outFile, "\n"); + return true; +} + + +static struct foo { + const char *name; + const CFStringRef *viewspec; +} string2View[] = { + { + "keychain", &kSOSViewKeychainV0 + }, { + "masterkey", &kSOSViewPCSMasterKey, + }, { + "iclouddrive", &kSOSViewPCSiCloudDrive, + }, { + "photos", &kSOSViewPCSPhotos, + }, { + "escrow", &kSOSViewPCSEscrow, + }, { + "fde", &kSOSViewPCSFDE, + }, { + "maildrop", &kSOSViewPCSMailDrop, + }, { + "icloudbackup", &kSOSViewPCSiCloudBackup, + }, { + "notes", &kSOSViewPCSNotes, + }, { + "imessage", &kSOSViewPCSiMessage, + }, { + "feldspar", &kSOSViewPCSFeldspar, + }, { + "appletv", &kSOSViewAppleTV, + }, { + "homekit", &kSOSViewHomeKit, + }, { + "wifi", &kSOSViewWiFi, + }, { + "passwords", &kSOSViewAutofillPasswords, + }, { + "creditcards", &kSOSViewSafariCreditCards, + }, { + "icloudidentity", &kSOSViewiCloudIdentity, + }, { + "othersyncable", &kSOSViewOtherSyncable, + } +}; + +static CFStringRef convertViewReturnCodeToString(SOSViewActionCode ac) { + CFStringRef retval = NULL; + switch(ac) { + case kSOSCCGeneralViewError: + retval = CFSTR("General Error"); break; + case kSOSCCViewMember: + retval = CFSTR("Is Member of View"); break; + case kSOSCCViewNotMember: + retval = CFSTR("Is Not Member of View"); break; + case kSOSCCViewNotQualified: + retval = CFSTR("Is not qualified for View"); break; + case kSOSCCNoSuchView: + retval = CFSTR("No Such View"); break; + } + return retval; +} + +static bool listviewcmd(CFErrorRef *err) { + unsigned n; + + for (n = 0; n < sizeof(string2View)/sizeof(string2View[0]); n++) { + CFStringRef viewspec = *string2View[n].viewspec; + + SOSViewResultCode rc = SOSCCView(viewspec, kSOSCCViewQuery, err); + CFStringRef resultString = convertViewReturnCodeToString(rc); + + printmsg(CFSTR("View Result: %@ : %@\n"), resultString, viewspec); + }; + + return true; +} + +#define USE_NEW_SPI 1 +#if ! USE_NEW_SPI + +static char *createDateStrNow() { + char *retval = NULL; + time_t clock; + + struct tm *tmstruct; + + time(&clock); + tmstruct = localtime(&clock); + + retval = malloc(15); + sprintf(retval, "%04d%02d%02d%02d%02d%02d", tmstruct->tm_year+1900, tmstruct->tm_mon+1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec); + return retval; +} + +// #include + +CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void); +CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey; +CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey; +CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey; + +static char *CFDictionaryCopyCString(CFDictionaryRef dict, const void *key) { + CFStringRef val = CFDictionaryGetValue(dict, key); + char *retval = CFStringToCString(val); + return retval; +} + +#include + +static void sysdiagnose_dump() { + char *outputBase = NULL; + char *outputParent = NULL; + char *outputDir = NULL; + char hostname[80]; + char *productName = NULL; + char *productVersion = NULL; + char *buildVersion = NULL; + char *keysToRegister = NULL; + char *cloudkeychainproxy3 = NULL; + char *now = createDateStrNow(); + size_t length = 0; + int status = 0; + CFDictionaryRef sysfdef = _CFCopySystemVersionDictionary(); + + if(gethostname(hostname, 80)) { + strcpy(hostname, "unknownhost"); + } + + if(sysfdef) { + productName = CFDictionaryCopyCString(sysfdef, _kCFSystemVersionProductNameKey); + productVersion = CFDictionaryCopyCString(sysfdef, _kCFSystemVersionProductVersionKey); + buildVersion = CFDictionaryCopyCString(sysfdef, _kCFSystemVersionBuildVersionKey); + } else { + strcpy(productName, "unknownProduct"); + strcpy(productVersion, "unknownProductVersion"); + strcpy(buildVersion, "unknownVersion"); + } + + // OUTPUTBASE=ckcdiagnose_snapshot_${HOSTNAME}_${PRODUCT_VERSION}_${NOW} + length = strlen("ckcdiagnose_snapshot___") + strlen(hostname) + strlen(productVersion) + strlen(now) + 1; + outputBase = malloc(length); + status = snprintf(outputBase, length, "ckcdiagnose_snapshot_%s_%s_%s", hostname, productVersion, now); + if(status < 0) outputBase = ""; + +#if TARGET_OS_EMBEDDED + outputParent = "/Library/Logs/CrashReporter"; + keysToRegister = "/private/var/preferences/com.apple.security.cloudkeychainproxy3.keysToRegister.plist"; + cloudkeychainproxy3 = "/var/mobile/Library/SyncedPreferences/com.apple.security.cloudkeychainproxy3.plist"; +#else + outputParent = "/var/tmp"; + { + char *homeDir = ""; + struct passwd* pwd = getpwuid(getuid()); + if (pwd) homeDir = pwd->pw_dir; + + char *k2regfmt = "%s/Library/Preferences/com.apple.security.cloudkeychainproxy3.keysToRegister.plist"; + char *ckp3fmt = "%s/Library/SyncedPreferences/com.apple.security.cloudkeychainproxy3.plist"; + size_t k2rlen = strlen(homeDir) + strlen(k2regfmt) + 2; + size_t ckp3len = strlen(homeDir) + strlen(ckp3fmt) + 2; + keysToRegister = malloc(k2rlen); + cloudkeychainproxy3 = malloc(ckp3len); + snprintf(keysToRegister, k2rlen, k2regfmt, homeDir); + snprintf(cloudkeychainproxy3, ckp3len, ckp3fmt, homeDir); + } +#endif + + length = strlen(outputParent) + strlen(outputBase) + 2; + outputDir = malloc(length); + status = snprintf(outputDir, length, "%s/%s", outputParent, outputBase); + if(status < 0) return; + + mkdir(outputDir, 0700); + + setOutputTo(outputDir, "sw_vers.log"); + // report uname stuff + hostname + fprintf(outFile, "HostName: %s\n", hostname); + fprintf(outFile, "ProductName: %s\n", productName); + fprintf(outFile, "ProductVersion: %s\n", productVersion); + fprintf(outFile, "BuildVersion: %s\n", buildVersion); + closeOutput(); + + setOutputTo(outputDir, "syncD.log"); + // do sync -D + dumpKVS(optarg, NULL); + closeOutput(); + + setOutputTo(outputDir, "synci.log"); + // do sync -i + dumpCircleInfo(); + closeOutput(); + + setOutputTo(outputDir, "syncL.log"); + // do sync -L + listviewcmd(NULL); + closeOutput(); + + copyFileToOutputDir(outputDir, keysToRegister); + copyFileToOutputDir(outputDir, cloudkeychainproxy3); + + free(now); + if(productName) free(productName); + if(productVersion) free(productVersion); + if(buildVersion) free(buildVersion); + CFReleaseNull(sysfdef); +#if ! TARGET_OS_EMBEDDED + free(keysToRegister); + free(cloudkeychainproxy3); +#endif + +} +#else +static void sysdiagnose_dump() { + SOSCCSysdiagnose(NULL); +} + +#endif /* USE_NEW_SPI */ + + +// enable, disable, accept, reject, status, Reset, Clear +int +keychain_log(int argc, char * const *argv) +{ + /* + "Keychain Logging" + " -i info (current status)" + " -D [itemName] dump contents of KVS" + " -L list all known view and their status" + " -s sysdiagnose log dumps" + + */ + setOutputTo(NULL, NULL); + + int ch, result = 0; + CFErrorRef error = NULL; + bool hadError = false; + + while ((ch = getopt(argc, argv, "DiLs")) != -1) + switch (ch) { + + case 'i': + dumpCircleInfo(); + break; + + + case 's': + sysdiagnose_dump(); + break; + + case 'D': + hadError = !dumpKVS(optarg, &error); + break; + + case 'L': + hadError = !listviewcmd(&error); + break; + + case '?': + default: + return 2; /* Return 2 triggers usage message. */ + } + + if (hadError) + printerr(CFSTR("Error: %@\n"), error); + + return result; +} diff --git a/OSX/sec/SOSCircle/Tool/keychain_log.h b/OSX/sec/SOSCircle/Tool/keychain_log.h new file mode 100644 index 00000000..f0b98a15 --- /dev/null +++ b/OSX/sec/SOSCircle/Tool/keychain_log.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * keychain_log.h + * + * security tool subcommand (log) for sysdiagnose/ckcdiagnose information. + * + */ + + +#include + +SECURITY_COMMAND( + "synclog", keychain_log, + "[options]\n" + " -s sysdiagnose dump\n" + " -i info (current status)\n" + " -D [itemName] dump contents of KVS\n" + " -L list all known view and their status\n" + "\n", + "iCloud Keychain Logging") diff --git a/OSX/sec/SOSCircle/Tool/keychain_sync.c b/OSX/sec/SOSCircle/Tool/keychain_sync.c index 98406361..5bd81cf8 100644 --- a/OSX/sec/SOSCircle/Tool/keychain_sync.c +++ b/OSX/sec/SOSCircle/Tool/keychain_sync.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include @@ -52,25 +55,15 @@ #include #include -#include "SOSCommands.h" +#include "keychain_sync.h" +#include "keychain_log.h" +#include "secToolFileIO.h" #include -#define printmsg(format, ...) _printcfmsg(stdout, NULL, format, __VA_ARGS__) -#define printmsgWithFormatOptions(formatOptions, format, ...) _printcfmsg(stdout, formatOptions, format, __VA_ARGS__) -#define printerr(format, ...) _printcfmsg(stderr, NULL, format, __VA_ARGS__) #define MAXKVSKEYTYPE kUnknownKey #define DATE_LENGTH 18 -static void _printcfmsg(FILE *ff, CFDictionaryRef formatOptions, CFStringRef format, ...) -{ - va_list args; - va_start(args, format); - CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, formatOptions, format, args); - va_end(args); - CFStringPerformWithCString(message, ^(const char *utf8String) { fprintf(ff, utf8String, ""); }); - CFRelease(message); -} static bool clearAllKVS(CFErrorRef *error) { @@ -519,7 +512,7 @@ static bool dumpKVS(char *itemName, CFErrorRef *err) if (itemName) { CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); - printf("Retrieving %s from KVS\n", itemName); + fprintf(outFile, "Retrieving %s from KVS\n", itemName); keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL); CFReleaseSafe(itemStr); } @@ -529,12 +522,12 @@ static bool dumpKVS(char *itemName, CFErrorRef *err) CFReleaseSafe(keysToGet); if (objects) { - printf("All keys and values straight from KVS\n"); + fprintf(outFile, "All keys and values straight from KVS\n"); printEverything(objects); - printf("\nAll values in decoded form...\n"); + fprintf(outFile, "\nAll values in decoded form...\n"); decodeAllTheValues(objects); } - printf("\n"); + fprintf(outFile, "\n"); return true; } @@ -544,12 +537,12 @@ static bool syncAndWait(char *itemName, CFErrorRef *err) __block CFTypeRef objects = NULL; if (!itemName) { - fprintf(stderr, "No item keys supplied\n"); + fprintf(errFile, "No item keys supplied\n"); return false; } CFStringRef itemStr = CFStringCreateWithCString(kCFAllocatorDefault, itemName, kCFStringEncodingUTF8); - printf("Retrieving %s from KVS\n", itemName); + fprintf(outFile, "Retrieving %s from KVS\n", itemName); keysToGet = CFArrayCreateForCFTypes(kCFAllocatorDefault, itemStr, NULL); CFReleaseSafe(itemStr); @@ -578,7 +571,7 @@ static bool syncAndWait(char *itemName, CFErrorRef *err) CFReleaseSafe(keysToGet); dumpKVS(NULL, NULL); - printf("\n"); + fprintf(outFile, "\n"); return false; } @@ -707,7 +700,7 @@ static bool viewcmd(char *itemName, CFErrorRef *err) { if(ac == kSOSCCViewEnable) retcode = SOSCCViewSet(viewSet, NULL); else retcode = SOSCCViewSet(NULL, viewSet); - printf("SOSCCViewSet returned %s\n", (retcode)? "true": "false"); + fprintf(outFile, "SOSCCViewSet returned %s\n", (retcode)? "true": "false"); return true; } @@ -895,7 +888,7 @@ static bool setBag(char *itemName, CFErrorRef *err) } static void prClientViewState(char *label, bool result) { - printf("Sync Status for %s: %s\n", label, (result) ? "enabled": "not enabled"); + fprintf(outFile, "Sync Status for %s: %s\n", label, (result) ? "enabled": "not enabled"); } static bool clientViewStatus(CFErrorRef *error) { @@ -942,7 +935,7 @@ keychain_sync(int argc, char * const *argv) " -e enable (join/create circle)" " -i info (current status)" " -m dump my peer" - " -s schedule sync with all peers" + " -S schedule sync with all peers" " "Account/Circle Management" " -a accept all applicants" @@ -963,6 +956,10 @@ keychain_sync(int argc, char * const *argv) " -X [limit] best effort bail from circle in limit seconds" " -o list view unaware peers in circle" " -0 boot view unaware peers from circle" + " -1 grab account state from the keychain" + " -2 delete account state from the keychain" + " -3 grab engine state from the keychain" + " -4 delete engine state from the keychain" " "IDS" " -g set IDS device id" @@ -998,12 +995,13 @@ keychain_sync(int argc, char * const *argv) int ch, result = 0; CFErrorRef error = NULL; bool hadError = false; - - while ((ch = getopt(argc, argv, "ab:deg:hikl:mopq:rsv:w:x:zA:B:MNJCDEF:HG:ILOP:RT:UW:X:VY0")) != -1) + setOutputTo(NULL, NULL); + + while ((ch = getopt(argc, argv, "ab:deg:hikl:mopq:rsSv:w:x:zA:B:MNJCDEF:HG:ILOP:RT:UW:X:VY01234")) != -1) switch (ch) { case 'l': { - printf("Signing out of circle\n"); + fprintf(outFile, "Signing out of circle\n"); hadError = !SOSCCSignedOut(true, &error); if (!hadError) { errno = 0; @@ -1011,9 +1009,9 @@ keychain_sync(int argc, char * const *argv) if (errno != 0 || reason < kSOSDepartureReasonError || reason >= kSOSNumDepartureReasons) { - fprintf(stderr, "Invalid custom departure reason %s\n", optarg); + fprintf(errFile, "Invalid custom departure reason %s\n", optarg); } else { - printf("Setting custom departure reason %d\n", reason); + fprintf(outFile, "Setting custom departure reason %d\n", reason); hadError = !SOSCCSetLastDepartureReason(reason, &error); notify_post(kSOSCCCircleChangedNotification); } @@ -1023,14 +1021,14 @@ keychain_sync(int argc, char * const *argv) case 'q': { - printf("Signing out of circle\n"); + fprintf(outFile, "Signing out of circle\n"); bool signOutImmediately = false; if (strcasecmp(optarg, "true") == 0) { signOutImmediately = true; } else if (strcasecmp(optarg, "false") == 0) { signOutImmediately = false; } else { - printf("Please provide a \"true\" or \"false\" whether you'd like to leave the circle immediately\n"); + fprintf(outFile, "Please provide a \"true\" or \"false\" whether you'd like to leave the circle immediately\n"); } hadError = !SOSCCSignedOut(signOutImmediately, &error); notify_post(kSOSCCCircleChangedNotification); @@ -1039,7 +1037,7 @@ keychain_sync(int argc, char * const *argv) case 'p': { - printf("Grabbing DS ID\n"); + fprintf(outFile, "Grabbing DS ID\n"); CFStringRef deviceID = SOSCCCopyDeviceID(&error); if (error) { hadError = true; @@ -1048,9 +1046,9 @@ keychain_sync(int argc, char * const *argv) if (!isNull(deviceID)) { const char *id = CFStringGetCStringPtr(deviceID, kCFStringEncodingUTF8); if (id) - printf("IDS Device ID: %s\n", id); + fprintf(outFile, "IDS Device ID: %s\n", id); else - printf("IDS Device ID is null!\n"); + fprintf(outFile, "IDS Device ID is null!\n"); } CFReleaseNull(deviceID); break; @@ -1058,7 +1056,7 @@ keychain_sync(int argc, char * const *argv) case 'g': { - printf("Setting DS ID: %s\n", optarg); + fprintf(outFile, "Setting DS ID: %s\n", optarg); CFStringRef deviceID = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8); hadError = SOSCCSetDeviceID(deviceID, &error); CFReleaseNull(deviceID); @@ -1067,7 +1065,7 @@ keychain_sync(int argc, char * const *argv) case 'w': { - printf("Attempting to send this message over IDS: %s\n", optarg); + fprintf(outFile, "Attempting to send this message over IDS: %s\n", optarg); CFStringRef message = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8); hadError = SOSCCIDSServiceRegistrationTest(message, &error); if (error) { @@ -1080,7 +1078,7 @@ keychain_sync(int argc, char * const *argv) case 'x': { - printf("Starting ping test using this message: %s\n", optarg); + fprintf(outFile, "Starting ping test using this message: %s\n", optarg); CFStringRef message = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingUTF8); hadError = SOSCCIDSPingTest(message, &error); if (error) { @@ -1100,12 +1098,12 @@ keychain_sync(int argc, char * const *argv) break; case 'e': - printf("Turning ON keychain syncing\n"); + fprintf(outFile, "Turning ON keychain syncing\n"); hadError = requestToJoinCircle(&error); break; case 'd': - printf("Turning OFF keychain syncing\n"); + fprintf(outFile, "Turning OFF keychain syncing\n"); hadError = !SOSCCRemoveThisDeviceFromCircle(&error); break; @@ -1116,7 +1114,7 @@ keychain_sync(int argc, char * const *argv) hadError = !SOSCCAcceptApplicants(applicants, &error); CFRelease(applicants); } else { - fprintf(stderr, "No applicants to accept\n"); + fprintf(errFile, "No applicants to accept\n"); } break; } @@ -1128,7 +1126,7 @@ keychain_sync(int argc, char * const *argv) hadError = !SOSCCRejectApplicants(applicants, &error); CFRelease(applicants); } else { - fprintf(stderr, "No applicants to reject\n"); + fprintf(errFile, "No applicants to reject\n"); } break; } @@ -1156,62 +1154,105 @@ keychain_sync(int argc, char * const *argv) hadError = true; } CFReleaseNull(unawares); + break; + } + case '1': + { + CFDataRef accountState = SOSCCCopyAccountState(&error); + if (accountState) { + printmsg(CFSTR(" %@\n"), CFDataCopyHexString(accountState)); + } else { + hadError = true; + } + CFReleaseNull(accountState); + break; + } + case '2': + { + bool status = SOSCCDeleteAccountState(&error); + if (status) { + printmsg(CFSTR("Deleted account from the keychain %d\n"), status); + } else { + hadError = true; + } + break; + } + case '3': + { + CFDataRef engineState = SOSCCCopyEngineData(&error); + if (engineState) { + printmsg(CFSTR(" %@\n"), CFDataCopyHexString(engineState)); + } else { + hadError = true; + } + CFReleaseNull(engineState); + break; + } + case '4': + { + bool status = SOSCCDeleteEngineState(&error); + if (status) { + printmsg(CFSTR("Deleted engine-state from the keychain %d\n"), status); + } else { + hadError = true; + } + break; } - case 's': + case 's': #if TARGET_OS_EMBEDDED SOSCloudKeychainRequestSyncWithAllPeers(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), NULL); #else - printf("not exported yet...\n"); + fprintf(outFile, "not exported yet...\n"); #endif break; case 'E': { - printf("Ensuring Fresh Parameters\n"); + fprintf(outFile, "Ensuring Fresh Parameters\n"); bool result = SOSCCRequestEnsureFreshParameters(&error); if (error) { hadError = true; break; } if (result) { - printf("Refreshed Parameters Ensured!\n"); + fprintf(outFile, "Refreshed Parameters Ensured!\n"); } else { - printf("Problem trying to ensure fresh parameters\n"); + fprintf(outFile, "Problem trying to ensure fresh parameters\n"); } break; } case 'A': { - printf("Applying to Ring\n"); + fprintf(outFile, "Applying to Ring\n"); CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); hadError = SOSCCApplyToARing(ringName, &error); break; } case 'B': { - printf("Withdrawing from Ring\n"); + fprintf(outFile, "Withdrawing from Ring\n"); CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); hadError = SOSCCWithdrawlFromARing(ringName, &error); break; } case 'F': { - printf("Status of this device in the Ring\n"); + fprintf(outFile, "Status of this device in the Ring\n"); CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); hadError = SOSCCRingStatus(ringName, &error); break; } case 'G': { - printf("Enabling Ring\n"); + fprintf(outFile, "Enabling Ring\n"); CFStringRef ringName = CFStringCreateWithCString(kCFAllocatorDefault, (char *)optarg, kCFStringEncodingUTF8); hadError = SOSCCEnableRing(ringName, &error); break; } case 'H': { - printf("Setting random escrow record\n"); + fprintf(outFile, "Setting random escrow record\n"); bool success = SOSCCSetEscrowRecord(CFSTR("label"), 8, &error); if(success) hadError = false; @@ -1226,25 +1267,25 @@ keychain_sync(int argc, char * const *argv) CFDictionaryForEach(attempts, ^(const void *key, const void *value) { if(isString(key)){ char *keyString = CFStringToCString(key); - printf("%s:\n", keyString); + fprintf(outFile, "%s:\n", keyString); free(keyString); } if(isDictionary(value)){ CFDictionaryForEach(value, ^(const void *key, const void *value) { if(isString(key)){ char *keyString = CFStringToCString(key); - printf("%s: ", keyString); + fprintf(outFile, "%s: ", keyString); free(keyString); } if(isString(value)){ char *time = CFStringToCString(value); - printf("timestamp: %s\n", time); + fprintf(outFile, "timestamp: %s\n", time); free(time); } else if(isNumber(value)){ uint64_t tries; CFNumberGetValue(value, kCFNumberLongLongType, &tries); - printf("date: %llu\n", tries); + fprintf(outFile, "date: %llu\n", tries); } }); } @@ -1266,12 +1307,12 @@ keychain_sync(int argc, char * const *argv) } case 'I': { - printf("Printing all the rings\n"); + fprintf(outFile, "Printing all the rings\n"); CFStringRef ringdescription = SOSCCGetAllTheRings(&error); if(!ringdescription) hadError = true; else - printf("Rings: %s", CFStringToCString(ringdescription)); + fprintf(outFile, "Rings: %s", CFStringToCString(ringdescription)); break; } diff --git a/OSX/sec/SOSCircle/Tool/SOSCommands.h b/OSX/sec/SOSCircle/Tool/keychain_sync.h similarity index 94% rename from OSX/sec/SOSCircle/Tool/SOSCommands.h rename to OSX/sec/SOSCircle/Tool/keychain_sync.h index 6103461f..a36d0439 100644 --- a/OSX/sec/SOSCircle/Tool/SOSCommands.h +++ b/OSX/sec/SOSCircle/Tool/keychain_sync.h @@ -52,6 +52,11 @@ SECURITY_COMMAND( " -X [limit] best effort bail from circle in limit seconds\n" " -o list view unaware peers in circle\n" " -0 boot view unaware peers from circle\n" + " -1 grab account state from the keychain\n" + " -2 delete account state from the keychain\n" + " -3 grab engine state from the keychain\n" + " -4 delete engine state from the keychain\n" + "\n" "IDS\n" " -g set IDS device id\n" diff --git a/OSX/sec/SOSCircle/Tool/secToolFileIO.c b/OSX/sec/SOSCircle/Tool/secToolFileIO.c new file mode 100644 index 00000000..233e170f --- /dev/null +++ b/OSX/sec/SOSCircle/Tool/secToolFileIO.c @@ -0,0 +1,67 @@ +// +// secToolFileIO.c +// sec +// +// Created by Richard Murphy on 1/22/16. +// +// + +#include "secToolFileIO.h" + +#include +#include +#include + +FILE *outFile = NULL; +FILE *errFile = NULL; + +void _printcfmsg(FILE *ff, CFDictionaryRef formatOptions, CFStringRef format, ...) +{ + va_list args; + va_start(args, format); + CFStringRef message = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, formatOptions, format, args); + va_end(args); + CFStringPerformWithCString(message, ^(const char *utf8String) { fprintf(ff, utf8String, ""); }); + CFRelease(message); +} + + +int setOutputTo(char *dir, char *filename) { + size_t pathlen = 0; + + if(dir && filename) { + pathlen = strlen(dir) + strlen(filename) + 2; + char path[pathlen]; + snprintf(path, pathlen, "%s/%s", dir, filename); + outFile = fopen(path, "a"); + } else if(dir || filename) { + outFile = stdout; + return -1; + } else { + outFile = stdout; + } + errFile = stderr; + return 0; +} + +void closeOutput(void) { + if(outFile != stdout) { + fclose(outFile); + } + outFile = stdout; +} + +int copyFileToOutputDir(char *dir, char *toCopy) { + char *bname = basename(toCopy); + char destpath[256]; + int status; + copyfile_state_t cpfilestate = copyfile_state_alloc(); + + status = snprintf(destpath, 256, "%s/%s", dir, bname); + if(status < 0 || status > 256) return -1; + + int retval = copyfile(toCopy, destpath, cpfilestate, COPYFILE_ALL); + + copyfile_state_free(cpfilestate); + return retval; +} diff --git a/OSX/sec/SOSCircle/Tool/secToolFileIO.h b/OSX/sec/SOSCircle/Tool/secToolFileIO.h new file mode 100644 index 00000000..a73bcd9c --- /dev/null +++ b/OSX/sec/SOSCircle/Tool/secToolFileIO.h @@ -0,0 +1,35 @@ +// +// secToolFileIO.h +// sec +// +// Created by Richard Murphy on 1/22/16. +// +// + +#ifndef secToolFileIO_h +#define secToolFileIO_h + +#include +#include +#include +#include +#include +#include +#include + +#define printmsg(format, ...) _printcfmsg(outFile, NULL, format, __VA_ARGS__) +#define printmsgWithFormatOptions(formatOptions, format, ...) _printcfmsg(outFile, formatOptions, format, __VA_ARGS__) +#define printerr(format, ...) _printcfmsg(errFile, NULL, format, __VA_ARGS__) + +extern FILE *outFile; +extern FILE *errFile; + +void _printcfmsg(FILE *ff, CFDictionaryRef formatOptions, CFStringRef format, ...); + +int setOutputTo(char *dir, char *filename); + +void closeOutput(void); + +int copyFileToOutputDir(char *dir, char *toCopy); + +#endif /* secToolFileIO_h */ diff --git a/OSX/sec/Security/AppleBaselineEscrowCertificates.h b/OSX/sec/Security/AppleBaselineEscrowCertificates.h index 6cf859a9..5a4d011e 100644 --- a/OSX/sec/Security/AppleBaselineEscrowCertificates.h +++ b/OSX/sec/Security/AppleBaselineEscrowCertificates.h @@ -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,23 +212,23 @@ 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, }; diff --git a/OSX/sec/Security/Regressions/Security_regressions.h b/OSX/sec/Security/Regressions/Security_regressions.h index 5b09c07c..035b3d77 100644 --- a/OSX/sec/Security/Regressions/Security_regressions.h +++ b/OSX/sec/Security/Regressions/Security_regressions.h @@ -12,9 +12,11 @@ ONE_TEST(si_05_add) ONE_TEST(si_10_find_internet) ONE_TEST(si_11_update_data) ONE_TEST(si_12_item_stress) +ONE_TEST(si_13_item_system) ONE_TEST(si_14_dateparse) ONE_TEST(si_15_certificate) ONE_TEST(si_16_ec_certificate) +ONE_TEST(si_17_item_system_bluetooth) ONE_TEST(si_20_sectrust_activation) ONE_TEST(si_20_sectrust) ONE_TEST(si_21_sectrust_asr) @@ -85,6 +87,9 @@ ONE_TEST(si_85_sectrust_ssl_policy) ONE_TEST(si_86_sectrust_eap_tls) ONE_TEST(si_87_sectrust_name_constraints) ONE_TEST(si_88_sectrust_vpnprofile) +ONE_TEST(si_89_cms_hash_agility) +ONE_TEST(si_90_emcs) +ONE_TEST(si_91_sectrust_ast2) ONE_TEST(vmdh_40) ONE_TEST(vmdh_41_example) diff --git a/OSX/sec/Security/Regressions/secitem/si-13-item-system.m b/OSX/sec/Security/Regressions/secitem/si-13-item-system.m new file mode 100644 index 00000000..a1521b37 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-13-item-system.m @@ -0,0 +1,125 @@ +/* + * 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@ + */ + +#define __KEYCHAINCORE__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + + +/* Test add api in all it's variants. */ +static void tests(void) +{ + NSDictionary *item, *query; + CFTypeRef result = NULL; + NSDictionary *whoami = NULL; + + whoami = CFBridgingRelease(_SecSecuritydCopyWhoAmI(NULL)); + + NSLog(@"whoami: %@", whoami); + + /* + * first clean some + */ + + query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"keychain label", + }; + SecItemDelete((CFDictionaryRef)query); + + query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"keychain label", + (id)kSecUseSystemKeychain : @YES, + }; + SecItemDelete((CFDictionaryRef)query); + + /* + * Add entry + */ + + item = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"keychain label", + (id)kSecUseSystemKeychain : @YES, + }; + + ok_status(SecItemAdd((CFDictionaryRef)item, NULL), "SecItemAdd"); + + /* + * Check for multi user mode and its expected behavior (since its different) + */ + + bool multiUser = (whoami[@"musr"]) ? true : false; + + /* + * Check we can't find it in our keychain + */ + + query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"keychain label", + }; + + is(SecItemCopyMatching((CFTypeRef)query, &result), multiUser ? errSecItemNotFound : noErr, "SecItemCopyMatching"); + CFReleaseNull(result); + if (multiUser) { + is(SecItemDelete((CFTypeRef)query), errSecItemNotFound, "SecItemDelete"); + } else { + ok(true, "dummy"); + } + + /* + * Check we can find it in system keychain + */ + + query = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"keychain label", + (id)kSecUseSystemKeychain : @YES, + }; + + ok_status(SecItemCopyMatching((CFTypeRef)query, &result), "SecItemCopyMatching(system)"); + + ok_status(SecItemDelete((CFTypeRef)query), "SecItemDelete(system)"); +} + +int si_13_item_system(int argc, char *const *argv) +{ + plan_tests(5); + + @autoreleasepool { + tests(); + } + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-17-item-system-bluetooth.m b/OSX/sec/Security/Regressions/secitem/si-17-item-system-bluetooth.m new file mode 100644 index 00000000..a0701bf5 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-17-item-system-bluetooth.m @@ -0,0 +1,94 @@ +/* + * 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@ + */ + +#define __KEYCHAINCORE__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Security_regressions.h" + +// If we're running no server this test isn't valid +#if defined(NO_SERVER) && NO_SERVER +#define DO_TESTS false +#else +#define DO_TESTS true +#endif + + +static NSString* const kBlueToothServiceName = @"BluetoothGlobal"; + +/* Test presence of properly migrated items into system keychain. */ +static void tests(void) +{ + NSDictionary *query; + NSDictionary *whoami = NULL; + + whoami = CFBridgingRelease(_SecSecuritydCopyWhoAmI(NULL)); + + NSLog(@"whoami: %@", whoami); + + /* + * Check for multi user mode and its expected behavior (since its different) + */ + + bool multiUser = (whoami[@"musr"]) ? true : false; + + /* + * Check we can't find it in our keychain + */ + SKIP: { + skip("No Server mode, test not valid", 2, DO_TESTS) + query = @{ + (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService : kBlueToothServiceName, + }; + + is(SecItemCopyMatching((CFTypeRef)query, NULL), multiUser ? errSecItemNotFound : noErr, "Blue tooth item - user keychain"); + + query = @{ + (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrService : kBlueToothServiceName, + (__bridge id)kSecUseSystemKeychain : @YES, + }; + + is(SecItemCopyMatching((CFTypeRef)query, NULL), multiUser ? noErr : errSecItemNotFound, "Blue tooth item - system keychain"); + } +} + +int si_17_item_system_bluetooth(int argc, char *const *argv) +{ + plan_tests(2); + + @autoreleasepool { + tests(); + } + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-20-sectrust.c b/OSX/sec/Security/Regressions/secitem/si-20-sectrust.c index 584030c7..f53e135b 100644 --- a/OSX/sec/Security/Regressions/secitem/si-20-sectrust.c +++ b/OSX/sec/Security/Regressions/secitem/si-20-sectrust.c @@ -348,13 +348,106 @@ static void date_tests(void) CFReleaseNull(leaf); } +static bool test_chain_of_three(uint8_t *cert0, size_t cert0len, + uint8_t *cert1, size_t cert1len, + uint8_t *root, size_t rootlen, + bool should_succeed, CF_RETURNS_RETAINED CFStringRef *failureReason) +{ + bool ok = false; + + const void *secCert0, *secCert1, *secRoot; + isnt(secCert0 = SecCertificateCreateWithBytes(NULL, cert0, cert0len), NULL, "create leaf"); + isnt(secCert1 = SecCertificateCreateWithBytes(NULL, cert1, cert1len), NULL, "create subCA"); + isnt(secRoot = SecCertificateCreateWithBytes(NULL, root, rootlen), NULL, "create root"); + + const void *v_certs[] = { secCert0, secCert1 }; + CFArrayRef certs = NULL; + isnt(certs = CFArrayCreate(NULL, v_certs, sizeof(v_certs)/sizeof(*v_certs), NULL), + NULL, "failed to create cert array"); + CFArrayRef anchors = NULL; + isnt(anchors = CFArrayCreate(NULL, &secRoot, 1, NULL), NULL, "failed to create anchors array"); + + SecPolicyRef policy = NULL; + isnt(policy = SecPolicyCreateBasicX509(), NULL, "failed to create policy"); + CFDateRef date = NULL; + isnt(date = CFDateCreate(NULL, 472100000.0), NULL, "failed to create date"); // 17 Dec 2015 + + SecTrustRef trust = NULL; + SecTrustResultType trustResult; + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "failed to create trust"); + ok_status(SecTrustSetVerifyDate(trust, date), "failed to set verify date"); + ok_status(SecTrustSetAnchorCertificates(trust, anchors), "failed to set anchors"); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate chain"); + is(SecTrustGetCertificateCount(trust), 3, "expected chain of 3"); + bool did_succeed = (trustResult == kSecTrustResultUnspecified); + + if (failureReason && should_succeed && !did_succeed) { + *failureReason = SecTrustCopyFailureDescription(trust); + } else if (failureReason && !should_succeed && did_succeed) { + *failureReason = CFSTR("expected kSecTrustResultRecoverableTrustFailure"); + } + + if ((should_succeed && did_succeed) || (!should_succeed && !did_succeed)) { + ok = true; + } + + CFReleaseSafe(secCert0); + CFReleaseSafe(secCert1); + CFReleaseSafe(secRoot); + CFReleaseSafe(certs); + CFReleaseSafe(anchors); + CFReleaseSafe(date); + CFReleaseSafe(policy); + CFReleaseSafe(trust); + + return ok; +} + +static void rsa_key_size_tests() { + + ok(test_chain_of_three(_leaf2048A, sizeof(_leaf2048A),_int2048A, sizeof(_int2048A), _root512, sizeof(_root512), + false, NULL), "SECURITY: failed to detect weak root"); + ok(test_chain_of_three(_leaf2048B, sizeof(_leaf2048B), _int512, sizeof(_int512), _root2048, sizeof(_root2048), + false, NULL), "SECURITY: failed to detect weak intermediate"); + ok(test_chain_of_three(_leaf512, sizeof(_leaf512), _int2048B, sizeof(_int2048B), _root2048, sizeof(_root2048), + false, NULL), "SECURITY: failed to detect weak leaf"); + + CFStringRef failureReason = NULL; + ok(test_chain_of_three(_leaf1024, sizeof(_leaf1024), _int2048B, sizeof(_int2048B), _root2048, sizeof(_root2048), + true, &failureReason), "REGRESSION: key size test 1024-bit leaf: %@", failureReason); + CFReleaseNull(failureReason); + ok(test_chain_of_three(_leaf2048C, sizeof(_leaf2048C), _int2048B, sizeof(_int2048B), _root2048, sizeof(_root2048), + true, &failureReason), "REGRESSION: key size test 2048-bit leaf: %@", failureReason); + CFReleaseNull(failureReason); + +} + +static void ec_key_size_tests() { + + /* Because CoreCrypto does not support P128, we fail to chain if any CAs use weakly sized curves */ + ok(test_chain_of_three(_leaf128, sizeof(_leaf128), _int384B, sizeof(_int384B), _root384, sizeof(_root384), + false, NULL), "SECURITY: failed to detect weak leaf"); + + CFStringRef failureReason = NULL; + ok(test_chain_of_three(_leaf192, sizeof(_leaf192), _int384B, sizeof(_int384B), _root384, sizeof(_root384), + true, &failureReason), "REGRESSION: key size test 192-bit leaf: %@", failureReason); + CFReleaseNull(failureReason); + ok(test_chain_of_three(_leaf384C, sizeof(_leaf384C), _int384B, sizeof(_int384B), _root384, sizeof(_root384), + true, &failureReason), "REGRESSION: key size test 384-bit leaf: %@", failureReason); + CFReleaseNull(failureReason); + +} + int si_20_sectrust(int argc, char *const *argv) { - plan_tests(101); + plan_tests(101+8*13); basic_tests(); rsa8k_tests(); date_tests(); + rsa_key_size_tests(); + ec_key_size_tests(); return 0; } diff --git a/OSX/sec/Security/Regressions/secitem/si-20-sectrust.h b/OSX/sec/Security/Regressions/secitem/si-20-sectrust.h index 4b82fcae..a854cc1d 100644 --- a/OSX/sec/Security/Regressions/secitem/si-20-sectrust.h +++ b/OSX/sec/Security/Regressions/secitem/si-20-sectrust.h @@ -608,6 +608,10 @@ const uint8_t prt_forest_fi_certificate[1797] = { 0x3b, 0xbd, 0xbf, 0x5b, 0x4a, 0x6c, 0xd3, 0x1c, 0x47 }; +/* + * MARK: Date Test Certs + */ + /* SHA1 Fingerprint=62:45:08:9B:4A:CC:45:58:8B:0F:A1:E8:E3:AE:61:5B:4B:FF:80:93 */ /* subject:/C=US/ST=CA/O=Apple Inc./OU=ETS/CN=Escrow Service Key 5DBB9DF79A4272CB07F127CBAFFC5B9D2E7111EA68BF926199D828329535AFF1 */ /* issuer :/serialNumber=101/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Escrow Service Root CA */ @@ -749,3 +753,846 @@ const uint8_t longroot[982]={ 0x91,0x57,0x4A,0x9C,0x99,0x26, }; +// MARK: RSA Key Size Test Certs + +/* RSA Key Size Test Cert Chains + * _root512 -> _int2048A -> _leaf2048A + * _root2048 -> _int512 -> _leaf2048B + * _root2048 -> _int2048B -> _leaf512 + * _root2048 -> _int2048B -> _leaf1024 + * _root2048 -> _int2048B -> _leaf2048C + */ + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=512-bit Test Root CA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=512-bit Test Root CA */ +unsigned char _root512[600]={ + 0x30,0x82,0x02,0x54,0x30,0x82,0x01,0xFE,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xAF,0x64,0x99,0x71,0x1A,0x67,0x40,0xD8,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x03,0x0C,0x14, + 0x35,0x31,0x32,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F, + 0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33, + 0x30,0x33,0x32,0x34,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x31,0x35,0x32,0x33,0x30, + 0x33,0x32,0x34,0x5A,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43, + 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55, + 0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x14,0x30, + 0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65, + 0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69, + 0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x03,0x0C,0x14,0x35,0x31,0x32, + 0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x30,0x5C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, + 0x05,0x00,0x03,0x4B,0x00,0x30,0x48,0x02,0x41,0x00,0xBE,0x86,0xC0,0x0C,0x4A,0x75, + 0xC7,0xEC,0x8D,0xBF,0x1E,0xFC,0x70,0x58,0x23,0x5E,0xF0,0x61,0x1E,0x59,0x74,0x41, + 0x88,0x19,0x87,0x20,0x87,0x77,0xE3,0x08,0x8A,0x68,0x80,0xE4,0xED,0x35,0xE7,0x85, + 0x52,0x30,0xF7,0xF1,0xC4,0x16,0xED,0x59,0xE8,0xF3,0x40,0x23,0x8E,0x30,0x72,0x40, + 0x22,0x26,0x15,0x9F,0xE4,0x97,0xEB,0x56,0xE8,0xAF,0x02,0x03,0x01,0x00,0x01,0xA3, + 0x45,0x30,0x43,0x30,0x12,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30, + 0x06,0x01,0x01,0xFF,0x02,0x01,0x03,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x14,0xE9,0x8B,0x3E,0x9D,0x8A,0xA7,0xCA,0x70,0x97,0x2B,0x9A,0x2C,0x31, + 0xC7,0xF9,0xA2,0x5A,0x4B,0x72,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D, + 0x01,0x01,0x0B,0x05,0x00,0x03,0x41,0x00,0x6E,0x14,0x08,0x64,0xCD,0x84,0xDB,0xBF, + 0xA4,0x2B,0x5F,0x51,0x5F,0x2D,0x00,0x46,0xA5,0x20,0x28,0x53,0x74,0x90,0x6D,0x24, + 0xD4,0xB9,0x7E,0x0D,0xFD,0x5E,0x65,0x7F,0xB5,0x88,0x96,0xD8,0x54,0xBA,0xBD,0x09, + 0x1C,0x89,0x91,0x5B,0xC4,0x4B,0xD4,0x6B,0xE4,0x4B,0x7A,0xBF,0x62,0x36,0x97,0xF7, + 0x58,0xAC,0xCD,0x9C,0xAF,0x9B,0x02,0x68, +}; + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Root CA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Root CA */ +unsigned char _root2048[996]={ + 0x30,0x82,0x03,0xE0,0x30,0x82,0x02,0xC8,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xD2,0xA0,0x17,0x6E,0xF4,0xB7,0xF3,0x96,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x8B,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, + 0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32, + 0x33,0x30,0x34,0x31,0x30,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x31,0x35,0x32,0x33, + 0x30,0x34,0x31,0x30,0x5A,0x30,0x81,0x8B,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03, + 0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x14, + 0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20, + 0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53, + 0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72, + 0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30, + 0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74, + 0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02, + 0x82,0x01,0x01,0x00,0xEE,0x68,0xB9,0x94,0x15,0x11,0x2F,0x35,0x36,0xBC,0x9D,0x63, + 0x25,0x8E,0x55,0xE4,0x17,0xE0,0x60,0x9C,0x6D,0x71,0x4C,0x30,0x7B,0xB7,0xEE,0x42, + 0x2D,0xE9,0x05,0x4C,0x41,0x3A,0x19,0x97,0x77,0xCC,0x4C,0xFF,0x81,0x52,0xE8,0xDF, + 0xB7,0x1A,0x75,0x1F,0xD1,0xD7,0x4D,0x21,0x5E,0x79,0xDF,0x7E,0xCF,0x45,0x47,0xF5, + 0x4D,0x05,0xD6,0xB1,0xF3,0xEA,0xF8,0x28,0xD8,0xAC,0x2C,0xCE,0x83,0xBF,0xA5,0x70, + 0x6F,0x5B,0x46,0x39,0xF6,0xC1,0x78,0x56,0x31,0x24,0x7E,0x15,0xCE,0x04,0x50,0x99, + 0x30,0xDA,0xF0,0xAE,0x23,0xDD,0x86,0x54,0xAD,0xBC,0x55,0x45,0x93,0xCC,0xC8,0xE7, + 0x16,0x46,0x00,0x34,0x2C,0x8C,0x8F,0x31,0xED,0x08,0x3F,0xD9,0xA6,0x90,0x32,0x37, + 0x1B,0xCD,0xD4,0x16,0x83,0xEE,0xF9,0x52,0x80,0x3E,0x27,0x26,0xEF,0xEF,0xF9,0xFD, + 0xA6,0xD5,0x38,0x83,0xD9,0x8F,0xB6,0xF0,0xA1,0x0D,0x4F,0x89,0x8D,0x7C,0x14,0x7D, + 0x8F,0x7A,0x84,0xF9,0xCB,0x8C,0x68,0x9E,0xF3,0x0E,0x2C,0x68,0xBF,0x37,0x69,0x2A, + 0x67,0x90,0x7D,0xAF,0xF0,0x7B,0x38,0xBC,0xB3,0x77,0xD1,0xDD,0xF4,0x5E,0x3F,0xA0, + 0x48,0xE8,0xBA,0x59,0xD8,0xB6,0xFF,0x51,0x7C,0xB8,0xCE,0xAE,0x02,0x5A,0x71,0x1E, + 0xD6,0x5A,0x0A,0x55,0x27,0x29,0x9C,0xC2,0xF6,0x8B,0x0E,0x0D,0xFA,0xF3,0x3F,0x60, + 0x17,0xE8,0xFA,0x98,0xC0,0x92,0xD7,0x14,0x9B,0xD1,0x3E,0x03,0xE4,0x8D,0x58,0xFF, + 0x4C,0x01,0x77,0x74,0x83,0x01,0xA6,0xB1,0x81,0x34,0x26,0x0D,0xF8,0xAA,0x08,0xF2, + 0xDC,0xEA,0x32,0x11,0x02,0x03,0x01,0x00,0x01,0xA3,0x45,0x30,0x43,0x30,0x12,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01, + 0x03,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, + 0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xCA,0x4D,0x8B,0xBD, + 0x98,0x36,0x22,0xF8,0xA9,0x21,0x8E,0xEA,0xFC,0xE6,0xD7,0x17,0x81,0xA7,0xE2,0x12, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03, + 0x82,0x01,0x01,0x00,0x99,0x99,0xDB,0x59,0xEE,0x32,0x98,0x1C,0xE4,0x62,0xE4,0xF9, + 0xA5,0xE9,0xA4,0x3F,0x49,0x57,0x37,0x71,0x34,0x3E,0x68,0xAE,0x27,0xB4,0xAF,0xCB, + 0x96,0xFD,0xA8,0x0A,0xE7,0x0A,0x22,0x7C,0x5E,0x78,0x95,0xA9,0x67,0xAF,0xB4,0xDD, + 0x09,0xD1,0xE5,0x0C,0x6B,0xC6,0xD8,0x1A,0xE3,0x91,0x5F,0xBD,0xD0,0xB9,0x0F,0x1D, + 0xB9,0xB7,0xF1,0xC7,0x64,0xCA,0xAB,0x69,0x6E,0xD0,0x61,0xB3,0x9F,0x27,0x1E,0x06, + 0xB6,0x42,0x84,0xAB,0x6F,0xE7,0x2B,0xBC,0x04,0x28,0x64,0xC2,0xC0,0x1D,0x43,0xFF, + 0x2A,0x1D,0x3F,0x92,0xA1,0xD7,0xD5,0xFB,0x04,0xF9,0x57,0x9F,0x78,0x87,0x8C,0xDB, + 0xB3,0x3F,0x41,0x96,0x8E,0x65,0x50,0x39,0xE7,0xD0,0x8A,0x39,0x29,0x68,0x12,0x11, + 0x44,0xDD,0x7B,0x86,0x59,0xAF,0x40,0xEA,0x78,0xD9,0xDD,0xB5,0xDB,0xA7,0x7F,0xD4, + 0xBA,0x94,0x8D,0x7D,0xA5,0xD0,0xAA,0x48,0x42,0x1E,0x6C,0x71,0x33,0x49,0xCA,0x0D, + 0xF5,0x8D,0x10,0xD0,0x3E,0xF8,0xD3,0x35,0xAE,0x83,0xCA,0x02,0x23,0xC2,0xCD,0x21, + 0x75,0x9B,0x2C,0xE0,0xF7,0x23,0x26,0x04,0xED,0x78,0xE8,0x29,0x33,0x87,0x65,0x98, + 0x4C,0x7E,0xC3,0x61,0xB5,0xDB,0x66,0xBD,0x9D,0x3D,0xC9,0x02,0x7A,0xB8,0xA2,0x7C, + 0x81,0x8B,0x10,0xB5,0x97,0x63,0x85,0x2B,0x19,0x94,0xB3,0x4C,0x8D,0xED,0x76,0xCE, + 0x31,0x49,0xCC,0x22,0x67,0xFB,0xDA,0x6A,0x0A,0xE2,0x56,0xCD,0x51,0x6A,0x6E,0x54, + 0xDF,0x04,0x1A,0xBE,0x77,0xB9,0x28,0x2F,0xCA,0xA5,0xA5,0xF4,0xF1,0xE5,0x12,0x1B, + 0x2D,0x60,0xB7,0xA7, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test SubCA 1 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=512-bit Test Root CA */ +unsigned char _int2048A[809]={ + 0x30,0x82,0x03,0x25,0x30,0x82,0x02,0xCF,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x76, + 0xCD,0xF6,0x90,0x52,0xAA,0x72,0x81,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x8A,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06, + 0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31, + 0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C, + 0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14, + 0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65, + 0x72,0x69,0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x03,0x0C,0x14,0x35, + 0x31,0x32,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74, + 0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x30,0x32,0x30, + 0x38,0x34,0x31,0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x30,0x32,0x30,0x38, + 0x34,0x31,0x5A,0x30,0x77,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C, + 0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A, + 0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30, + 0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79, + 0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20, + 0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x31,0x30,0x82,0x01,0x22, + 0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03, + 0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xAD,0xF2,0x04, + 0x31,0xBD,0x86,0x8D,0x5A,0x0C,0xF1,0xDF,0x48,0xBE,0xD3,0x98,0x61,0x50,0x75,0x95, + 0xCB,0x1D,0xE3,0x0D,0x17,0x3F,0xEC,0xD6,0xEA,0x5C,0xB7,0x75,0xEB,0x3B,0x73,0x09, + 0x69,0x35,0xD2,0x82,0xF8,0x08,0xAE,0xF0,0xF5,0xC1,0xCA,0xFB,0x84,0x3E,0x36,0xAE, + 0xCB,0xF9,0x59,0x61,0xE2,0x18,0xED,0x77,0xF8,0xCC,0x75,0x3E,0x4B,0x98,0x81,0x2B, + 0x04,0x04,0xEE,0xC5,0x79,0x64,0xBB,0x77,0xED,0xA1,0xC3,0x6C,0x80,0xD7,0xFE,0xAE, + 0x05,0x58,0xBD,0x42,0x26,0xD5,0xC4,0xE5,0x4E,0x26,0x09,0x74,0x0A,0xAE,0x49,0x31, + 0x80,0x4E,0x25,0xD8,0x2C,0x87,0x32,0xEB,0xD9,0x3D,0xFB,0x5F,0x21,0x6B,0x0E,0xC7, + 0x83,0x4A,0x6C,0x2C,0xB1,0x82,0xEC,0xDF,0xD2,0x65,0x92,0x32,0x5C,0x30,0xEA,0x48, + 0xC7,0x13,0x39,0xB7,0x4D,0x81,0x79,0x1C,0x17,0x31,0xC1,0x83,0x42,0xFB,0xC3,0x1B, + 0xF0,0xA0,0x45,0xED,0xAA,0xDC,0x02,0x73,0x4B,0x48,0x76,0xAE,0x68,0x80,0x93,0x51, + 0x3D,0x79,0x7F,0x9E,0x53,0xD3,0x60,0x5A,0x4F,0x5B,0x2E,0xB8,0x13,0x6A,0x5F,0x27, + 0x7E,0x09,0x80,0x61,0xCF,0x41,0xDE,0xD1,0x9F,0xFA,0xEF,0x42,0xD0,0xB1,0x81,0x69, + 0x03,0x91,0x1A,0xD9,0xE2,0x33,0x34,0x78,0xFE,0x45,0xB1,0x23,0x39,0x20,0xBC,0x2D, + 0xA5,0x8A,0xB2,0x84,0xEF,0x2A,0xF4,0x6C,0x2E,0xD1,0xEE,0x61,0x38,0x8F,0xA0,0xB0, + 0x0D,0xC4,0x0A,0x3D,0xB9,0x2C,0x6D,0x77,0xB5,0xE3,0x06,0x8B,0xB4,0x0D,0xA7,0x71, + 0xFD,0x38,0x0B,0x1F,0x5C,0x1C,0x9F,0x2F,0x2E,0xA4,0xD4,0xE8,0x6F,0x02,0x03,0x01, + 0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF, + 0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01, + 0xFF,0x04,0x04,0x03,0x02,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16, + 0x04,0x14,0x03,0x99,0x06,0x5B,0xDA,0x2C,0xBA,0x9B,0x66,0x0A,0x5A,0x7B,0xAB,0x99, + 0xA5,0x7F,0x72,0xA9,0xD4,0xF7,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0x14,0xE9,0x8B,0x3E,0x9D,0x8A,0xA7,0xCA,0x70,0x97,0x2B,0x9A,0x2C, + 0x31,0xC7,0xF9,0xA2,0x5A,0x4B,0x72,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x41,0x00,0xAE,0x2A,0xA7,0x7F,0xE7,0xC9,0xE4, + 0xAA,0x2C,0x7F,0x04,0x5D,0x9B,0x0E,0x01,0x47,0x1E,0xB1,0x0E,0x35,0xD7,0x1F,0xAC, + 0x8E,0xA7,0xCC,0xAD,0x16,0xAC,0x47,0xDC,0x5E,0x13,0x1C,0x15,0x05,0x89,0x56,0xC0, + 0x76,0x55,0x96,0xA0,0x8B,0xBD,0x3B,0xD7,0x93,0x08,0xBA,0xD0,0x7E,0x64,0x7A,0xB1, + 0x74,0xE0,0x82,0x2B,0xE4,0x12,0xA3,0x4D,0x0B, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=512-bit Test SubCA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Root CA */ +unsigned char _int512[802]={ + 0x30,0x82,0x03,0x1E,0x30,0x82,0x02,0x06,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xBE,0x29,0xEC,0x6D,0x40,0x7E,0x44,0x98,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x8B,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, + 0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x30, + 0x32,0x30,0x39,0x32,0x32,0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x30,0x32, + 0x30,0x39,0x32,0x32,0x5A,0x30,0x74,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43, + 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1B, + 0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x35,0x31,0x32,0x2D,0x62,0x69,0x74, + 0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x30,0x5C,0x30,0x0D,0x06, + 0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x4B,0x00,0x30, + 0x48,0x02,0x41,0x00,0xF2,0xD1,0x57,0xDD,0xA6,0xBC,0x2B,0xBC,0x22,0x7B,0x5D,0xC5, + 0x3A,0x73,0xCE,0x80,0x88,0xD7,0xDF,0x45,0xBE,0x01,0x22,0xA7,0xC2,0x7E,0x35,0x1F, + 0x74,0x02,0xA4,0xE3,0xD9,0xF3,0xE4,0x35,0xE9,0xB0,0xBD,0x71,0xC7,0x19,0x80,0xA8, + 0x9F,0xD7,0x62,0xFC,0x46,0xA6,0x84,0xF2,0xB0,0x9F,0xF5,0x1C,0xF1,0xA5,0x18,0x58, + 0x76,0x49,0x3F,0xF9,0x02,0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x0F,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E, + 0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x02,0x04,0x30,0x1D, + 0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x9E,0x85,0x9A,0xA5,0x88,0x09,0xB0, + 0x93,0x9B,0xB4,0xE5,0xCE,0x68,0x99,0x93,0xE9,0x79,0xE9,0x7C,0x98,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xCA,0x4D,0x8B,0xBD,0x98,0x36, + 0x22,0xF8,0xA9,0x21,0x8E,0xEA,0xFC,0xE6,0xD7,0x17,0x81,0xA7,0xE2,0x12,0x30,0x0D, + 0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01, + 0x01,0x00,0xD7,0x94,0x1E,0x53,0x9B,0xB5,0xC6,0x02,0x26,0xC2,0x7F,0xB2,0xD1,0x36, + 0x63,0xD5,0xEE,0x35,0x66,0x92,0x48,0xEF,0xD1,0xB4,0xDD,0xD7,0xE1,0xDF,0x05,0xF2, + 0x76,0x74,0x28,0x75,0xC1,0x51,0x66,0x6E,0x2C,0x2A,0x8C,0x82,0x34,0xD3,0x43,0x0F, + 0x22,0x12,0x01,0xD6,0x7D,0xFA,0x0E,0xF0,0x52,0xB0,0x20,0x1E,0x25,0x2B,0x39,0xA5, + 0x2C,0xD5,0x9F,0x89,0x87,0x42,0xAC,0xCB,0xEA,0x56,0xB6,0x8A,0x65,0x40,0xD9,0x19, + 0x84,0xF3,0x37,0x71,0x1C,0x0A,0x5E,0x2C,0xBB,0xB1,0xB4,0xA0,0x99,0x35,0x5A,0x0F, + 0x62,0xE0,0x7A,0x91,0x2A,0x14,0x47,0xF9,0x2E,0x3D,0x7C,0x53,0x98,0x23,0x63,0x3D, + 0x47,0x46,0x9E,0x7C,0x49,0x09,0x50,0xEA,0xCE,0xB4,0x1A,0x17,0x4E,0x6E,0x6D,0x0A, + 0x99,0xF5,0xAD,0x6E,0x88,0xF1,0xCE,0xF0,0xD7,0xB4,0x3A,0x6E,0xE7,0x97,0x4C,0x53, + 0x04,0x1D,0xB3,0x08,0x49,0x63,0x14,0x25,0x99,0xA7,0xCD,0x82,0xD5,0xF9,0xB9,0xCB, + 0x89,0x83,0xCD,0xD5,0x9E,0x57,0xBA,0x90,0x83,0x5F,0x31,0xB4,0x3C,0x3C,0x46,0xD0, + 0xA1,0xA7,0x7F,0x7A,0xF8,0x18,0x4B,0xC0,0xA9,0x0E,0x47,0x9A,0xE4,0x9B,0x6F,0x1B, + 0xAB,0x8F,0x71,0x54,0x8E,0xA6,0x0B,0xCC,0x16,0xE2,0xCD,0x38,0xA8,0xC2,0x0E,0x20, + 0xB0,0x6E,0x9C,0x8B,0x02,0xDF,0xC3,0xCE,0xB8,0xBB,0x92,0x50,0x27,0xB2,0x81,0xC5, + 0x48,0x16,0x82,0xC4,0xB1,0x5E,0x5F,0x43,0x47,0xF9,0x6F,0x8A,0x81,0x95,0x93,0xB2, + 0x78,0x24,0x67,0xEB,0xCB,0xC1,0xA4,0x4F,0x23,0x11,0xDF,0x33,0xD0,0x5F,0x79,0x26, + 0x1F,0x81, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test SubCA 2 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Root CA */ +unsigned char _int2048B[1005]={ + 0x30,0x82,0x03,0xE9,0x30,0x82,0x02,0xD1,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xBE,0x29,0xEC,0x6D,0x40,0x7E,0x44,0x99,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x81,0x8B,0x31,0x0B,0x30,0x09,0x06,0x03, + 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08, + 0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10, + 0x06,0x03,0x55,0x04,0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, + 0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F, + 0x6F,0x74,0x20,0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x30, + 0x32,0x30,0x39,0x33,0x39,0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x30,0x32, + 0x30,0x39,0x33,0x39,0x5A,0x30,0x77,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06, + 0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43, + 0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55, + 0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31, + 0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69, + 0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1E, + 0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30,0x34,0x38,0x2D,0x62,0x69, + 0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32,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,0xBA, + 0x74,0x33,0x7D,0x7B,0x48,0x2C,0x25,0x5F,0x73,0x9C,0x09,0xCC,0xBC,0x90,0x38,0xDF, + 0x41,0x06,0xD2,0x1F,0x92,0xD3,0xF0,0x94,0xBC,0x97,0x39,0x17,0x68,0x76,0xE0,0x9C, + 0x68,0x78,0xD3,0xE7,0xC7,0xBE,0xC8,0xD8,0xBE,0x2F,0x94,0x93,0x3E,0xCF,0x24,0x4D, + 0xB3,0xCF,0xA8,0xC1,0xDF,0xF3,0xC5,0x6A,0x23,0xFC,0x7C,0xAC,0x20,0xC1,0x28,0x7D, + 0x61,0x50,0xEB,0x1D,0xD1,0xAE,0xD3,0xCC,0xEC,0x67,0x95,0x0B,0x6C,0x06,0xFE,0x6C, + 0xC5,0xBC,0xBA,0xCB,0xDF,0x2D,0x0E,0xBD,0x1E,0x67,0xF9,0xD0,0xF0,0x71,0x91,0x96, + 0xD4,0x2E,0x4C,0x1A,0xC0,0xEA,0xD7,0x8B,0x09,0xDF,0xC2,0x89,0x30,0xAD,0x48,0xC4, + 0xEE,0x22,0x7A,0x8A,0xD9,0x8E,0x71,0xD1,0xE8,0x3B,0x4D,0x2A,0xB6,0x41,0x32,0x04, + 0x66,0x5B,0x5C,0x5C,0x8D,0x0E,0xFC,0x80,0x2A,0x26,0x23,0xF8,0xEA,0x77,0xA1,0xEC, + 0xF1,0x2F,0x63,0xB0,0xB3,0xA0,0x8F,0x53,0xDB,0xF2,0x7E,0x9E,0xF8,0x8F,0x9B,0x4B, + 0xA2,0x57,0xB5,0xE9,0x47,0xEF,0x86,0xEE,0xAE,0x88,0xB5,0xF7,0x6E,0x42,0x79,0x99, + 0x84,0xB8,0x7F,0x48,0x47,0x25,0x52,0x88,0x9C,0x1F,0xAB,0x7D,0xCE,0x8B,0x21,0x39, + 0x7B,0xF6,0xD1,0xB8,0x2B,0xCE,0xDA,0x21,0x15,0x3A,0xF0,0x0D,0xD1,0x59,0x0F,0xF4, + 0xFF,0x6B,0xCF,0x71,0x5D,0xE9,0x8F,0xE7,0xC1,0x4F,0xF7,0xEA,0xB8,0xE5,0x9F,0x16, + 0xB7,0x17,0x5A,0x27,0x35,0x2C,0xDE,0x18,0xF6,0x55,0xDC,0x05,0x18,0xD2,0x12,0x0C, + 0x35,0x44,0x88,0xFC,0xEC,0x5E,0x46,0x17,0xDA,0x48,0xD5,0x73,0xD2,0x73,0xEB,0x02, + 0x03,0x01,0x00,0x01,0xA3,0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0x0C,0x3F,0x97,0x58,0x60,0x67,0x21,0xC9,0xDB,0xD4,0x23,0x58, + 0x60,0x8E,0xC1,0x3F,0x99,0x9F,0x12,0x78,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, + 0x18,0x30,0x16,0x80,0x14,0xCA,0x4D,0x8B,0xBD,0x98,0x36,0x22,0xF8,0xA9,0x21,0x8E, + 0xEA,0xFC,0xE6,0xD7,0x17,0x81,0xA7,0xE2,0x12,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x62,0x5B,0x7A, + 0xEA,0x51,0xBC,0x4B,0xE2,0xA6,0x3F,0xC9,0x71,0x1F,0x03,0x64,0x83,0x96,0x69,0x09, + 0x36,0x14,0xA3,0xCF,0xFB,0x7D,0x67,0xB5,0x24,0x12,0x10,0xCF,0xA2,0x38,0x41,0x60, + 0x73,0xDD,0x9F,0x78,0x3A,0xE2,0x57,0xBF,0x64,0x0A,0xE4,0xB5,0x97,0x64,0x38,0x6E, + 0x36,0xCE,0x49,0x5E,0x21,0x53,0x4E,0x77,0x20,0x1E,0xBE,0xE0,0x33,0xDB,0x99,0xF1, + 0xC9,0xE8,0xA8,0x29,0x0A,0x23,0xE9,0x8D,0x91,0xE3,0x65,0x03,0xCB,0x97,0xA5,0x3F, + 0xF1,0xBF,0x28,0x4D,0x6C,0x2E,0xA7,0xFE,0x65,0x57,0xBE,0x1B,0x64,0xCE,0xFB,0x4B, + 0x33,0x7C,0x79,0x9B,0xCE,0x57,0xBE,0xB3,0x11,0x44,0xC1,0xD8,0x83,0x88,0x01,0x02, + 0x7C,0x51,0x32,0x31,0xA5,0xE7,0xE2,0xD2,0x91,0xAB,0x4F,0x37,0xE7,0x8D,0xBC,0x44, + 0x93,0xC8,0x29,0x0D,0x68,0x30,0xDB,0x54,0x1A,0x42,0x92,0x54,0xC2,0x0D,0xBF,0x28, + 0x69,0x94,0x95,0x77,0xCA,0xDA,0x68,0xFA,0x12,0xF4,0x19,0xEE,0x81,0x8F,0x9C,0x22, + 0x04,0x89,0xDD,0x2F,0x0A,0x17,0xC5,0xB5,0x1C,0x3A,0x3F,0x13,0x77,0x21,0x49,0xFC, + 0xBF,0xB7,0x82,0x9A,0x37,0x8A,0x6D,0x10,0xF6,0x44,0xF2,0xD5,0xFB,0xBC,0xB6,0xC5, + 0x50,0xD7,0x9B,0x4D,0x6D,0x18,0x85,0xB7,0xE6,0x90,0xE1,0xD4,0x3F,0x16,0x8A,0x74, + 0x97,0x32,0x29,0x3C,0xCA,0xE2,0x9E,0xC6,0xEB,0xBA,0x7A,0x9B,0xF9,0xE8,0xC7,0xA5, + 0x01,0x29,0x38,0x5B,0x6D,0x13,0xFC,0x2D,0x6A,0xE9,0x99,0xEC,0x62,0x10,0xEA,0x07, + 0x31,0x7F,0xF6,0x2C,0xE3,0x85,0x8C,0x0C,0x20,0x99,0x69,0x60,0x53, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Leaf 1 */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test SubCA 1 */ +unsigned char _leaf2048A[1000]={ + 0x30,0x82,0x03,0xE4,0x30,0x82,0x02,0xCC,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x7E, + 0x98,0x75,0xB3,0x73,0xE3,0x76,0xC7,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x77,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72, + 0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31, + 0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30,0x34,0x38,0x2D,0x62, + 0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x31,0x30, + 0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x31,0x38,0x35,0x36,0x5A, + 0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x31,0x38,0x35,0x36,0x5A,0x30, + 0x76,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72, + 0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70, + 0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55, + 0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67, + 0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x14,0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74, + 0x20,0x4C,0x65,0x61,0x66,0x20,0x31,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09,0x2A, + 0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00,0x30, + 0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xB3,0xA5,0x19,0x09,0x20,0x84,0xCE,0x67, + 0x24,0x88,0xCD,0xEB,0x25,0x9C,0xE7,0xD3,0x52,0xC5,0xC0,0x0F,0xA2,0x39,0x6C,0xF2, + 0x1D,0x6D,0x8F,0x29,0x45,0x09,0xD8,0x34,0xE8,0xD7,0xE0,0xD4,0xE6,0x96,0x20,0x33, + 0xDC,0x4A,0x99,0x3F,0x39,0x20,0x52,0x72,0x4A,0x12,0x5F,0x31,0xF3,0xB0,0x2B,0x17, + 0x6E,0x6B,0x80,0x8F,0xFD,0xC7,0x48,0x8D,0x42,0xBB,0xFA,0x2E,0xBD,0x98,0xA4,0x14, + 0x6B,0x6B,0xD0,0x98,0x3D,0x33,0x13,0x99,0x00,0x3A,0x69,0xAD,0x76,0xD5,0x2A,0x01, + 0x7B,0x32,0x68,0x2D,0x7F,0xA2,0x48,0x25,0x2C,0x0F,0x6F,0xA1,0xD9,0xA7,0xB7,0x75, + 0xE1,0x1D,0xAD,0xCA,0xBB,0x3A,0xBF,0xA8,0x4D,0x93,0x8E,0xC3,0xF3,0x51,0x65,0xDC, + 0xD8,0x2D,0x6B,0x4C,0x10,0x77,0x6B,0xEC,0x4F,0x07,0x8C,0x5B,0x8B,0x9A,0x53,0xDC, + 0xF3,0x1C,0x17,0x10,0x42,0x42,0x29,0x14,0x0A,0xE7,0x4C,0xEF,0x04,0x95,0xA0,0x84, + 0x47,0xD2,0x2C,0x81,0xB4,0x37,0x53,0xD2,0x76,0x31,0x97,0xE1,0x11,0xB1,0xDE,0x83, + 0xE0,0xFC,0xA5,0x12,0x34,0x0C,0xBD,0x81,0x31,0xA9,0x6D,0xDC,0x7C,0xE6,0x79,0xC2, + 0x42,0xED,0x91,0xCA,0x26,0xD5,0x4C,0x30,0xA8,0x49,0x70,0x69,0xD5,0x4C,0x34,0x92, + 0xCB,0xC3,0xA4,0x52,0x70,0x2D,0xDD,0x5A,0xFB,0x22,0x00,0xD7,0x2D,0xA3,0x75,0xC1, + 0xED,0xE4,0x2A,0x3E,0x23,0xE6,0xBD,0x84,0xC4,0xCC,0xE8,0x49,0xE0,0xAE,0xCA,0x81, + 0x75,0xDB,0x87,0xEF,0xE9,0xE9,0x1E,0xA9,0xBE,0x40,0x0B,0x64,0x86,0x22,0xBA,0xAE, + 0x64,0x27,0xA9,0xFE,0x07,0xE5,0x69,0x8F,0x02,0x03,0x01,0x00,0x01,0xA3,0x75,0x30, + 0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30, + 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x5D, + 0xA6,0xDA,0xDF,0xA5,0x29,0x94,0xF6,0x34,0xA9,0xC5,0x46,0xA3,0xBB,0xBD,0x0A,0x00, + 0x0E,0xD4,0xFC,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0x03,0x99,0x06,0x5B,0xDA,0x2C,0xBA,0x9B,0x66,0x0A,0x5A,0x7B,0xAB,0x99,0xA5,0x7F, + 0x72,0xA9,0xD4,0xF7,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, + 0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x0D,0xCB,0x71,0x05,0x25,0x22,0xD7,0x9A, + 0xE9,0x74,0x9E,0x16,0x91,0x73,0x90,0x95,0x1D,0x52,0xA7,0xAB,0xDA,0xDF,0x40,0x7B, + 0x57,0x7D,0x0A,0x9A,0xE9,0x65,0x18,0xF7,0x94,0x2B,0x9E,0x88,0x30,0xD3,0x8E,0x2A, + 0xE6,0xC6,0x7E,0xF7,0xF7,0x1A,0xE0,0x9F,0x91,0xB5,0xD0,0x62,0xA1,0x5D,0xB7,0x6B, + 0x0E,0xC7,0x4E,0x44,0xCC,0x79,0x39,0x56,0xA0,0x2D,0x9E,0x43,0xC3,0xF7,0x26,0x8B, + 0x99,0xC8,0x0E,0x68,0x5D,0xBD,0x02,0xB5,0xB1,0x59,0xB5,0x0F,0xF0,0x58,0xF6,0x32, + 0x57,0x7D,0xD3,0xB6,0x4C,0x89,0x64,0x21,0xBB,0xB3,0x13,0x15,0xC0,0xDD,0xF7,0xB5, + 0x1C,0xD1,0x1F,0xF9,0xE0,0xE9,0xB6,0x7F,0x1D,0x60,0xDC,0x9F,0x07,0xE9,0x5C,0x42, + 0x02,0x9B,0x64,0x13,0x5D,0x75,0xB5,0x77,0x01,0xF6,0xF6,0x2D,0x02,0xA8,0x18,0x59, + 0x9C,0x38,0x35,0xBC,0x75,0x11,0xCC,0x56,0xF5,0x5A,0x01,0x73,0xA9,0x06,0x31,0xAC, + 0x12,0x0C,0x03,0xC2,0xF3,0x67,0x26,0xA4,0xB3,0x2D,0xA2,0x7A,0xE5,0x44,0xE2,0x4F, + 0x28,0x25,0x6C,0xB8,0xF2,0x52,0xAF,0xCE,0x72,0x47,0xE9,0xD6,0xD1,0xFD,0x6B,0xFB, + 0x94,0x28,0xA8,0x82,0x85,0x49,0x8B,0xBC,0xB5,0x7B,0x93,0xCF,0x2D,0x29,0xE1,0x0C, + 0x5B,0xAF,0x3C,0xEC,0xED,0x78,0xDC,0x24,0x56,0x5C,0xC8,0xF4,0x47,0xBC,0x63,0xA3, + 0x37,0xF9,0x9C,0x92,0xF5,0xD3,0xAD,0x71,0xEC,0x43,0xE9,0x0B,0xDC,0xB5,0x9F,0x03, + 0x44,0x55,0x12,0x1D,0x39,0xF3,0x8C,0xAE,0x59,0x15,0xC1,0x12,0xAF,0xC1,0x02,0x95, + 0x62,0x7D,0x56,0xF0,0x93,0x47,0x5A,0x50, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Leaf 2 */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=512-bit Test SubCA */ +unsigned char _leaf2048B[803]={ + 0x30,0x82,0x03,0x1F,0x30,0x82,0x02,0xC9,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4E, + 0xBF,0xB9,0x68,0xC8,0x8C,0x3A,0xE1,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x74,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A, + 0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03, + 0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72, + 0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31, + 0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x35,0x31,0x32,0x2D,0x62,0x69, + 0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x30,0x1E,0x17,0x0D, + 0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x31,0x39,0x33,0x34,0x5A,0x17,0x0D,0x31, + 0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x31,0x39,0x33,0x34,0x5A,0x30,0x76,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x03,0x0C,0x14, + 0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x4C,0x65, + 0x61,0x66,0x20,0x32,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,0xD3,0x79,0xB9,0x77,0x2A,0x76,0x17,0xEE,0xD1,0x4E,0x6D, + 0x6B,0x9F,0x42,0xAA,0xDE,0x81,0x47,0xC5,0x2B,0x43,0x3A,0x4F,0xB9,0x42,0x5E,0x5A, + 0x35,0xDE,0xF5,0x86,0x8C,0x0E,0xD1,0xC3,0x7B,0xA2,0x82,0x52,0x33,0xA0,0x2B,0x8C, + 0x58,0x04,0x75,0x8E,0xFB,0x08,0x9B,0xA7,0xEA,0x66,0x86,0xFA,0x5E,0xC2,0xCC,0x21, + 0x6C,0x17,0xC3,0x6B,0x05,0xFE,0x33,0x21,0x51,0x18,0xA1,0x0A,0xDD,0x5F,0xCE,0xF2, + 0xF6,0xB6,0x82,0x6C,0xBB,0x26,0x68,0x76,0xC3,0x16,0xEB,0x35,0x78,0x79,0x03,0xB0, + 0x36,0xC5,0x7D,0xDF,0x5C,0x38,0xB6,0xF0,0xD1,0xE0,0x9D,0x71,0xFB,0xA8,0x1B,0x83, + 0x9D,0x30,0xBC,0x2D,0x09,0x4D,0x9F,0xF4,0x69,0x33,0x99,0xE5,0xE9,0x76,0x6B,0x78, + 0x71,0xA7,0x13,0xF4,0xFB,0x2A,0x24,0x4D,0xD0,0x54,0x6E,0xAE,0x19,0xEE,0xCB,0x43, + 0x8C,0x3F,0x90,0x0F,0xDC,0xFE,0xA4,0xFF,0x8A,0xAD,0x22,0x21,0x61,0x51,0xAA,0x76, + 0x66,0x43,0xC0,0xE5,0x42,0x94,0x0F,0xBE,0x3C,0x89,0x45,0x50,0x0D,0x4F,0xDC,0x19, + 0xEF,0xF8,0x19,0xB6,0x7E,0x42,0xBD,0x88,0xA3,0x65,0x59,0xE8,0x7A,0xC1,0x7F,0x32, + 0x15,0x38,0xA3,0x58,0xC4,0x25,0x74,0xFC,0x02,0x8C,0xFC,0x31,0x28,0x20,0x05,0xAD, + 0x9B,0x27,0xE5,0x25,0x81,0x63,0x92,0xE1,0x49,0x55,0x5B,0xD7,0x36,0x3E,0xC4,0x2F, + 0x98,0x23,0xAA,0x62,0x85,0x68,0x4C,0x2D,0xEA,0x46,0xD6,0x99,0xCE,0x61,0x7C,0xE7, + 0x18,0x0B,0x72,0x5E,0xA0,0x06,0x49,0x6E,0x1C,0x31,0x0F,0x61,0x3F,0x62,0x68,0xC0, + 0x89,0xC8,0x91,0x45,0xAD,0x02,0x03,0x01,0x00,0x01,0xA3,0x75,0x30,0x73,0x30,0x0C, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03, + 0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03, + 0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03, + 0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x81,0x88,0xF3,0xCE, + 0xC9,0x31,0x5E,0x77,0x3C,0x27,0x4E,0x5E,0x4A,0xE6,0xEA,0x06,0x7A,0xEA,0x32,0x43, + 0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x9E,0x85,0x9A, + 0xA5,0x88,0x09,0xB0,0x93,0x9B,0xB4,0xE5,0xCE,0x68,0x99,0x93,0xE9,0x79,0xE9,0x7C, + 0x98,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00, + 0x03,0x41,0x00,0x39,0x1A,0x27,0x7C,0xDB,0x9C,0xE7,0x83,0x5F,0x57,0x69,0x4D,0xAD, + 0xD5,0x98,0xBA,0xA8,0x56,0x54,0x8D,0x84,0x18,0xB0,0xAF,0xEA,0x4B,0x74,0xB7,0x87, + 0xDC,0xD8,0x1E,0x10,0x10,0xE3,0x73,0xC1,0x90,0x83,0x9F,0xB8,0xF4,0x41,0x03,0x02, + 0x49,0xF7,0x57,0x5C,0x7D,0x03,0xE9,0x9E,0x57,0xF4,0xBC,0x74,0x3A,0xC0,0x9B,0xFF, + 0x20,0x73,0xC7, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=512-bit Test Leaf */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test SubCA 2 */ +unsigned char _leaf512[798]={ + 0x30,0x82,0x03,0x1A,0x30,0x82,0x02,0x02,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x14,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x77,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30,0x34,0x38,0x2D, + 0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32, + 0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x32,0x30,0x30,0x38, + 0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x32,0x30,0x30,0x38,0x5A, + 0x30,0x73,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41, + 0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1A,0x30,0x18,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x11,0x35,0x31,0x32,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74, + 0x20,0x4C,0x65,0x61,0x66,0x30,0x5C,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x4B,0x00,0x30,0x48,0x02,0x41,0x00,0xEB,0x34, + 0xD8,0x83,0x6D,0xFE,0xDD,0x09,0x27,0xC1,0xA1,0xA7,0x1F,0x9D,0xA8,0xDF,0x55,0xDE, + 0x54,0x03,0x3D,0x42,0x54,0x24,0x3D,0x92,0x8B,0x21,0x4B,0xEE,0x8C,0x2B,0x9C,0x3F, + 0x34,0xD1,0x6B,0xDE,0xC0,0xC2,0x20,0x06,0x87,0x9B,0x11,0x96,0x8C,0xB5,0x24,0xDD, + 0x93,0xE6,0x1B,0x77,0xC1,0x7A,0xD0,0x1F,0xD2,0x09,0x3D,0x21,0x8A,0x15,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x75,0x30,0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01, + 0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04, + 0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A, + 0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D, + 0x0E,0x04,0x16,0x04,0x14,0xAE,0x83,0x56,0x29,0x05,0x75,0x48,0xB2,0x2F,0x0D,0x92, + 0x26,0x21,0xC2,0x7C,0x34,0x48,0xF7,0xAC,0xAF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23, + 0x04,0x18,0x30,0x16,0x80,0x14,0x0C,0x3F,0x97,0x58,0x60,0x67,0x21,0xC9,0xDB,0xD4, + 0x23,0x58,0x60,0x8E,0xC1,0x3F,0x99,0x9F,0x12,0x78,0x30,0x0D,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x85,0xEC, + 0xC6,0xA7,0x1B,0x36,0x62,0x3A,0x04,0xBB,0xE8,0x8F,0xE2,0x66,0x8E,0xD4,0x02,0x97, + 0x6C,0x29,0x27,0xFF,0xC8,0xC6,0xBC,0xFE,0x9D,0xBC,0x09,0x8C,0x6B,0x0B,0x1E,0x48, + 0x82,0x46,0xBD,0xCF,0x02,0xB7,0x59,0x6E,0x7A,0xFC,0x8C,0x58,0x03,0x6A,0x92,0x4A, + 0xB0,0x1F,0x2E,0x6F,0x78,0x84,0x10,0x54,0xA9,0x70,0x65,0xDD,0xA2,0xAA,0xAA,0xFA, + 0x59,0x98,0xD7,0x42,0x60,0x42,0x15,0x2C,0x11,0x48,0xDE,0xF6,0x76,0x91,0x5C,0x2B, + 0x0B,0xEF,0x5F,0x23,0x61,0x8A,0x4E,0x81,0x82,0x3F,0xDA,0x9E,0x02,0xAF,0x82,0xDD, + 0x43,0x94,0x08,0xD1,0xA0,0x31,0x98,0x14,0x4C,0xBD,0x5E,0xFA,0x73,0xDC,0x0A,0x72, + 0xA4,0xB0,0x78,0x8A,0xC6,0xFE,0xBB,0x5A,0xBF,0x78,0x32,0x8D,0x26,0x7B,0xA3,0xBD, + 0x06,0x45,0x93,0xC6,0x96,0x99,0x14,0x8C,0x69,0xD1,0x52,0xDC,0xD4,0x1C,0x3E,0xCB, + 0x91,0x46,0x92,0x1B,0xBE,0x21,0xEC,0x21,0xE2,0xB9,0x23,0xD5,0xB0,0xAD,0x42,0xFA, + 0x9A,0x91,0xA4,0xA1,0x48,0x4D,0x94,0xB5,0xCF,0x14,0x21,0xA4,0x8E,0x18,0x2E,0x78, + 0x93,0xA0,0xED,0x43,0x15,0x92,0x68,0x57,0x78,0x52,0x28,0xEB,0x4A,0x48,0x79,0xEF, + 0x17,0xD3,0xD5,0xAD,0x2F,0x8A,0xF4,0xD2,0x21,0x79,0x08,0x08,0x66,0xE1,0x54,0x7F, + 0xFC,0x3D,0x5D,0x81,0xD8,0xA8,0x47,0xC3,0x3B,0xE9,0x52,0x77,0x05,0xF2,0x42,0xDE, + 0x23,0x24,0x99,0x7A,0x20,0x49,0x86,0x49,0x04,0x60,0x77,0xBD,0xD5,0x33,0xBB,0x49, + 0x61,0x8B,0x1C,0xBB,0x8E,0xE8,0x1D,0xA4,0x1E,0xA4,0x21,0x77,0x59,0xBD, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=1024-bit Test Leaf */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test SubCA 2 */ +unsigned char _leaf1024[867]={ + 0x30,0x82,0x03,0x5F,0x30,0x82,0x02,0x47,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x15,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x77,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30,0x34,0x38,0x2D, + 0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32, + 0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x32,0x30,0x32,0x32, + 0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x32,0x30,0x32,0x32,0x5A, + 0x30,0x74,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41, + 0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1B,0x30,0x19,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x12,0x31,0x30,0x32,0x34,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73, + 0x74,0x20,0x4C,0x65,0x61,0x66,0x30,0x81,0x9F,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48, + 0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8D,0x00,0x30,0x81,0x89,0x02, + 0x81,0x81,0x00,0xCA,0xCD,0xBD,0x1E,0xA5,0xF1,0xDC,0x50,0x7F,0xF6,0x52,0x96,0x56, + 0x1F,0xD9,0x9A,0x3F,0x32,0xED,0x45,0x29,0xCE,0x2C,0x18,0xA4,0x3E,0xA6,0x92,0xDF, + 0x8E,0x33,0x76,0x4D,0xCB,0xDB,0xD9,0x5E,0x83,0x32,0x96,0x19,0x8B,0x62,0xFE,0x67, + 0xBB,0xE6,0xC0,0x3D,0x1A,0xEF,0xE4,0x19,0x40,0x8B,0x26,0x80,0xD9,0x22,0x8A,0x1E, + 0xDF,0xC6,0x79,0x2C,0x07,0x7C,0xD7,0x10,0x91,0x7E,0x0F,0xC5,0x5E,0x69,0xC3,0xEB, + 0x1F,0x34,0x50,0x4D,0xA5,0xE1,0xF6,0x3A,0x6C,0xF0,0xD4,0x21,0x20,0x5C,0x0A,0x68, + 0xC1,0x26,0x4B,0x4A,0x79,0x08,0x64,0x67,0xDE,0x1E,0x17,0xC5,0xE4,0xEE,0xA6,0xE3, + 0xC4,0x54,0x34,0x7C,0xFE,0x82,0x5B,0xE4,0xAB,0xAF,0x97,0x2C,0x6B,0xAC,0x02,0x11, + 0xF3,0xD9,0x67,0x02,0x03,0x01,0x00,0x01,0xA3,0x75,0x30,0x73,0x30,0x0C,0x06,0x03, + 0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06,0x03,0x55,0x1D, + 0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55,0x1D, + 0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xB9,0xC9,0xD8,0x19,0xA6,0x69, + 0x3A,0x16,0x2E,0x32,0x2B,0x9A,0x10,0xB6,0xFA,0x20,0x93,0x16,0x7E,0xBC,0x30,0x1F, + 0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x0C,0x3F,0x97,0x58,0x60, + 0x67,0x21,0xC9,0xDB,0xD4,0x23,0x58,0x60,0x8E,0xC1,0x3F,0x99,0x9F,0x12,0x78,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0xA6,0x0A,0xB5,0x39,0x4B,0xA9,0xED,0x9B,0x8C,0xC5,0x5D,0xF1,0xAA, + 0x9D,0x57,0x55,0x5C,0xF2,0x10,0x29,0xBD,0x56,0x36,0xEF,0x52,0xDC,0xEA,0x27,0xF9, + 0xA2,0x79,0xBB,0xE6,0x16,0x29,0xA4,0x90,0x31,0x26,0x24,0x8A,0x79,0xBE,0x36,0xFC, + 0xA9,0xEF,0x77,0x13,0x16,0xA3,0x55,0xEB,0xD1,0x1A,0xD8,0xE2,0x16,0x72,0x5F,0x7D, + 0x10,0x76,0x3B,0x9A,0x00,0x51,0xAC,0x5A,0x4E,0x05,0xA3,0x82,0x1D,0xAB,0xC1,0x5E, + 0x44,0xD8,0xA0,0x95,0xD1,0xB5,0x75,0xE6,0x3B,0xB2,0x20,0xFB,0xBB,0xB9,0x88,0xD5, + 0x27,0x3B,0x90,0xA6,0xF0,0x6D,0x80,0xC8,0xA3,0x3A,0x3D,0x33,0x8F,0x14,0x09,0x5D, + 0xBB,0xA0,0xD7,0x3D,0x10,0xE9,0x8D,0x0E,0xB4,0x51,0x42,0xD3,0xB3,0xEF,0xC2,0xF2, + 0x0B,0x35,0x35,0x5D,0x7B,0xE1,0x47,0x9E,0x90,0xF9,0x14,0xDD,0xDD,0x1E,0x5F,0xDC, + 0xAB,0x04,0x08,0x8A,0x6B,0x82,0x2F,0xCA,0xA6,0x37,0x07,0x4C,0x94,0xD5,0x4F,0x83, + 0x67,0xEF,0xE2,0x12,0xDB,0x71,0x69,0x5A,0x33,0x8E,0x32,0x90,0xDE,0xE7,0x8C,0x6E, + 0x64,0xFD,0x8E,0x09,0xDA,0xBD,0x08,0xBE,0xC1,0x6F,0xD0,0x30,0xDD,0x18,0xDB,0xD1, + 0x34,0x7D,0x86,0x69,0xD7,0x57,0xE4,0x70,0x7F,0xF8,0x49,0xC0,0x4B,0xE4,0x73,0xE1, + 0x29,0x26,0x5E,0x04,0xDC,0xC6,0x69,0x17,0xDF,0x62,0x20,0xE1,0x15,0xAB,0xDD,0x1B, + 0x0C,0xD7,0xA6,0x1C,0x2C,0x7B,0xD9,0x2D,0xDE,0x46,0x43,0x81,0xFA,0xD9,0x11,0xDD, + 0xE8,0x4B,0x6A,0x31,0x85,0x24,0x0A,0xFD,0xAD,0x93,0xF6,0x50,0x2B,0x36,0xE5,0xE5, + 0x9E,0x8D,0x85, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test Leaf 3 */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=2048-bit Test SubCA 2 */ +unsigned char _leaf2048C[1001]={ + 0x30,0x82,0x03,0xE5,0x30,0x82,0x02,0xCD,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0x81,0x94,0x54,0x10,0xDC,0xA5,0x98,0x16,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86, + 0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x77,0x31,0x0B,0x30,0x09,0x06,0x03,0x55, + 0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C, + 0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x32,0x30,0x34,0x38,0x2D, + 0x62,0x69,0x74,0x20,0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32, + 0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x32,0x30,0x33,0x33, + 0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x32,0x30,0x33,0x33,0x5A, + 0x30,0x76,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31, + 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F, + 0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41, + 0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E, + 0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55, + 0x04,0x03,0x0C,0x14,0x32,0x30,0x34,0x38,0x2D,0x62,0x69,0x74,0x20,0x54,0x65,0x73, + 0x74,0x20,0x4C,0x65,0x61,0x66,0x20,0x33,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,0xC4,0xFE,0xE0,0xE5,0xC7,0x13,0x95, + 0x56,0x9E,0xA2,0x32,0xF5,0x52,0xD8,0xAA,0x06,0xF0,0x0F,0x2A,0x76,0xA8,0xCB,0xF3, + 0x39,0x5D,0x6E,0xEA,0x9C,0x4F,0x80,0xA1,0x9F,0xAC,0x8F,0x7D,0x34,0xDD,0x5D,0xD1, + 0x69,0xD9,0x2C,0x5D,0x49,0x2D,0x31,0x81,0x0D,0x2E,0x25,0xB7,0xA2,0x63,0x77,0xA1, + 0x58,0x8C,0x8D,0x2A,0x73,0x86,0xD8,0x15,0xFF,0xA9,0xED,0xF1,0xE6,0x08,0x7F,0x15, + 0x7B,0xFE,0xCC,0x07,0x7F,0xB7,0x63,0xA0,0x00,0x98,0xF0,0xBA,0x74,0x0C,0x34,0x2B, + 0xC4,0xE6,0xD6,0x2A,0xEE,0x7E,0x9D,0xBE,0xFD,0x34,0x70,0xCC,0x22,0x2C,0x2E,0x4F, + 0x81,0xC1,0xDA,0xB8,0x0B,0xC4,0xF9,0xFE,0xFD,0x74,0x47,0xE4,0xA9,0xA4,0x65,0x85, + 0x10,0x86,0x29,0x72,0x35,0x38,0x4B,0xD7,0xDA,0x3A,0x59,0xE7,0x8A,0x6D,0xC5,0x71, + 0x59,0x89,0xA5,0xC4,0xA3,0x9E,0xFC,0x81,0x18,0xD3,0x97,0x48,0xB2,0xDD,0xFE,0xB3, + 0xB3,0x78,0x71,0x35,0x3C,0x66,0x0F,0xD6,0xAA,0x84,0xF8,0xCB,0x87,0xB8,0xB4,0xFD, + 0x19,0x18,0x31,0xCC,0x53,0xB7,0x1B,0xB6,0x7D,0x99,0x9C,0x14,0x19,0xDA,0x84,0x72, + 0x88,0x21,0x9A,0x87,0x60,0x69,0xC3,0x8E,0x1F,0x34,0x3B,0xA3,0x56,0xA5,0x21,0xF0, + 0xDB,0xC1,0x54,0xEA,0x41,0x69,0x19,0x45,0x5E,0x52,0xB3,0x3A,0xBD,0x1A,0x8A,0x64, + 0x7B,0xA9,0xD4,0xF1,0x2B,0x58,0xCF,0x0D,0x7F,0x3C,0x86,0xDA,0x9A,0x94,0x42,0x36, + 0x6B,0x9F,0xD8,0xF4,0x64,0x18,0x66,0x6F,0xF7,0xB5,0x80,0xCE,0x43,0x8D,0x84,0x7A, + 0x99,0xE3,0x3D,0x03,0xB5,0x94,0x86,0xBD,0xEB,0x02,0x03,0x01,0x00,0x01,0xA3,0x75, + 0x30,0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00, + 0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0, + 0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01, + 0x05,0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14, + 0x50,0x25,0x7E,0xA7,0xF5,0x2B,0xA3,0x3A,0x35,0x31,0x82,0x4C,0xD6,0xA6,0x5F,0x04, + 0xC1,0x3A,0xAC,0x63,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80, + 0x14,0x0C,0x3F,0x97,0x58,0x60,0x67,0x21,0xC9,0xDB,0xD4,0x23,0x58,0x60,0x8E,0xC1, + 0x3F,0x99,0x9F,0x12,0x78,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, + 0x01,0x0B,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x7E,0xF7,0x12,0xE6,0x05,0x3B,0x13, + 0x4B,0x35,0xAD,0x63,0xCF,0x39,0xC7,0x9B,0x62,0x83,0xF6,0x52,0xCC,0x54,0x14,0x13, + 0x5D,0xD8,0xE3,0x1E,0x33,0x37,0x6F,0x3B,0x13,0x9F,0x23,0xBC,0xA0,0xAC,0xF3,0xA1, + 0x94,0x0C,0xE0,0x51,0xDE,0x08,0x56,0x8B,0x90,0x2E,0x4B,0xB1,0xCD,0x9B,0x1A,0x44, + 0x8E,0xB9,0x0B,0xA7,0x0B,0x5B,0xAC,0x7A,0x37,0xF7,0x71,0x27,0x4E,0xB8,0x15,0x09, + 0x70,0x10,0xAA,0x3C,0x61,0xC8,0x76,0x2A,0x2E,0x13,0x76,0xC9,0x2E,0xEE,0x98,0x75, + 0xF7,0x61,0x7D,0x8E,0x3C,0xFC,0x19,0xDE,0xAB,0xE5,0xDA,0xFE,0x30,0x00,0x45,0x13, + 0xE2,0x82,0x96,0x59,0xEE,0x02,0x5A,0x9B,0xFA,0x1B,0x4E,0x65,0xE0,0x75,0x8F,0x99, + 0x82,0xBD,0x2A,0x16,0x10,0xC2,0xA5,0xA2,0x1A,0xC0,0xF6,0x4A,0x42,0x46,0xBA,0x12, + 0xE0,0x64,0x7B,0x10,0x57,0xB6,0xFE,0xC3,0x46,0xCC,0x43,0xDC,0x69,0xF0,0x72,0x69, + 0x62,0xDB,0x0C,0x6E,0x21,0xF9,0xB4,0x59,0xD7,0xA3,0xFC,0x82,0x98,0x60,0x60,0x57, + 0x7F,0xDD,0x25,0x65,0xB7,0x04,0x3E,0xDA,0xA3,0x07,0x7C,0x69,0xAF,0x81,0xA9,0x49, + 0x81,0x09,0x62,0x71,0x51,0x4F,0x40,0x8F,0xE4,0x01,0x4C,0xAE,0xF4,0x9D,0xE0,0x38, + 0xB1,0x20,0xF0,0x5D,0x1C,0xA0,0xB4,0x31,0xBF,0xE7,0xC7,0xFE,0xFF,0xA5,0x81,0xFB, + 0x8E,0xEE,0x19,0xB1,0xF1,0x64,0x44,0x3D,0xDA,0x71,0xE3,0x80,0x58,0xFB,0x23,0x6E, + 0xAE,0x3B,0x69,0x64,0x37,0x82,0x54,0xD6,0xEA,0xD4,0x02,0xD9,0x27,0x1A,0x9F,0xCE, + 0x0D,0x44,0xA9,0x29,0x07,0x8C,0x76,0x0A,0xCB, +}; + +// MARK: EC Key Size Test Certs + +/* EC Key Size Test Cert Chains + * _root384 -> _int384B -> _leaf128 + * _root384 -> _int384B -> _leaf192 + * _root384 -> _int384B -> _leaf384C + */ + +/* subject:/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test Root CA */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test Root CA */ +unsigned char _root384[662]={ + 0x30,0x82,0x02,0x92,0x30,0x82,0x02,0x18,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0x9B,0x8A,0xBF,0x1F,0x3B,0x4D,0xCC,0x76,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x04,0x01,0x30,0x81,0x8C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E, + 0x67,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70, + 0x33,0x38,0x34,0x72,0x31,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x30,0x33,0x30,0x34, + 0x32,0x35,0x5A,0x17,0x0D,0x32,0x35,0x31,0x32,0x31,0x35,0x30,0x33,0x30,0x34,0x32, + 0x35,0x5A,0x30,0x81,0x8C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02, + 0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C, + 0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x07, + 0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x14,0x30,0x12,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63, + 0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75, + 0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67, + 0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70,0x33, + 0x38,0x34,0x72,0x31,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43, + 0x41,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x05, + 0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0xFE,0xE3,0x68,0x79,0x40,0x81,0x4D, + 0xC3,0xAA,0x9F,0x1D,0x9D,0x03,0x33,0x5F,0x39,0x4D,0xFD,0x4E,0x7E,0xC3,0xC2,0x9D, + 0xB4,0x61,0x98,0x8D,0x02,0xA9,0xA0,0xA7,0x4E,0x49,0xE8,0xFE,0xAD,0x1D,0x6B,0x7D, + 0xAF,0xDA,0x55,0xF5,0xD2,0x8E,0x5F,0x2F,0x0E,0x55,0x50,0x61,0x07,0x81,0xE6,0xDF, + 0xD5,0xD1,0xA5,0x21,0xA9,0x78,0x38,0xC5,0x75,0x76,0x06,0x54,0x67,0xC7,0xD1,0x00, + 0x37,0xD2,0x65,0x52,0xB6,0x28,0xA0,0x5D,0x76,0x32,0xF0,0x48,0xAC,0x86,0x8B,0x5B, + 0x90,0x08,0xE4,0xD3,0xCA,0xF0,0xE8,0x0E,0x45,0xA3,0x45,0x30,0x43,0x30,0x12,0x06, + 0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x08,0x30,0x06,0x01,0x01,0xFF,0x02,0x01, + 0x03,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01, + 0x06,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x86,0xC8,0x90,0xD5, + 0xD7,0x5C,0x3A,0xE1,0x29,0xF4,0x13,0x54,0xD0,0x06,0x90,0xAA,0xEC,0xF8,0x97,0xF7, + 0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03,0x69,0x00,0x30,0x66, + 0x02,0x31,0x00,0xE3,0xE1,0x9C,0xB4,0xEE,0x40,0x25,0x9A,0x82,0x3F,0x0A,0x03,0x55, + 0xDC,0x52,0x7D,0x3B,0xFC,0xC2,0x1A,0x05,0x97,0xEF,0x3F,0xA0,0x63,0x49,0x8A,0x00, + 0x38,0x72,0x05,0xDB,0x74,0x9C,0xED,0x68,0x8E,0x03,0xB8,0x6B,0x36,0x11,0x2C,0x77, + 0xA3,0xB8,0x7C,0x02,0x31,0x00,0xA9,0xB5,0x88,0xB6,0x3A,0x85,0x55,0x2E,0x69,0x56, + 0x8D,0xC4,0x5B,0x24,0xD2,0x8A,0x0E,0x01,0xA9,0x0E,0xC1,0x4D,0xDB,0x39,0xE9,0x9C, + 0x16,0x49,0xEE,0xD8,0x50,0xC0,0x1E,0x02,0xD4,0x5C,0x8B,0x07,0xD1,0xA5,0x74,0xE3, + 0x6F,0x62,0xC8,0x32,0x40,0x1D, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test SubCA 2 */ +/* issuer :/C=US/ST=California/L=Cupertino/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test Root CA */ +unsigned char _int384B[671]={ + 0x30,0x82,0x02,0x9B,0x30,0x82,0x02,0x21,0xA0,0x03,0x02,0x01,0x02,0x02,0x09,0x00, + 0xFE,0xE6,0x21,0x31,0x73,0x83,0x11,0xBA,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE, + 0x3D,0x04,0x01,0x30,0x81,0x8C,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61, + 0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04, + 0x07,0x0C,0x09,0x43,0x75,0x70,0x65,0x72,0x74,0x69,0x6E,0x6F,0x31,0x14,0x30,0x12, + 0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E, + 0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63, + 0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E, + 0x67,0x31,0x1F,0x30,0x1D,0x06,0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70, + 0x33,0x38,0x34,0x72,0x31,0x20,0x54,0x65,0x73,0x74,0x20,0x52,0x6F,0x6F,0x74,0x20, + 0x43,0x41,0x30,0x1E,0x17,0x0D,0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x32,0x31,0x32, + 0x31,0x38,0x5A,0x17,0x0D,0x31,0x36,0x31,0x32,0x31,0x36,0x32,0x32,0x31,0x32,0x31, + 0x38,0x5A,0x30,0x78,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1F,0x30,0x1D,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70,0x33,0x38,0x34,0x72,0x31,0x20, + 0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32,0x30,0x76,0x30,0x10, + 0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x22, + 0x03,0x62,0x00,0x04,0x08,0xAE,0xF2,0x28,0x6E,0x8C,0xE8,0x16,0x01,0x86,0x37,0xFE, + 0xFD,0x17,0xA5,0x37,0x30,0xD2,0x55,0xDB,0x4C,0x6D,0xE5,0xAF,0x63,0xBD,0x5F,0xB5, + 0x6E,0xDB,0x66,0xB3,0x2C,0xA0,0xD1,0x6B,0xC2,0x82,0x28,0xBB,0xEF,0xD7,0xFE,0xA1, + 0x3D,0x5A,0x00,0x56,0xFD,0xD2,0x28,0x36,0x8D,0xEE,0xFC,0x3F,0x58,0xFE,0x5D,0x0C, + 0x82,0xE8,0x7F,0x0D,0x89,0xEE,0x4A,0xC1,0xF7,0xF3,0xB3,0x64,0xF7,0xB9,0x58,0xD6, + 0x76,0x62,0x67,0x52,0x9B,0xDA,0x19,0xDA,0xD3,0xCA,0x55,0xF9,0xBD,0xBD,0x38,0x4E, + 0x23,0xA5,0xF8,0xA9,0xA3,0x63,0x30,0x61,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01, + 0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x02,0x04,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E, + 0x04,0x16,0x04,0x14,0xD8,0xEA,0x0F,0xE6,0x82,0x91,0x5F,0xC4,0xA1,0x59,0x2B,0xBC, + 0xB4,0x63,0x42,0xAF,0x57,0xCC,0xBC,0x79,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04, + 0x18,0x30,0x16,0x80,0x14,0x86,0xC8,0x90,0xD5,0xD7,0x5C,0x3A,0xE1,0x29,0xF4,0x13, + 0x54,0xD0,0x06,0x90,0xAA,0xEC,0xF8,0x97,0xF7,0x30,0x09,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x04,0x01,0x03,0x69,0x00,0x30,0x66,0x02,0x31,0x00,0xBD,0x7D,0x2C,0x3A, + 0xC6,0xE6,0xA7,0xDB,0x73,0xA2,0x36,0x13,0x38,0xC4,0x17,0x71,0x35,0x41,0x23,0xC7, + 0xCC,0xF1,0x9E,0x89,0x97,0x1F,0xD7,0xFC,0x58,0x9D,0x50,0x2D,0x0B,0xD9,0x33,0xD5, + 0x7E,0xB4,0xD8,0x43,0xCF,0xDB,0x0A,0xBE,0xBE,0x44,0xDF,0x10,0x02,0x31,0x00,0xFD, + 0xE3,0x32,0x58,0x06,0x7D,0xA1,0x7B,0x1F,0x22,0x85,0x82,0x54,0xD9,0xB0,0x36,0x4A, + 0x2E,0x0B,0x24,0xA6,0x9B,0xBD,0x15,0x76,0xDB,0xAC,0xD4,0x97,0x91,0x64,0x11,0xFE, + 0x47,0x11,0x59,0xBC,0xAF,0x1C,0x5A,0x16,0xF8,0x2E,0x0B,0x46,0x2C,0xD7,0x6E, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=secp128r1 Test Leaf */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test SubCA 2 */ +unsigned char _leaf128[599]={ + 0x30,0x82,0x02,0x53,0x30,0x82,0x01,0xDA,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x49, + 0xF9,0xF0,0x5F,0xA0,0x17,0xBD,0x2F,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x01,0x30,0x78,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1F,0x30,0x1D,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70,0x33,0x38,0x34,0x72,0x31,0x20, + 0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32,0x30,0x1E,0x17,0x0D, + 0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x32,0x32,0x33,0x34,0x5A,0x17,0x0D,0x31, + 0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x32,0x32,0x33,0x34,0x5A,0x30,0x75,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1C,0x30,0x1A,0x06,0x03,0x55,0x04,0x03,0x0C,0x13, + 0x73,0x65,0x63,0x70,0x31,0x32,0x38,0x72,0x31,0x20,0x54,0x65,0x73,0x74,0x20,0x4C, + 0x65,0x61,0x66,0x30,0x36,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, + 0x06,0x05,0x2B,0x81,0x04,0x00,0x1C,0x03,0x22,0x00,0x04,0xB1,0x4F,0xBB,0xCA,0x19, + 0xDD,0x23,0xF4,0x58,0xC2,0xDF,0x70,0x7A,0x46,0xB4,0xC9,0x22,0x71,0xF6,0x4D,0x1D, + 0xDA,0x4C,0x0F,0x62,0x68,0x14,0x42,0xA7,0x77,0x8F,0xC6,0xA3,0x75,0x30,0x73,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06, + 0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07, + 0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0x56,0x3C,0xD0, + 0xEF,0xEF,0x08,0x74,0x41,0xD8,0xAB,0x26,0x21,0xD7,0xD9,0x6A,0xED,0xE1,0x1B,0x54, + 0xF2,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xD8,0xEA, + 0x0F,0xE6,0x82,0x91,0x5F,0xC4,0xA1,0x59,0x2B,0xBC,0xB4,0x63,0x42,0xAF,0x57,0xCC, + 0xBC,0x79,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03,0x68,0x00, + 0x30,0x65,0x02,0x31,0x00,0xFD,0x13,0x19,0x07,0xFB,0xD1,0x1B,0x3A,0xB1,0x82,0x2D, + 0xA0,0x16,0xEE,0xAD,0x0B,0xCF,0x19,0x65,0x49,0x64,0xCE,0x03,0x04,0x32,0xD9,0x1F, + 0xD2,0xC7,0x0A,0x43,0xD8,0xB9,0x9B,0x74,0x41,0x1A,0x20,0xAA,0xB3,0x2A,0xA8,0x71, + 0xAC,0x65,0x73,0xBE,0xD1,0x02,0x30,0x2D,0x0D,0xFC,0x08,0x2E,0x9A,0x61,0xA3,0xB6, + 0x55,0x72,0x4A,0x26,0x73,0xE3,0xA2,0x1A,0xE4,0x64,0x1C,0x44,0x93,0x5B,0xF8,0x93, + 0xBB,0x42,0x2E,0x01,0xC9,0xAF,0xE1,0x98,0x04,0x8B,0x8C,0xC1,0x9F,0x2B,0x37,0x54, + 0x4B,0x55,0xC9,0xF2,0x3F,0x6F,0x5E, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=prime192v1 Test Leaf */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test SubCA 2 */ +unsigned char _leaf192[619]={ + 0x30,0x82,0x02,0x67,0x30,0x82,0x01,0xEE,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x49, + 0xF9,0xF0,0x5F,0xA0,0x17,0xBD,0x30,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x01,0x30,0x78,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1F,0x30,0x1D,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70,0x33,0x38,0x34,0x72,0x31,0x20, + 0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32,0x30,0x1E,0x17,0x0D, + 0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x32,0x32,0x34,0x33,0x5A,0x17,0x0D,0x31, + 0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x32,0x32,0x34,0x33,0x5A,0x30,0x76,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x03,0x0C,0x14, + 0x70,0x72,0x69,0x6D,0x65,0x31,0x39,0x32,0x76,0x31,0x20,0x54,0x65,0x73,0x74,0x20, + 0x4C,0x65,0x61,0x66,0x30,0x49,0x30,0x13,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x02, + 0x01,0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01,0x03,0x32,0x00,0x04,0x29, + 0x68,0x3F,0x3A,0xC9,0x63,0xDD,0x0F,0xC9,0x1A,0x4B,0x94,0x5C,0xEE,0x2C,0x41,0x42, + 0xE0,0x35,0x9B,0xA9,0x93,0x03,0x8C,0xB7,0x2A,0xC5,0x96,0x8D,0x33,0x94,0x90,0x58, + 0x78,0x5F,0xA4,0xFE,0x93,0x96,0x89,0x4D,0x50,0xB6,0xB8,0x78,0x40,0xC5,0xBA,0xA3, + 0x75,0x30,0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30, + 0x00,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05, + 0xA0,0x30,0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x69,0x6E,0x52,0x27,0xD9,0x64,0x18,0x47,0x7F,0x23,0xF7,0xFB,0xF6,0x07,0x48, + 0xDD,0x0E,0x48,0x0D,0xC3,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16, + 0x80,0x14,0xD8,0xEA,0x0F,0xE6,0x82,0x91,0x5F,0xC4,0xA1,0x59,0x2B,0xBC,0xB4,0x63, + 0x42,0xAF,0x57,0xCC,0xBC,0x79,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04, + 0x01,0x03,0x68,0x00,0x30,0x65,0x02,0x31,0x00,0xC3,0x36,0x26,0x00,0x44,0x7B,0xEE, + 0xAA,0x4A,0x13,0xA5,0x64,0x8A,0x6B,0x40,0x91,0x43,0x3A,0x4E,0x3C,0xDF,0x28,0x59, + 0x12,0x86,0xB1,0x45,0x34,0x23,0xAE,0x8B,0x6D,0x91,0x7D,0xFB,0x0E,0x15,0xF9,0xC9, + 0xFB,0x52,0x96,0xBA,0x0B,0xBE,0x84,0xAC,0x58,0x02,0x30,0x5C,0x21,0x90,0x17,0x18, + 0x38,0xA3,0x40,0xAF,0x53,0x76,0x88,0x4B,0x22,0x97,0x5E,0x54,0xF2,0x98,0x0F,0xB5, + 0x61,0x4C,0x10,0x44,0x53,0xFC,0xB6,0x6E,0xF3,0x9E,0x2C,0x4B,0x3B,0xAC,0xC8,0x90, + 0xBF,0xAE,0xEC,0xC7,0x62,0xFE,0x2F,0xAF,0x1A,0x90,0x35, +}; + +/* subject:/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test Leaf 3 */ +/* issuer :/C=US/ST=California/O=Apple, Inc./OU=Security Engineering/CN=secp384r1 Test SubCA 2 */ +unsigned char _leaf384C[665]={ + 0x30,0x82,0x02,0x95,0x30,0x82,0x02,0x1C,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x49, + 0xF9,0xF0,0x5F,0xA0,0x17,0xBD,0x31,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x04,0x01,0x30,0x78,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, + 0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69, + 0x66,0x6F,0x72,0x6E,0x69,0x61,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C, + 0x0B,0x41,0x70,0x70,0x6C,0x65,0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20, + 0x45,0x6E,0x67,0x69,0x6E,0x65,0x65,0x72,0x69,0x6E,0x67,0x31,0x1F,0x30,0x1D,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x16,0x73,0x65,0x63,0x70,0x33,0x38,0x34,0x72,0x31,0x20, + 0x54,0x65,0x73,0x74,0x20,0x53,0x75,0x62,0x43,0x41,0x20,0x32,0x30,0x1E,0x17,0x0D, + 0x31,0x35,0x31,0x32,0x31,0x37,0x32,0x33,0x32,0x32,0x35,0x35,0x5A,0x17,0x0D,0x31, + 0x36,0x31,0x32,0x31,0x36,0x32,0x33,0x32,0x32,0x35,0x35,0x5A,0x30,0x77,0x31,0x0B, + 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x08,0x0C,0x0A,0x43,0x61,0x6C,0x69,0x66,0x6F,0x72,0x6E,0x69,0x61, + 0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0B,0x41,0x70,0x70,0x6C,0x65, + 0x2C,0x20,0x49,0x6E,0x63,0x2E,0x31,0x1D,0x30,0x1B,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x14,0x53,0x65,0x63,0x75,0x72,0x69,0x74,0x79,0x20,0x45,0x6E,0x67,0x69,0x6E,0x65, + 0x65,0x72,0x69,0x6E,0x67,0x31,0x1E,0x30,0x1C,0x06,0x03,0x55,0x04,0x03,0x0C,0x15, + 0x73,0x65,0x63,0x70,0x33,0x38,0x34,0x72,0x31,0x20,0x54,0x65,0x73,0x74,0x20,0x4C, + 0x65,0x61,0x66,0x20,0x33,0x30,0x76,0x30,0x10,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D, + 0x02,0x01,0x06,0x05,0x2B,0x81,0x04,0x00,0x22,0x03,0x62,0x00,0x04,0x1F,0x62,0x07, + 0xBA,0x5D,0x2A,0x56,0xED,0x5D,0xE7,0x0B,0x18,0xDE,0x65,0x13,0xA4,0x31,0x53,0xFC, + 0x86,0x86,0xB4,0xC4,0x27,0x39,0x4D,0xD1,0x22,0xC2,0xFF,0x07,0x62,0xAB,0x64,0xDD, + 0xCC,0xEB,0x7F,0x08,0x12,0x78,0x20,0x90,0x40,0xD3,0xCF,0x45,0x71,0x98,0x6E,0x4E, + 0x93,0xC5,0x66,0x40,0x76,0xB0,0xAD,0xDB,0xD6,0xFA,0x9C,0x7F,0x46,0xF9,0xC9,0xDE, + 0xF5,0x41,0xA3,0x0C,0x7F,0x73,0xF3,0x0C,0x91,0xE1,0x0B,0xAD,0xBC,0xD5,0xD2,0xB1, + 0x6F,0xC3,0x1F,0x43,0x94,0x9C,0x18,0x5B,0xD9,0xE1,0x5A,0x84,0x2F,0xA3,0x75,0x30, + 0x73,0x30,0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30, + 0x0E,0x06,0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30, + 0x13,0x06,0x03,0x55,0x1D,0x25,0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05, + 0x05,0x07,0x03,0x02,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xB3, + 0xB5,0xC9,0x62,0x46,0xDD,0x1C,0x89,0x93,0xE3,0xAA,0x7C,0xEA,0x61,0x22,0x8B,0xF2, + 0x04,0x31,0x74,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14, + 0xD8,0xEA,0x0F,0xE6,0x82,0x91,0x5F,0xC4,0xA1,0x59,0x2B,0xBC,0xB4,0x63,0x42,0xAF, + 0x57,0xCC,0xBC,0x79,0x30,0x09,0x06,0x07,0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,0x03, + 0x68,0x00,0x30,0x65,0x02,0x30,0x33,0xE4,0xE8,0x8E,0x00,0x57,0xE4,0x53,0xCC,0xD4, + 0x04,0xF2,0xB6,0x7D,0xD5,0x14,0x5B,0xB2,0xBE,0x28,0xF8,0x5D,0x55,0x7A,0xB3,0x06, + 0x17,0x87,0xA9,0xAA,0x23,0xCE,0xAF,0x15,0xF3,0xE1,0xA8,0x9B,0xCF,0x06,0xC9,0x06, + 0x75,0x0C,0x13,0x12,0x40,0x32,0x02,0x31,0x00,0xE2,0x28,0x4A,0x28,0xA6,0x94,0x2C, + 0x8E,0x5A,0x13,0xCF,0x33,0xBB,0x6A,0x11,0x74,0x3A,0xED,0x3A,0x61,0x07,0x6D,0x49, + 0x84,0xBF,0xE2,0x1F,0xED,0x08,0x70,0x0F,0xCA,0x45,0xBA,0x68,0x1C,0xF3,0x15,0x7E, + 0xAB,0x41,0x0E,0xAB,0x84,0x29,0x33,0x87,0x3A, +}; diff --git a/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c b/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c index 3816cc9b..e28fcf59 100644 --- a/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c +++ b/OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c @@ -68,8 +68,6 @@ const char *create_db_sql = "CREATE INDEX iunwp ON keys(unwp);" "COMMIT;"; -void kc_dbhandle_reset(void); - #ifdef NO_SERVER static void ensureKeychainExists(void) { CFDictionaryRef query = CFDictionaryCreateForCFTypes(0, kSecClass,kSecClassInternetPassword, NULL); @@ -103,7 +101,7 @@ static void tests(void) "populate keychain"); free(keychain_name); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); diff --git a/OSX/sec/Security/Regressions/secitem/si-31-keychain-bad.c b/OSX/sec/Security/Regressions/secitem/si-31-keychain-bad.c index c2df5411..05fc5bb3 100644 --- a/OSX/sec/Security/Regressions/secitem/si-31-keychain-bad.c +++ b/OSX/sec/Security/Regressions/secitem/si-31-keychain-bad.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -52,8 +53,6 @@ const uint8_t keychain_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a }; -void kc_dbhandle_reset(void); - /* Test basic add delete update copy matching stuff. */ static void tests(void) { @@ -72,7 +71,7 @@ static void tests(void) (ssize_t)sizeof(keychain_data), "write garbage to keychain file"); ok_unix(close(fd), "close keychain file"); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); diff --git a/OSX/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c b/OSX/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c index 49bf6443..ecff54fc 100644 --- a/OSX/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c +++ b/OSX/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -45,8 +46,6 @@ static void ensureKeychainExists(void) { } #endif -void kc_dbhandle_reset(void); - /* Create an empty keychain file that can't be read or written and make sure securityd can deal with it. */ static void tests(void) @@ -67,7 +66,7 @@ static void tests(void) ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_name); ok_unix(close(fd), "close keychain file '%s'", keychain_name); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); diff --git a/OSX/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c b/OSX/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c index cafe5a14..4206fb84 100644 --- a/OSX/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c +++ b/OSX/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c @@ -867,14 +867,14 @@ static void tests(void) password = SecPasswordGenerate(kSecPasswordTypeWifi, &error, passwordRequirements); ok(password == NULL); ok(error != NULL); - + error = NULL; CFRelease(wrongCount); CFRelease(passwordRequirements); CFRelease(minRef); CFRelease(maxRef); CFRelease(allowedCharacters); - + password = CFSTR("Apple1?"); isnt(true, SecPasswordIsPasswordWeak(password)); CFRelease(password); @@ -1018,12 +1018,15 @@ static void tests(void) is(true, SecPasswordIsPasswordWeak2(true, CFSTR("666666"))); is(true, SecPasswordIsPasswordWeak2(true, CFSTR("123456"))); is(false, SecPasswordIsPasswordWeak2(true, CFSTR("666166"))); - + is(true, SecPasswordIsPasswordWeak2(true, CFSTR("525252"))); + is(true, SecPasswordIsPasswordWeak2(false, CFSTR("525252"))); + is(true, SecPasswordIsPasswordWeak2(false, CFSTR("52525"))); + } int si_73_secpasswordgenerate(int argc, char *const *argv) { - plan_tests(305); + plan_tests(308); tests(); return 0; diff --git a/OSX/sec/Security/Regressions/secitem/si-76-shared-credentials.c b/OSX/sec/Security/Regressions/secitem/si-76-shared-credentials.c index 23ea368b..368854f7 100644 --- a/OSX/sec/Security/Regressions/secitem/si-76-shared-credentials.c +++ b/OSX/sec/Security/Regressions/secitem/si-76-shared-credentials.c @@ -164,6 +164,9 @@ int si_76_shared_credentials(int argc, char *const *argv) #if !TARGET_OS_WATCH plan_tests(12); tests(); +#else + plan_tests(1); + ok_status(0); #endif return 0; } diff --git a/OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.c b/OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.c index e808f871..519a5ee5 100644 --- a/OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.c +++ b/OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.c @@ -50,14 +50,18 @@ static void tests(void) const void *v_certs[] = { cert0, cert1 }; CFArrayRef certs = CFArrayCreate(NULL, v_certs, sizeof(v_certs)/sizeof(*v_certs), &kCFTypeArrayCallBacks); CFArrayRef anchor_certs = CFArrayCreate(NULL, (const void**)&rootcert, 1, &kCFTypeArrayCallBacks); + + /* Set explicit verify date: 15 Dec 2015 */ + CFDateRef date = NULL; + isnt(date = CFDateCreate(NULL, 471907305.0), NULL, "Create verify date"); /* Create AppleTV VPN profile signing policy instance. */ isnt(policy = SecPolicyCreateAppleATVVPNProfileSigning(), NULL, "create policy"); /* Create trust reference. */ ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); - ok_status(SecTrustSetAnchorCertificates(trust, anchor_certs), "set anchor"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trustResult is kSecTrustResultUnspecified"); @@ -80,6 +84,7 @@ static void tests(void) isnt(policy = SecPolicyCreateAppleATVVPNProfileSigning(), NULL, "create policy"); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trustResult is kSecTrustResultRecoverableTrustFailure"); @@ -89,6 +94,9 @@ static void tests(void) CFReleaseSafe(certs); CFReleaseSafe(cert3); CFReleaseSafe(cert2); + CFReleaseSafe(anchor_certs); + CFReleaseSafe(rootcert); + CFReleaseSafe(date); } @@ -97,7 +105,7 @@ int si_88_sectrust_vpnprofile(int argc, char *const *argv); int si_88_sectrust_vpnprofile(int argc, char *const *argv) { - plan_tests(15); + plan_tests(18); tests(); diff --git a/OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.c b/OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.c new file mode 100644 index 00000000..d611bbfb --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.c @@ -0,0 +1,108 @@ +/* + * 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 +#include +#include +#include + +#include "Security_regressions.h" + +#include "si-89-cms-hash-agility.h" + + +static void tests(void) +{ + CFDataRef message = NULL, contentData = NULL, hashAgilityOid = NULL, hashAgilityValue = NULL; + SecPolicyRef policy = NULL; + SecTrustRef trust = NULL; + CFDictionaryRef attrs = NULL; + CFArrayRef attrValues = NULL; + CFDateRef signingTime = NULL, expectedTime = NULL; + + ok(message = CFDataCreate(NULL, valid_message, sizeof(valid_message)), "Create valid message"); + ok(contentData = CFDataCreate(NULL, content, sizeof(content)), "Create detached content"); + ok(policy = SecPolicyCreateBasicX509(), "Create policy"); + + /* verify the valid message and copy out attributes */ + is(SecCMSVerifyCopyDataAndAttributes(message, contentData, policy, &trust, NULL, &attrs), + errSecSuccess, "Verify valid CMS message and get attributes"); + isnt(attrs, NULL, "Copy CMS attributes"); + + /* verify we can get the parsed attribute */ + uint8_t appleHashAgilityOid[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x63, 0x64, 0x9, 0x1 }; + ok(hashAgilityOid = CFDataCreate(NULL, appleHashAgilityOid, sizeof(appleHashAgilityOid)), + "Create oid data"); + ok(attrValues = (CFArrayRef) CFDictionaryGetValue(attrs, hashAgilityOid), + "Get hash agility value array"); + is(CFArrayGetCount(attrValues), 1, "One attribute value"); + ok(hashAgilityValue = CFArrayGetValueAtIndex(attrValues, 0), "Get hash agility value"); + is((size_t)CFDataGetLength(hashAgilityValue), sizeof(attribute), "Verify size of parsed hash agility value"); + is(memcmp(attribute, CFDataGetBytePtr(hashAgilityValue), sizeof(attribute)), 0, + "Verify correct hash agility value"); + + attrValues = NULL; + + /*verify we can get the signing time attribute */ + ok(signingTime = (CFDateRef) CFDictionaryGetValue(attrs, kSecCMSSignDate), "Get signing time"); + ok(expectedTime = CFDateCreate(NULL, 468295000.0), "Set expected signing time"); + is(CFDateCompare(signingTime, expectedTime, NULL), 0, "Verify signing time"); + + CFReleaseNull(message); + + /* verify the invalid message */ + ok(message = CFDataCreate(NULL, invalid_message, sizeof(invalid_message)), "Create invalid message"); + is(SecCMSVerify(message, contentData, policy, &trust, NULL), errSecAuthFailed, + "Verify invalid CMS message"); + + CFReleaseNull(message); + + /* verify the valid message with no hash agility attribute */ + ok(message = CFDataCreate(NULL, valid_no_attr, sizeof(valid_no_attr)), + "Create valid message with no hash agility value"); + is(SecCMSVerifyCopyDataAndAttributes(message, contentData, policy, &trust, NULL, &attrs), + errSecSuccess, "Verify 2nd valid CMS message and get attributes"); + isnt(attrs, NULL, "Copy 2nd CMS attributes"); + + /* verify we can't get the hash agility attribute */ + is((CFArrayRef) CFDictionaryGetValue(attrs, hashAgilityOid), NULL, + "Get hash agility value array"); + + + CFReleaseNull(message); + CFReleaseNull(contentData); + CFReleaseNull(hashAgilityOid); + CFReleaseNull(expectedTime); + CFReleaseNull(policy); + CFReleaseNull(trust); + CFReleaseNull(attrs); +} + +int si_89_cms_hash_agility(int argc, char *const *argv) +{ + plan_tests(20); + + tests(); + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.h b/OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.h new file mode 100644 index 00000000..8fe4bd98 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.h @@ -0,0 +1,604 @@ +/* + * 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 si_89_cms_hash_agility_h +#define si_89_cms_hash_agility_h + +#include + +/* Random data for content */ +unsigned char content[1024] = { + 0x2a, 0xb1, 0x8c, 0xf1, 0x66, 0x52, 0xd5, 0x3c, 0xdd, 0x53, 0xc0, 0x07, 0x6a, 0x13, 0xda, 0x25, 0x9c, 0x04, 0x64, 0x5c, + 0x97, 0xb8, 0xb3, 0xb5, 0xcf, 0xf8, 0xe1, 0x8f, 0xdd, 0x49, 0x64, 0x55, 0x97, 0xad, 0xbc, 0xad, 0xff, 0xd1, 0xd9, 0xdf, + 0x0f, 0x26, 0x96, 0x27, 0x78, 0x1b, 0x13, 0xf6, 0x2e, 0x75, 0xb2, 0x6a, 0xf1, 0x04, 0x71, 0xa3, 0x51, 0x8d, 0x9c, 0xe8, + 0xab, 0xee, 0xf4, 0xf4, 0xfa, 0x75, 0x16, 0xbe, 0x08, 0xaf, 0xdf, 0x23, 0xc2, 0x17, 0x75, 0x80, 0xad, 0x0e, 0x68, 0xc1, + 0x37, 0xd9, 0x49, 0x0b, 0xea, 0x8a, 0x29, 0x3a, 0x2d, 0xff, 0x45, 0xe9, 0x13, 0x93, 0xac, 0x2e, 0x25, 0x3d, 0x5f, 0xd1, + 0x36, 0x66, 0x61, 0x14, 0xa9, 0xf1, 0xae, 0x83, 0x3a, 0x96, 0xe3, 0xcd, 0xe1, 0xdd, 0xb8, 0x8b, 0x85, 0xe7, 0xd9, 0x1b, + 0x76, 0xf9, 0x55, 0xf7, 0xd8, 0xb6, 0xca, 0x5b, 0x0f, 0xb8, 0x40, 0x1b, 0x69, 0x54, 0x07, 0xde, 0xd5, 0x26, 0x85, 0x9b, + 0xd1, 0x4a, 0xce, 0x2b, 0xe1, 0xd8, 0xe7, 0x6a, 0x06, 0x28, 0x4b, 0x05, 0xa9, 0x0b, 0x65, 0x07, 0x3d, 0xf5, 0xca, 0x31, + 0xd0, 0xfb, 0x5b, 0xf8, 0x1e, 0x19, 0x5f, 0x69, 0x64, 0x1b, 0xe1, 0x6d, 0x15, 0x88, 0x9c, 0xd1, 0x25, 0x4d, 0xf2, 0xa5, + 0x74, 0x82, 0xa4, 0xd3, 0x21, 0xc2, 0x4f, 0x78, 0xcf, 0x37, 0xdd, 0x3c, 0xe5, 0x69, 0x27, 0x82, 0xf1, 0xc8, 0xe9, 0x2f, + 0x7a, 0x7d, 0xd4, 0x65, 0x78, 0xad, 0x4c, 0xfc, 0xa5, 0x29, 0x51, 0xe2, 0x67, 0xac, 0x29, 0xa4, 0x23, 0x46, 0xe0, 0x10, + 0x55, 0x2a, 0x7e, 0xef, 0x04, 0xd4, 0x9f, 0xe3, 0x65, 0x09, 0x2d, 0x33, 0x07, 0xa5, 0x6c, 0x3d, 0x6e, 0xf5, 0x3e, 0xda, + 0x92, 0xb3, 0x47, 0x89, 0xa8, 0xda, 0x04, 0xe0, 0xa6, 0xcd, 0xd5, 0x84, 0xd6, 0xd5, 0x6f, 0xa5, 0x30, 0x3f, 0xcc, 0x9e, + 0xfe, 0xd5, 0xd6, 0xb8, 0x61, 0xf6, 0xb0, 0x10, 0x9d, 0x4d, 0x5c, 0x90, 0xc8, 0x05, 0x4d, 0xba, 0x99, 0x8e, 0xa7, 0xc8, + 0x53, 0xe7, 0x5d, 0xd7, 0x37, 0xf3, 0x0b, 0xc9, 0x0f, 0x97, 0x2d, 0x3e, 0x22, 0xed, 0xdc, 0x28, 0x22, 0x32, 0x04, 0xc0, + 0x6a, 0x38, 0xd8, 0xc8, 0x85, 0xef, 0x57, 0x9c, 0xa1, 0xe0, 0x0b, 0x7e, 0x6a, 0xb4, 0x5a, 0x76, 0x7c, 0xaf, 0x6f, 0x5d, + 0xcc, 0x56, 0xef, 0x60, 0x3c, 0xce, 0x0f, 0x0a, 0x5e, 0xfa, 0xbb, 0xb6, 0xd8, 0xba, 0xda, 0x9d, 0xf5, 0x86, 0x55, 0xc2, + 0x84, 0x9b, 0x3d, 0xc2, 0x54, 0x5b, 0xa9, 0x23, 0x57, 0xe1, 0x0a, 0x84, 0x7e, 0x3c, 0x52, 0x9c, 0x3d, 0x02, 0x9b, 0xb5, + 0x9c, 0x50, 0xfb, 0xfc, 0x43, 0xf9, 0x07, 0x34, 0xd9, 0xad, 0x3f, 0x59, 0x44, 0x6b, 0x47, 0xa0, 0xb9, 0x29, 0x63, 0xfb, + 0xd9, 0xd7, 0xfc, 0x62, 0xda, 0x23, 0x7e, 0x2b, 0xb6, 0x09, 0xfc, 0x52, 0x70, 0x77, 0xb9, 0x4d, 0x92, 0xdd, 0xf2, 0x82, + 0x8c, 0xa3, 0xf5, 0x79, 0xf9, 0x21, 0xe8, 0x36, 0xea, 0xf5, 0xa7, 0x8c, 0x3c, 0x46, 0xab, 0x29, 0xdc, 0x91, 0xa8, 0x8e, + 0xc5, 0xe7, 0xe5, 0x95, 0xd5, 0xca, 0xed, 0xad, 0x54, 0x24, 0xf2, 0xee, 0x40, 0x9c, 0x06, 0x08, 0x03, 0x36, 0x0a, 0x73, + 0xa4, 0xcb, 0xbb, 0x28, 0x83, 0x28, 0x66, 0xc3, 0x79, 0xba, 0x7a, 0x76, 0x90, 0x10, 0x88, 0x04, 0x3f, 0x0f, 0x67, 0xd2, + 0x53, 0xab, 0x63, 0xc7, 0x83, 0xc9, 0x2b, 0xdd, 0x9c, 0x61, 0x99, 0xe4, 0x12, 0x18, 0xc6, 0x9a, 0x9d, 0x3c, 0xea, 0x13, + 0x87, 0x32, 0x57, 0x8d, 0x01, 0x11, 0x39, 0x56, 0x94, 0xb2, 0x4d, 0x73, 0xc0, 0xdc, 0x2d, 0x4c, 0xb3, 0xd1, 0x90, 0x36, + 0xd8, 0xae, 0xd3, 0x06, 0xd7, 0x70, 0xa5, 0xd6, 0x0e, 0x64, 0xf8, 0x80, 0xb6, 0x36, 0x0c, 0x31, 0xd3, 0xcc, 0x46, 0xba, + 0xb4, 0x14, 0xb4, 0xcb, 0x43, 0x68, 0x0f, 0x8d, 0xf7, 0x2c, 0x61, 0xf4, 0xfb, 0xce, 0xf1, 0xaf, 0xe9, 0x2e, 0x52, 0x02, + 0x29, 0x5e, 0xd7, 0xc6, 0xed, 0xf6, 0x22, 0xb9, 0x7b, 0xe8, 0x1a, 0xe6, 0x59, 0xdb, 0x43, 0xdd, 0x58, 0xe2, 0x50, 0xab, + 0x57, 0x01, 0xf0, 0x61, 0xb0, 0x83, 0xa9, 0x40, 0x0c, 0x24, 0x08, 0x6e, 0x95, 0x45, 0xba, 0xb3, 0x02, 0xa9, 0x41, 0xde, + 0xaf, 0xc2, 0x4c, 0xc2, 0x71, 0x1e, 0x86, 0xe4, 0xe9, 0x81, 0x9e, 0xdf, 0xea, 0x11, 0x66, 0x91, 0x02, 0x8c, 0xf5, 0xa3, + 0x05, 0xe3, 0xe9, 0x6e, 0x7f, 0x34, 0xb5, 0x0a, 0x3f, 0xc3, 0x70, 0x18, 0x33, 0x33, 0x7e, 0x85, 0x81, 0x04, 0x1f, 0xaa, + 0x14, 0x0c, 0x57, 0xca, 0x41, 0x97, 0x79, 0x62, 0x2e, 0x99, 0xbc, 0x6f, 0xce, 0x21, 0xad, 0xde, 0x7d, 0x74, 0x73, 0x3f, + 0x75, 0x00, 0x65, 0xc2, 0x40, 0x5e, 0xda, 0xce, 0x41, 0x4e, 0x8b, 0xd0, 0x32, 0x4f, 0x7f, 0xee, 0xbe, 0xc9, 0x41, 0xb2, + 0x42, 0xe9, 0x5a, 0xe5, 0xee, 0x18, 0x0c, 0x70, 0x93, 0xec, 0xb2, 0x46, 0xcd, 0x11, 0x16, 0x31, 0x81, 0x33, 0x5e, 0x82, + 0x20, 0x85, 0x1b, 0x02, 0x76, 0xeb, 0x13, 0xb9, 0xd4, 0xbd, 0xf9, 0xe7, 0xb5, 0x5e, 0x5e, 0x05, 0x48, 0x74, 0x27, 0xf2, + 0xdc, 0x3e, 0x87, 0x8b, 0x33, 0x3f, 0x50, 0xb6, 0xc6, 0x52, 0xf8, 0x61, 0x69, 0x7e, 0x6b, 0x30, 0xef, 0x2c, 0x6c, 0x5e, + 0x69, 0xc8, 0xba, 0x1e, 0x3d, 0x2a, 0x0c, 0x74, 0xbd, 0x93, 0xc9, 0x36, 0xcc, 0x72, 0x15, 0xe6, 0xbb, 0xd0, 0xc0, 0xe3, + 0xaf, 0x60, 0xcd, 0x83, 0x54, 0x50, 0x67, 0xbb, 0x70, 0x2a, 0xa1, 0x51, 0x87, 0x9b, 0xc5, 0xe0, 0xbb, 0xa3, 0xb1, 0x6f, + 0x3a, 0x1a, 0x62, 0x72, 0x6f, 0x89, 0x8a, 0x1d, 0xc4, 0x09, 0x55, 0xac, 0x67, 0x7b, 0xa3, 0xe6, 0xed, 0x4e, 0xbb, 0xf2, + 0x5f, 0x42, 0x95, 0x7b, 0x95, 0x7a, 0xbe, 0x3e, 0xf5, 0x2f, 0xee, 0x5f, 0x30, 0x57, 0x51, 0x94, 0x7d, 0x45, 0xd5, 0xd7, + 0x6e, 0xcc, 0xf6, 0x4d, 0xac, 0x7b, 0x51, 0x70, 0x32, 0x07, 0x1c, 0xaf, 0x97, 0xdd, 0x92, 0x0d, 0x9d, 0xba, 0x53, 0xf5, + 0x49, 0xc7, 0xa5, 0x6a, 0x7a, 0x3b, 0xb0, 0x3f, 0x0c, 0x01, 0xa5, 0x00, 0x4a, 0x33, 0x90, 0xf7, 0xee, 0x0a, 0x12, 0x5d, + 0xc0, 0x5d, 0xb1, 0x85, 0x63, 0xed, 0xcf, 0xb8, 0x84, 0xde, 0x51, 0x8f, 0xd9, 0xf4, 0x15, 0x76, 0x43, 0xc4, 0xfe, 0x89, + 0x16, 0xfe, 0x13, 0x92, 0xbd, 0x25, 0x66, 0xb9, 0x56, 0x60, 0x1f, 0x85, 0x3d, 0xc6, 0x9a, 0x02, 0xc4, 0x2a, 0xbf, 0x8b, + 0x1b, 0xf1, 0x41, 0xbb, 0x37, 0x77, 0xe1, 0x18, 0xa7, 0x5f, 0x2a, 0x30, 0x37, 0xf6, 0xf4, 0x2a, 0x4b, 0x77, 0xf8, 0x15, + 0xc5, 0xb9, 0xb5, 0xdd, 0x93, 0x4f, 0x59, 0x97, 0x6b, 0xf2, 0xe8, 0x6e, 0xf5, 0x7e, 0x21, 0x20, 0x64, 0xac, 0xe8, 0x8d, + 0x60, 0xcb, 0xd2, 0xdc, 0xa7, 0xc8, 0x16, 0xb2, 0x7c, 0xf3, 0xbe, 0x88, 0x5b, 0x75, 0xcb, 0xf7, 0x38, 0x79, 0xa5, 0x32, + 0x5f, 0xa7, 0xf2, 0xfd, 0x6a, 0x21, 0x71, 0x16, 0x1b, 0xe9, 0xde, 0xd9, 0x88, 0xf2, 0x89, 0xef, 0x4f, 0x9a, 0xc4, 0x9b, + 0x04, 0xa0, 0x16, 0xab, 0x39, 0x62, 0x3f, 0x1f, 0x06, 0x2a, 0x88, 0x04, 0x68, 0x63, 0xb1, 0x21, 0x87, 0x25, 0xfb, 0xc3, + 0xb5, 0xe0, 0xc8, 0x48, 0x42, 0x4e, 0x3a, 0xc9, 0x90, 0x4c, 0xc1, 0xa5, 0x69, 0x62, 0xd6, 0x25, 0xdc, 0xc9, 0x51, 0xeb, + 0x6f, 0x00, 0x70, 0x91, 0x86, 0x57, 0x36, 0x23, 0x1f, 0x29, 0x8b, 0x52, 0xb2, 0x31, 0xd5, 0x8d, 0xc5, 0xa3, 0x5f, 0xd3, + 0x7a, 0xe4, 0x2e, 0x3a +}; + +/* Random data for hash agility attribute */ +unsigned char attribute[32] = { + 0x2e, 0xd0, 0xd3, 0x8f, 0xfd, 0xab, 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, + 0x87, 0xa0, 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6 +}; + +/* Valid CMS message on content with hash agility attribute */ +uint8_t valid_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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, + 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, + 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, + 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, + 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, + 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, + 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, + 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, + 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, + 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, + 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, + 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, + 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, + 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, + 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, + 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, + 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, + 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, + 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, + 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, + 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, + 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, + 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, + 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, + 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, + 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, + 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, + 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, + 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, + 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, + 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, + 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, + 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, + 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, + 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, + 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, + 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, + 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, + 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, + 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, + 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, + 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, + 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, + 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, + 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, + 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, + 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, + 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, + 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, + 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, + 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, + 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, + 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, + 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, + 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, + 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, + 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, + 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, + 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, + 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, + 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, + 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, + 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, + 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, + 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, + 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, + 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, + 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, + 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, + 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, + 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, + 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, + 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x6d, + 0x30, 0x82, 0x03, 0x69, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0x9a, + 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, 0x35, 0x31, 0x31, 0x30, + 0x34, 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, + 0xb9, 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, + 0xec, 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x63, 0x64, 0x09, 0x01, 0x31, 0x22, 0x04, 0x20, 0x2e, 0xd0, 0xd3, 0x8f, 0xfd, 0xab, + 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, 0x87, 0xa0, + 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x89, 0xd3, 0x00, + 0x9b, 0xd0, 0x99, 0x21, 0x21, 0x47, 0xff, 0xa3, 0x4c, 0xef, 0xa7, 0x6e, 0x03, 0x1e, 0xbf, 0x6d, + 0x10, 0x3e, 0xf7, 0x36, 0x7e, 0x98, 0xb4, 0xb6, 0x74, 0xa0, 0xa6, 0x2c, 0x83, 0x33, 0xec, 0xeb, + 0xb5, 0x69, 0x3b, 0x10, 0x80, 0x60, 0x2b, 0xf4, 0x71, 0x84, 0x2a, 0x22, 0xfa, 0xbe, 0x51, 0x3d, + 0x69, 0xdc, 0x2b, 0x94, 0xf6, 0x8a, 0x82, 0xee, 0x88, 0xa3, 0xa4, 0x8a, 0x4d, 0x13, 0xee, 0x4b, + 0xf2, 0xd0, 0xef, 0x3a, 0x2d, 0xe0, 0x3e, 0x52, 0xe9, 0x75, 0xf3, 0xf1, 0x8a, 0xc6, 0x68, 0xab, + 0x5f, 0x97, 0x7c, 0xef, 0x2e, 0x06, 0xe4, 0x53, 0x2e, 0xa5, 0x20, 0x8b, 0x8a, 0x1f, 0x0b, 0x8a, + 0xb2, 0x0e, 0xe0, 0x77, 0xbf, 0x4d, 0x0f, 0x45, 0x15, 0x7f, 0x03, 0xdc, 0x0a, 0x5c, 0xcc, 0x88, + 0x49, 0x0b, 0x19, 0xde, 0xd8, 0xdd, 0x62, 0xc6, 0xad, 0x77, 0xaa, 0x37, 0x19, 0x31, 0x6d, 0x57, + 0x7f, 0x29, 0xc1, 0xe2, 0x7a, 0x15, 0xf9, 0xb9, 0xa5, 0xe2, 0xf3, 0xeb, 0x3f, 0x27, 0x5d, 0xac, + 0x02, 0xb8, 0xf7, 0x6d, 0xfe, 0x0f, 0x22, 0x89, 0xe3, 0x5d, 0xcc, 0xf3, 0x6a, 0x8f, 0x1a, 0xe5, + 0x94, 0xfd, 0xad, 0x9a, 0xc2, 0x5d, 0xb5, 0x1b, 0x48, 0xd8, 0x0b, 0x77, 0x9c, 0x27, 0x24, 0x55, + 0xf3, 0x8f, 0x5b, 0x7e, 0x0a, 0x73, 0x35, 0xb4, 0x6c, 0xc7, 0x84, 0xc3, 0x0b, 0x22, 0x57, 0x4d, + 0xff, 0x45, 0x4d, 0x78, 0xa7, 0xd0, 0x7d, 0xcf, 0x74, 0x5c, 0xe8, 0xa6, 0x26, 0x76, 0xda, 0xf1, + 0x4f, 0x75, 0x89, 0xd1, 0x6c, 0x7e, 0x52, 0x8c, 0x6e, 0xa8, 0x6e, 0x4c, 0x5b, 0x54, 0x94, 0x35, + 0x92, 0xec, 0x22, 0x5c, 0xdd, 0x97, 0x41, 0xef, 0x9f, 0x6d, 0xa2, 0x63, 0xaa, 0x22, 0x81, 0xab, + 0xfa, 0x0d, 0x2d, 0xed, 0xe6, 0x45, 0xe4, 0x2a, 0x51, 0x1d, 0xa6, 0x8d, 0x24, 0x99, 0xda, 0xb6, + 0xe3, 0xeb, 0x56, 0xf8, 0x6d, 0xe7, 0xbf, 0x14, 0xfa, 0x41, 0x82, 0x93, 0x28, 0xb0, 0x3f, 0x83, + 0x3a, 0x10, 0x79, 0x18, 0x4f, 0x21, 0xc7, 0xd1, 0x5f, 0x80, 0x77, 0x98, 0x0e, 0x26, 0xdd, 0x36, + 0xc7, 0xc6, 0x6b, 0xd2, 0x42, 0xd8, 0xa1, 0xfc, 0x69, 0x90, 0xa6, 0xea, 0xe6, 0xf2, 0x5b, 0x78, + 0xb7, 0x27, 0xe2, 0x13, 0xc2, 0xe7, 0xdf, 0x37, 0x30, 0x94, 0xaf, 0xbf, 0x88, 0x63, 0x3d, 0xad, + 0xfc, 0xdb, 0xf4, 0x5f, 0x5c, 0x4b, 0x07, 0x36, 0xc2, 0xc2, 0xca, 0xe3, 0x3d, 0xd9, 0x51, 0x88, + 0x37, 0xb5, 0xd6, 0x36, 0x63, 0x42, 0x8b, 0xd3, 0x86, 0xc3, 0xc0, 0x1c, 0x08, 0x2c, 0x5c, 0x93, + 0x21, 0x3e, 0x7a, 0x54, 0x21, 0xa4, 0xbc, 0x78, 0xdc, 0x41, 0x78, 0x18, 0x83, 0xf6, 0x4d, 0x2d, + 0x3a, 0xa1, 0xf3, 0xd2, 0x3e, 0x31, 0x91, 0x6f, 0xf9, 0xd3, 0xd6, 0xe1, 0xef, 0x83, 0xd7, 0x59, + 0xc9, 0xa3, 0x36, 0xcc, 0x26, 0xfd, 0x7c, 0x93, 0x0a, 0x4e, 0xae, 0x45, 0x4b, 0xb0, 0x58, 0xd0, + 0xb0, 0xca, 0x70, 0x35, 0x2f, 0x63, 0x28, 0x9d, 0x5a, 0xc8, 0x02, 0xf9, 0x8b, 0xaa, 0xcf, 0x6d, + 0x8b, 0xbb, 0xb5, 0xf6, 0x44, 0xe4, 0xcb, 0x3d, 0xbe, 0xd2, 0x70, 0x2d, 0xb3, 0xe9, 0x05, 0x6c, + 0xfe, 0x41, 0xa3, 0x05, 0xec, 0xe4, 0xf1, 0x9e, 0x37, 0x04, 0xd1, 0x9a, 0x60, 0xf9, 0x95, 0xc4, + 0x11, 0xb3, 0xbf, 0x17, 0xa4, 0x72, 0x2a, 0x03, 0x2d, 0x9a, 0x2b, 0xed, 0x97, 0xc9, 0x29, 0x05, + 0x23, 0xbb, 0xd2, 0xfe, 0x0b, 0x91, 0x5b, 0x93, 0x3f, 0x93, 0x10, 0x69, 0xcb, 0x92, 0x14, 0x8c, + 0xd4, 0xf3, 0x4f, 0x51, 0xc4, 0x78, 0x52, 0xc1, 0xea, 0x20, 0xa9, 0x16, 0x9b, 0x51, 0xb3, 0x69, + 0xf7, 0x92, 0xea, 0x6e, 0x94, 0x53, 0xc8, 0xf0, 0xd1, 0x24, 0x38, 0x3a, 0x1d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +/* + * Invalid CMS message on content with hash agility attribute. + * Only the hash agility attribute value has been changed from the valid message. + */ +uint8_t invalid_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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, + 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, + 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, + 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, + 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, + 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, + 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, + 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, + 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, + 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, + 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, + 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, + 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, + 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, + 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, + 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, + 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, + 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, + 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, + 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, + 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, + 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, + 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, + 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, + 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, + 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, + 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, + 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, + 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, + 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, + 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, + 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, + 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, + 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, + 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, + 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, + 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, + 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, + 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, + 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, + 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, + 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, + 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, + 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, + 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, + 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, + 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, + 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, + 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, + 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, + 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, + 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, + 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, + 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, + 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, + 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, + 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, + 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, + 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, + 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, + 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, + 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, + 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, + 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, + 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, + 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, + 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, + 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, + 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, + 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, + 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, + 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, + 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x6d, + 0x30, 0x82, 0x03, 0x69, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x81, 0x9a, + 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, 0x35, 0x31, 0x31, 0x30, + 0x34, 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, + 0xb9, 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, + 0xec, 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x63, 0x64, 0x09, 0x01, 0x31, 0x22, 0x04, 0x20, 0x2e, 0xd0, 0xd0, 0x8f, 0xfd, 0xab, + 0xc6, 0x13, 0xc8, 0x7c, 0x7b, 0x3c, 0x05, 0x16, 0xfb, 0x44, 0x66, 0x40, 0xaf, 0xe3, 0x87, 0xa0, + 0x4e, 0x80, 0xf4, 0xf3, 0x5d, 0xd2, 0x68, 0x08, 0x58, 0xe6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x89, 0xd3, 0x00, + 0x9b, 0xd0, 0x99, 0x21, 0x21, 0x47, 0xff, 0xa3, 0x4c, 0xef, 0xa7, 0x6e, 0x03, 0x1e, 0xbf, 0x6d, + 0x10, 0x3e, 0xf7, 0x36, 0x7e, 0x98, 0xb4, 0xb6, 0x74, 0xa0, 0xa6, 0x2c, 0x83, 0x33, 0xec, 0xeb, + 0xb5, 0x69, 0x3b, 0x10, 0x80, 0x60, 0x2b, 0xf4, 0x71, 0x84, 0x2a, 0x22, 0xfa, 0xbe, 0x51, 0x3d, + 0x69, 0xdc, 0x2b, 0x94, 0xf6, 0x8a, 0x82, 0xee, 0x88, 0xa3, 0xa4, 0x8a, 0x4d, 0x13, 0xee, 0x4b, + 0xf2, 0xd0, 0xef, 0x3a, 0x2d, 0xe0, 0x3e, 0x52, 0xe9, 0x75, 0xf3, 0xf1, 0x8a, 0xc6, 0x68, 0xab, + 0x5f, 0x97, 0x7c, 0xef, 0x2e, 0x06, 0xe4, 0x53, 0x2e, 0xa5, 0x20, 0x8b, 0x8a, 0x1f, 0x0b, 0x8a, + 0xb2, 0x0e, 0xe0, 0x77, 0xbf, 0x4d, 0x0f, 0x45, 0x15, 0x7f, 0x03, 0xdc, 0x0a, 0x5c, 0xcc, 0x88, + 0x49, 0x0b, 0x19, 0xde, 0xd8, 0xdd, 0x62, 0xc6, 0xad, 0x77, 0xaa, 0x37, 0x19, 0x31, 0x6d, 0x57, + 0x7f, 0x29, 0xc1, 0xe2, 0x7a, 0x15, 0xf9, 0xb9, 0xa5, 0xe2, 0xf3, 0xeb, 0x3f, 0x27, 0x5d, 0xac, + 0x02, 0xb8, 0xf7, 0x6d, 0xfe, 0x0f, 0x22, 0x89, 0xe3, 0x5d, 0xcc, 0xf3, 0x6a, 0x8f, 0x1a, 0xe5, + 0x94, 0xfd, 0xad, 0x9a, 0xc2, 0x5d, 0xb5, 0x1b, 0x48, 0xd8, 0x0b, 0x77, 0x9c, 0x27, 0x24, 0x55, + 0xf3, 0x8f, 0x5b, 0x7e, 0x0a, 0x73, 0x35, 0xb4, 0x6c, 0xc7, 0x84, 0xc3, 0x0b, 0x22, 0x57, 0x4d, + 0xff, 0x45, 0x4d, 0x78, 0xa7, 0xd0, 0x7d, 0xcf, 0x74, 0x5c, 0xe8, 0xa6, 0x26, 0x76, 0xda, 0xf1, + 0x4f, 0x75, 0x89, 0xd1, 0x6c, 0x7e, 0x52, 0x8c, 0x6e, 0xa8, 0x6e, 0x4c, 0x5b, 0x54, 0x94, 0x35, + 0x92, 0xec, 0x22, 0x5c, 0xdd, 0x97, 0x41, 0xef, 0x9f, 0x6d, 0xa2, 0x63, 0xaa, 0x22, 0x81, 0xab, + 0xfa, 0x0d, 0x2d, 0xed, 0xe6, 0x45, 0xe4, 0x2a, 0x51, 0x1d, 0xa6, 0x8d, 0x24, 0x99, 0xda, 0xb6, + 0xe3, 0xeb, 0x56, 0xf8, 0x6d, 0xe7, 0xbf, 0x14, 0xfa, 0x41, 0x82, 0x93, 0x28, 0xb0, 0x3f, 0x83, + 0x3a, 0x10, 0x79, 0x18, 0x4f, 0x21, 0xc7, 0xd1, 0x5f, 0x80, 0x77, 0x98, 0x0e, 0x26, 0xdd, 0x36, + 0xc7, 0xc6, 0x6b, 0xd2, 0x42, 0xd8, 0xa1, 0xfc, 0x69, 0x90, 0xa6, 0xea, 0xe6, 0xf2, 0x5b, 0x78, + 0xb7, 0x27, 0xe2, 0x13, 0xc2, 0xe7, 0xdf, 0x37, 0x30, 0x94, 0xaf, 0xbf, 0x88, 0x63, 0x3d, 0xad, + 0xfc, 0xdb, 0xf4, 0x5f, 0x5c, 0x4b, 0x07, 0x36, 0xc2, 0xc2, 0xca, 0xe3, 0x3d, 0xd9, 0x51, 0x88, + 0x37, 0xb5, 0xd6, 0x36, 0x63, 0x42, 0x8b, 0xd3, 0x86, 0xc3, 0xc0, 0x1c, 0x08, 0x2c, 0x5c, 0x93, + 0x21, 0x3e, 0x7a, 0x54, 0x21, 0xa4, 0xbc, 0x78, 0xdc, 0x41, 0x78, 0x18, 0x83, 0xf6, 0x4d, 0x2d, + 0x3a, 0xa1, 0xf3, 0xd2, 0x3e, 0x31, 0x91, 0x6f, 0xf9, 0xd3, 0xd6, 0xe1, 0xef, 0x83, 0xd7, 0x59, + 0xc9, 0xa3, 0x36, 0xcc, 0x26, 0xfd, 0x7c, 0x93, 0x0a, 0x4e, 0xae, 0x45, 0x4b, 0xb0, 0x58, 0xd0, + 0xb0, 0xca, 0x70, 0x35, 0x2f, 0x63, 0x28, 0x9d, 0x5a, 0xc8, 0x02, 0xf9, 0x8b, 0xaa, 0xcf, 0x6d, + 0x8b, 0xbb, 0xb5, 0xf6, 0x44, 0xe4, 0xcb, 0x3d, 0xbe, 0xd2, 0x70, 0x2d, 0xb3, 0xe9, 0x05, 0x6c, + 0xfe, 0x41, 0xa3, 0x05, 0xec, 0xe4, 0xf1, 0x9e, 0x37, 0x04, 0xd1, 0x9a, 0x60, 0xf9, 0x95, 0xc4, + 0x11, 0xb3, 0xbf, 0x17, 0xa4, 0x72, 0x2a, 0x03, 0x2d, 0x9a, 0x2b, 0xed, 0x97, 0xc9, 0x29, 0x05, + 0x23, 0xbb, 0xd2, 0xfe, 0x0b, 0x91, 0x5b, 0x93, 0x3f, 0x93, 0x10, 0x69, 0xcb, 0x92, 0x14, 0x8c, + 0xd4, 0xf3, 0x4f, 0x51, 0xc4, 0x78, 0x52, 0xc1, 0xea, 0x20, 0xa9, 0x16, 0x9b, 0x51, 0xb3, 0x69, + 0xf7, 0x92, 0xea, 0x6e, 0x94, 0x53, 0xc8, 0xf0, 0xd1, 0x24, 0x38, 0x3a, 0x1d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + +/* Valid CMS message with no hash agility attribute */ +unsigned char valid_no_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, 0x00, 0x00, 0xa0, 0x82, 0x06, 0xb4, 0x30, 0x82, 0x06, 0xb0, 0x30, 0x82, 0x04, 0x98, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, + 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, + 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, + 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, + 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, + 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, + 0x32, 0x39, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x31, 0x30, 0x32, + 0x38, 0x32, 0x31, 0x35, 0x35, 0x35, 0x38, 0x5a, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, + 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, + 0x01, 0x00, 0xc4, 0x2a, 0x38, 0x4b, 0xdd, 0x1c, 0xc7, 0x39, 0x47, 0xba, 0xbc, 0x5d, 0xd2, 0xcc, + 0x6e, 0x9e, 0x2c, 0x81, 0x26, 0x18, 0x59, 0x18, 0xb8, 0x45, 0x0c, 0xde, 0x5b, 0xbc, 0x25, 0xa4, + 0x78, 0x0b, 0x16, 0x3d, 0x3d, 0x10, 0x34, 0x48, 0xcf, 0x1f, 0x40, 0xaa, 0x4b, 0xb5, 0xbc, 0xf0, + 0x81, 0x5e, 0xa8, 0x72, 0xed, 0x6a, 0x8c, 0xf0, 0x4a, 0x9a, 0x80, 0x09, 0x3b, 0x89, 0xed, 0xad, + 0x2b, 0xb5, 0x5b, 0x0f, 0xe4, 0x3f, 0x6b, 0xc5, 0x15, 0x33, 0x5e, 0xdd, 0xa4, 0xac, 0x2f, 0xa5, + 0x13, 0x0f, 0x3c, 0xfc, 0xd8, 0xca, 0xb8, 0x88, 0x67, 0x75, 0xc4, 0x9a, 0x4c, 0x18, 0x9a, 0x38, + 0x68, 0xaa, 0x4c, 0x94, 0x35, 0xed, 0xa4, 0x0b, 0x80, 0x2b, 0xa9, 0x4d, 0xa4, 0x57, 0x22, 0xfc, + 0xd2, 0xc3, 0x12, 0x0b, 0x8a, 0x3c, 0xd7, 0x6d, 0x8b, 0x47, 0x4f, 0x24, 0xe5, 0xea, 0x1b, 0x03, + 0x78, 0xa2, 0x12, 0x36, 0x3f, 0x92, 0x16, 0x36, 0xff, 0xc5, 0xaf, 0xc3, 0xec, 0x4b, 0x6c, 0x23, + 0x04, 0x1b, 0xa9, 0xce, 0x3a, 0xa1, 0xa5, 0xe0, 0x54, 0x13, 0x43, 0x13, 0x29, 0x95, 0x5b, 0xcb, + 0x97, 0x74, 0x01, 0xbc, 0x3c, 0xb8, 0xa1, 0xb0, 0xf3, 0x3c, 0xfa, 0x21, 0x7a, 0x89, 0x90, 0x2b, + 0x1f, 0x20, 0x3f, 0xc1, 0x22, 0xda, 0x8d, 0xa5, 0x30, 0x57, 0x6d, 0xd4, 0x40, 0x99, 0x08, 0x0d, + 0xef, 0x36, 0x16, 0xa6, 0xec, 0xcf, 0x26, 0x78, 0x7c, 0x77, 0x7e, 0x50, 0x2a, 0xe3, 0xdf, 0x28, + 0xff, 0xd0, 0xc7, 0x0e, 0x8b, 0x6b, 0x56, 0x62, 0x53, 0x37, 0x5a, 0x1a, 0x85, 0x50, 0xec, 0x6a, + 0x6b, 0x2e, 0xd1, 0x35, 0x6e, 0x5d, 0x92, 0x30, 0x39, 0x82, 0x40, 0x7b, 0x6d, 0x89, 0x5b, 0x4d, + 0x30, 0x6d, 0x2e, 0x68, 0x16, 0x24, 0x63, 0x32, 0x24, 0xdc, 0x3e, 0x5b, 0x4a, 0xc4, 0x41, 0xfc, + 0x76, 0x07, 0xe6, 0xa3, 0x1b, 0x18, 0xec, 0x59, 0xed, 0x13, 0x0b, 0x2d, 0xe9, 0x86, 0x89, 0x2c, + 0x0a, 0xb0, 0x19, 0x97, 0x4d, 0x1b, 0xfb, 0xd4, 0xef, 0x54, 0xcd, 0xe5, 0xb2, 0x22, 0x70, 0x3a, + 0x50, 0x03, 0xaa, 0xc0, 0xf8, 0xb4, 0x8e, 0x16, 0xd8, 0x2a, 0xc1, 0xd1, 0x2d, 0xa0, 0x27, 0x59, + 0x63, 0x70, 0xc3, 0x74, 0x14, 0xee, 0xde, 0xa9, 0xd9, 0x73, 0xdb, 0x16, 0x6d, 0xef, 0x7f, 0x50, + 0xb6, 0xd2, 0x54, 0x0d, 0x4d, 0x31, 0x5f, 0x23, 0x2c, 0xfd, 0x8f, 0x67, 0x7c, 0xe9, 0xaa, 0x1c, + 0x29, 0xf5, 0x83, 0x1b, 0x2b, 0x0e, 0x66, 0x0e, 0x5c, 0xfe, 0xc9, 0x38, 0xb0, 0x90, 0xfa, 0x31, + 0x4c, 0xb1, 0xef, 0xea, 0xd0, 0x47, 0x17, 0xde, 0x45, 0xc1, 0x93, 0xef, 0xba, 0xde, 0x9f, 0x69, + 0xc7, 0xa6, 0x14, 0x23, 0xb1, 0x8b, 0xaa, 0xbf, 0x61, 0x37, 0x57, 0x11, 0x6a, 0xb2, 0xf7, 0xec, + 0x52, 0x7e, 0x65, 0x80, 0xff, 0xa1, 0xa8, 0x20, 0x7e, 0x0b, 0xae, 0x21, 0xfa, 0xe8, 0x20, 0x52, + 0x93, 0xc5, 0xe9, 0x39, 0x5b, 0x8e, 0xab, 0xef, 0x86, 0xa6, 0xd8, 0x43, 0x7e, 0xa9, 0x5c, 0x6d, + 0x91, 0xd8, 0x5c, 0xa4, 0x2a, 0xed, 0x26, 0xa8, 0x1b, 0xaa, 0x3b, 0xfa, 0x86, 0x75, 0x37, 0xc6, + 0x70, 0x12, 0x2b, 0x8c, 0x55, 0x96, 0x76, 0x04, 0xf6, 0xe3, 0xf9, 0xe2, 0x0d, 0x2e, 0xe0, 0x23, + 0xdf, 0xfa, 0xe0, 0x9c, 0x11, 0xf9, 0xd4, 0x51, 0x05, 0xed, 0x2b, 0x3f, 0xa3, 0x3f, 0xa2, 0xe6, + 0x30, 0x81, 0x17, 0x00, 0x8f, 0x15, 0x91, 0xfb, 0x21, 0x62, 0xf4, 0xff, 0x93, 0x1a, 0x2e, 0xfe, + 0x1a, 0xcb, 0x93, 0x3d, 0xd4, 0x6e, 0x3a, 0xb8, 0x70, 0xdf, 0x93, 0xb4, 0x02, 0xc4, 0x8c, 0x54, + 0x92, 0xde, 0xa7, 0x32, 0x65, 0x1c, 0x85, 0x95, 0x34, 0xf8, 0x8d, 0x06, 0x5b, 0x7d, 0x72, 0x00, + 0xd8, 0x31, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xee, 0x16, 0xde, 0xfd, 0x11, 0xd3, 0x88, 0xfb, + 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, 0x30, 0x81, 0xcb, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xc3, 0x30, 0x81, 0xc0, 0x80, 0x14, 0xee, 0x16, 0xde, 0xfd, + 0x11, 0xd3, 0x88, 0xfb, 0xef, 0xfb, 0x19, 0x23, 0x8a, 0x23, 0x85, 0x7b, 0xe8, 0x41, 0x26, 0xa1, + 0xa1, 0x81, 0x9c, 0xa4, 0x81, 0x99, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x2c, + 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0f, + 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x82, + 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x0c, 0x0f, 0x08, 0x79, + 0x6f, 0x56, 0x21, 0xdf, 0xdd, 0xf5, 0x97, 0x8d, 0xdc, 0x97, 0x06, 0xfb, 0x2e, 0xe0, 0x21, 0x60, + 0xc3, 0x02, 0xf4, 0x41, 0x79, 0x79, 0xc2, 0x23, 0x9a, 0x8a, 0x54, 0x2e, 0x66, 0xab, 0xc0, 0x21, + 0xf6, 0x9f, 0xc5, 0x2e, 0x41, 0xb8, 0xa3, 0x32, 0x9f, 0x3d, 0x4e, 0xf4, 0x83, 0xee, 0xcc, 0x60, + 0xf6, 0x82, 0x3d, 0xb4, 0xa9, 0x9d, 0xcd, 0xa0, 0x02, 0x89, 0xb0, 0x32, 0x1b, 0xb5, 0x7c, 0xf4, + 0x8f, 0xbc, 0x9b, 0x24, 0xc2, 0xe2, 0x81, 0xd6, 0x6f, 0x0e, 0x22, 0x5e, 0x50, 0xd9, 0x5b, 0x2e, + 0x89, 0xbf, 0xa4, 0xfe, 0xa8, 0xc2, 0x9a, 0xf4, 0xec, 0x70, 0x66, 0x01, 0x4b, 0x50, 0x30, 0x97, + 0x0a, 0xcc, 0x9f, 0xac, 0xe4, 0x89, 0x1c, 0x8d, 0x88, 0x0d, 0xdb, 0x21, 0xbd, 0x2f, 0x24, 0x8e, + 0x83, 0xf9, 0xe6, 0x71, 0xed, 0x71, 0x26, 0x31, 0x99, 0x9d, 0x04, 0xeb, 0x34, 0xea, 0x6d, 0x65, + 0xb8, 0x02, 0x83, 0x57, 0x78, 0x36, 0x3a, 0x0b, 0xc7, 0x41, 0x63, 0xb5, 0xf6, 0x1c, 0xd2, 0x01, + 0x86, 0x04, 0x58, 0x40, 0x3e, 0x91, 0x98, 0x39, 0x72, 0x75, 0x11, 0xca, 0x14, 0x73, 0x90, 0x34, + 0x8b, 0x21, 0xa4, 0xd0, 0xba, 0xe7, 0x33, 0x03, 0x22, 0x0f, 0x1a, 0xf7, 0x10, 0x2b, 0x69, 0x4c, + 0x73, 0xef, 0x04, 0x18, 0xf9, 0xe1, 0x11, 0xa8, 0xb8, 0x1b, 0x57, 0x0b, 0x03, 0x10, 0x1c, 0xce, + 0x13, 0xca, 0xe4, 0xde, 0x8c, 0xf4, 0xcf, 0xf5, 0xb7, 0x80, 0x3e, 0xbc, 0x1f, 0x51, 0x9b, 0x20, + 0x8c, 0xb0, 0x2d, 0x67, 0x1c, 0x84, 0x25, 0x4c, 0x8b, 0xd3, 0xa7, 0x09, 0x8e, 0x60, 0xe2, 0x99, + 0x0d, 0x10, 0x12, 0x14, 0xfc, 0x17, 0x62, 0x69, 0xcd, 0xa4, 0x64, 0xf0, 0x7e, 0xba, 0xe0, 0xc9, + 0x51, 0x78, 0xf8, 0xb4, 0x0d, 0x7d, 0xb8, 0xa0, 0xee, 0x9c, 0x9e, 0x84, 0xd5, 0xa4, 0x02, 0xe5, + 0x7a, 0x1c, 0x65, 0xe1, 0x20, 0xfb, 0x4d, 0x61, 0x7a, 0x47, 0x25, 0x06, 0x95, 0x17, 0x62, 0x60, + 0x4b, 0x0b, 0xc6, 0xca, 0xa7, 0x35, 0x8f, 0xd4, 0x63, 0x3e, 0x5e, 0x92, 0x1a, 0x08, 0x7c, 0x6b, + 0x15, 0x41, 0x95, 0x76, 0x7d, 0x39, 0x28, 0xec, 0x3e, 0x1f, 0x49, 0xd5, 0xd5, 0x89, 0xf9, 0x5f, + 0x14, 0x02, 0x2f, 0x27, 0xb0, 0x39, 0xba, 0xf7, 0x91, 0x53, 0x75, 0x77, 0xab, 0x88, 0x40, 0x1d, + 0x77, 0xaf, 0x79, 0xfd, 0xdc, 0xac, 0x99, 0x82, 0xf2, 0x46, 0x05, 0x97, 0x60, 0xef, 0x7b, 0xf5, + 0x34, 0x38, 0xbf, 0xd7, 0x42, 0x3e, 0x8b, 0x5a, 0x4a, 0x0c, 0x22, 0x7e, 0x4d, 0x4e, 0xf6, 0xf7, + 0xcc, 0x6e, 0x31, 0x33, 0x1a, 0x84, 0xbe, 0x07, 0xf7, 0xe8, 0xe2, 0x43, 0x00, 0x54, 0x4a, 0x38, + 0xda, 0x98, 0xe3, 0x84, 0xb2, 0xd0, 0x76, 0x79, 0x94, 0x11, 0x7e, 0xa8, 0xca, 0x56, 0xa0, 0xfd, + 0x4b, 0xba, 0x7c, 0x0a, 0xa4, 0x34, 0x01, 0xad, 0xf4, 0x37, 0x4f, 0x38, 0x33, 0x9f, 0x71, 0xdc, + 0xc4, 0x4c, 0x96, 0xb0, 0x8a, 0x86, 0xe5, 0x8d, 0xd2, 0x44, 0xe3, 0x18, 0xcb, 0x81, 0xa6, 0x7c, + 0xaf, 0x8e, 0xfb, 0x41, 0x6e, 0xc5, 0x82, 0xf0, 0x51, 0xb7, 0x0f, 0x23, 0x9b, 0x77, 0xed, 0x9a, + 0x06, 0x6b, 0x77, 0x7c, 0x8e, 0xc4, 0xdf, 0x50, 0xa0, 0xd2, 0x81, 0x3e, 0x65, 0xbe, 0xe5, 0x51, + 0x79, 0x93, 0x24, 0x8e, 0xb3, 0xb5, 0x25, 0x48, 0x76, 0x0e, 0x75, 0x94, 0xef, 0x9a, 0x9d, 0xc7, + 0x95, 0x08, 0xca, 0x35, 0x6b, 0x73, 0xbc, 0x4b, 0x93, 0x7a, 0x93, 0x55, 0x2d, 0xe4, 0x5f, 0xcf, + 0x11, 0x31, 0x94, 0xb2, 0x5a, 0x05, 0x80, 0xd7, 0x59, 0x79, 0x14, 0x8a, 0x2a, 0xb9, 0xd7, 0x3d, + 0x33, 0x69, 0xa9, 0xab, 0xaa, 0xb8, 0x4c, 0x73, 0xb6, 0x71, 0x2c, 0x6f, 0x31, 0x82, 0x03, 0x3b, + 0x30, 0x82, 0x03, 0x37, 0x02, 0x01, 0x01, 0x30, 0x81, 0xa4, 0x30, 0x81, 0x96, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x6e, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x41, 0x70, + 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 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, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0f, 0x43, 0x4d, 0x53, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x02, 0x09, 0x00, 0xdd, 0x3f, 0x19, 0x90, 0xd8, 0x99, 0xba, 0x86, 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, 0x35, 0x31, 0x31, 0x30, 0x34, + 0x30, 0x31, 0x35, 0x36, 0x34, 0x30, 0x5a, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x30, 0x9e, 0x11, 0x91, 0x83, 0x14, 0xd8, 0xb9, + 0xd6, 0x24, 0x8e, 0x04, 0x7e, 0x31, 0xa7, 0x66, 0xf7, 0x3c, 0x96, 0xc6, 0x23, 0x60, 0x2e, 0xec, + 0x9e, 0x0c, 0xda, 0xab, 0x25, 0x58, 0x02, 0xf2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xbc, 0x5a, 0x74, 0xac, 0x24, + 0x13, 0xa5, 0xa3, 0xfb, 0x61, 0xfb, 0x19, 0x7a, 0x3f, 0x7b, 0x46, 0x5a, 0xcd, 0x8a, 0x92, 0x23, + 0xeb, 0xd0, 0xdf, 0xf2, 0x05, 0xbe, 0x02, 0xf9, 0xd5, 0x81, 0xca, 0x16, 0xf9, 0xd9, 0x63, 0x9e, + 0x19, 0xb8, 0xea, 0x1d, 0x51, 0x2c, 0xfc, 0x65, 0x0c, 0x67, 0x31, 0x5d, 0xa2, 0x87, 0x40, 0xa2, + 0x58, 0x57, 0x35, 0xe1, 0xa2, 0xc8, 0x25, 0xe4, 0x79, 0xd1, 0xc2, 0x76, 0x26, 0x20, 0x11, 0x76, + 0x38, 0xc8, 0xa1, 0x08, 0x98, 0x7c, 0x28, 0x8a, 0x14, 0x23, 0x89, 0xfa, 0xe6, 0x55, 0xaf, 0x47, + 0x1f, 0xe8, 0x5c, 0xc4, 0x0b, 0x88, 0x27, 0x75, 0xf5, 0x2d, 0x2c, 0x63, 0x63, 0x7b, 0xd3, 0x2b, + 0xd2, 0xb1, 0x4d, 0xf5, 0xd3, 0xa9, 0xdc, 0xc1, 0x34, 0x9d, 0xb8, 0x44, 0xae, 0xa3, 0x41, 0xd7, + 0x1e, 0x02, 0xff, 0x06, 0x3d, 0x8b, 0x3b, 0x01, 0xc6, 0xa9, 0x0f, 0x7a, 0x59, 0x03, 0x05, 0x2a, + 0xcf, 0x19, 0xc1, 0xd2, 0xea, 0x30, 0x3f, 0xbd, 0x83, 0x80, 0x26, 0xd7, 0x73, 0x32, 0x00, 0x8d, + 0x4f, 0x69, 0xaa, 0xf0, 0x39, 0x3f, 0xae, 0x46, 0xfc, 0x19, 0x7e, 0x62, 0xd2, 0xc8, 0x59, 0xa2, + 0xd1, 0x23, 0xa2, 0xab, 0xdd, 0x5b, 0xbc, 0xa9, 0x4d, 0x8c, 0x3a, 0xa4, 0x9d, 0x8e, 0x80, 0x0c, + 0x2b, 0x2d, 0x26, 0x27, 0xb7, 0xf2, 0xb9, 0x19, 0xc5, 0x8e, 0x17, 0x44, 0xb2, 0x19, 0x29, 0x3b, + 0x25, 0x7e, 0x76, 0xf8, 0x97, 0x85, 0xbc, 0x78, 0xa4, 0x41, 0xcb, 0x10, 0xed, 0xd7, 0x8c, 0x4c, + 0x56, 0x44, 0xfc, 0x7c, 0xa8, 0x98, 0xff, 0xa5, 0xef, 0x21, 0xe4, 0xc2, 0x2b, 0xaf, 0xfb, 0xb2, + 0xcb, 0x4c, 0x63, 0x19, 0x53, 0xae, 0xc4, 0xbc, 0x44, 0x31, 0xcb, 0x06, 0x2f, 0x01, 0x2b, 0x6b, + 0x7e, 0xd8, 0x24, 0x76, 0x16, 0x74, 0xa5, 0xb2, 0x46, 0xff, 0x14, 0xde, 0xc8, 0xe5, 0xfc, 0xeb, + 0xfa, 0xb8, 0xc2, 0x39, 0x9d, 0xf6, 0xdd, 0xbb, 0xba, 0x7d, 0x2d, 0x49, 0x4c, 0x7d, 0x87, 0xe2, + 0x0a, 0xb7, 0x52, 0xb5, 0x3d, 0x9d, 0x02, 0xf2, 0x04, 0x3d, 0x9b, 0x8b, 0x04, 0xe8, 0x84, 0x50, + 0x19, 0xb7, 0xfa, 0x4f, 0x9f, 0xa6, 0x00, 0x06, 0x2a, 0x44, 0xb2, 0x58, 0x91, 0x2f, 0xde, 0xd6, + 0x25, 0xcc, 0xd5, 0x68, 0x04, 0x51, 0xb1, 0x0f, 0x08, 0x41, 0xdd, 0xea, 0x16, 0x70, 0xbd, 0x5a, + 0xbc, 0x05, 0x60, 0xbc, 0xd4, 0x67, 0x62, 0xe2, 0xc3, 0xc0, 0x79, 0xdf, 0x49, 0xd7, 0x52, 0x62, + 0xde, 0xce, 0x68, 0x5c, 0x32, 0x9b, 0xd3, 0xb8, 0xef, 0x62, 0x7b, 0x4b, 0x0e, 0x15, 0xae, 0x92, + 0xfb, 0x06, 0x36, 0xb9, 0x05, 0x72, 0x2f, 0x01, 0x55, 0x70, 0x2b, 0x09, 0x54, 0xe1, 0x70, 0x15, + 0xab, 0x24, 0xcb, 0x07, 0x4c, 0x7e, 0xde, 0x38, 0xb2, 0x03, 0x56, 0xdb, 0x2f, 0x8c, 0x3b, 0xe5, + 0x5e, 0x1a, 0xbb, 0x90, 0x08, 0x55, 0xb2, 0x3d, 0xd9, 0x6f, 0xe8, 0x81, 0x08, 0x04, 0x5e, 0x82, + 0x84, 0x7e, 0x9c, 0x3f, 0x5a, 0x66, 0x6f, 0x6c, 0xc6, 0x98, 0x82, 0x27, 0xb6, 0x49, 0x7b, 0x14, + 0x07, 0x9d, 0x20, 0x61, 0x9d, 0xd9, 0x3d, 0xd0, 0x71, 0x0c, 0x72, 0x82, 0x50, 0xac, 0x61, 0xcd, + 0xc5, 0xc6, 0xc9, 0x90, 0xe2, 0x92, 0x5b, 0x02, 0x73, 0xda, 0x98, 0x2e, 0x21, 0x1e, 0x66, 0x79, + 0x83, 0x2e, 0x1d, 0x66, 0x0e, 0x2b, 0x6d, 0x42, 0x7d, 0xf4, 0x0a, 0xd3, 0xa1, 0x9b, 0x7f, 0x61, + 0xa7, 0x13, 0x3a, 0xa4, 0x6e, 0x0d, 0x0b, 0xbf, 0x42, 0x32, 0xf7, 0xca, 0x0e, 0x96, 0x0a, 0xcb, + 0x9a, 0x0a, 0x6a, 0x24, 0x8c, 0x43, 0x76, 0x0e, 0xa8, 0x71, 0xcd, 0x3f, 0xc4, 0x85, 0x46, 0x50, + 0xb9, 0x65, 0x43, 0x49, 0xae, 0x31, 0x25, 0x76, 0x4b, 0xfb, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +#endif /* si_89_cms_hash_agility_h */ diff --git a/OSX/sec/Security/Regressions/secitem/si-90-emcs.m b/OSX/sec/Security/Regressions/secitem/si-90-emcs.m new file mode 100644 index 00000000..771973f6 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-90-emcs.m @@ -0,0 +1,62 @@ +#define __KEYCHAINCORE__ 1 + +#include +#include + +#include "SecEMCSPriv.h" +#include "Security_regressions.h" + +static void tests(void) +{ + + @autoreleasepool { + NSDictionary *idmsData = SecEMCSCreateNewiDMSKey(NULL, NULL, @"1234", NULL, NULL); + [idmsData autorelease]; + ok(idmsData); + + NSData *emcsKey = SecEMCSCreateDerivedEMCSKey(idmsData, @"1234", NULL); + [emcsKey autorelease]; + ok(emcsKey, "emcs key"); + + /* + * change password + */ + + NSDictionary *newIdmsData = SecEMCSCreateNewiDMSKey(NULL, emcsKey, @"4321", NULL, NULL); + [newIdmsData autorelease]; + + NSData *newEmcsKey = SecEMCSCreateDerivedEMCSKey(newIdmsData, @"4321", NULL); + [newEmcsKey autorelease]; + ok(newEmcsKey, "new emcs key"); + + ok([newEmcsKey isEqualToData:emcsKey], "key same"); + } + + @autoreleasepool { + + NSDictionary *fakeIdmsData = @{ + @"iter" : @1000, + @"salt" : [NSData dataWithBytes:"\x7b\x30\x67\x4c\x01\x34\xae\xda\xaf\x4a\x34\xda\x68\x5b\x0b\x75" length:16], + @"wkey" : [NSData dataWithBytes:"\xa1\x15\xee\x24\xdf\x39\xd6\x96\xb9\x57\x65\xa0\xec\x7d\x80\x4c\xd1\xb3\xc0\x31\x38\xc0\x3a\x38" length: 24], + }; + + NSData *data = SecEMCSCreateDerivedEMCSKey(fakeIdmsData, @"1234", NULL); + ok(data, "KDF1"); + + ok([data isEqualToData:[NSData dataWithBytes:"\xa4\x42\x8b\xb0\xb8\x20\xdb\xfa\x58\x84\xab\xe3\x52\x93\xeb\x10" length:16]], "same"); + + [data release]; + + data = SecEMCSCreateDerivedEMCSKey(fakeIdmsData, @"4321", NULL); + ok(!data, "KFD2"); + } +} + +int si_90_emcs(int argc, char *const *argv) +{ + plan_tests(7); + + tests(); + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.c b/OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.c new file mode 100644 index 00000000..aa101508 --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.c @@ -0,0 +1,105 @@ +/* + * 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 +#include +#include +#include + +#include "utilities/SecCFRelease.h" +#include "utilities/SecCFWrappers.h" + +#include "Security_regressions.h" + + +#include "si-91-sectrust-ast2.h" + +static void tests(void) +{ + SecTrustRef trust = NULL; + SecPolicyRef policy = NULL; + SecCertificateRef cert0 = NULL, cert1 = NULL, rootcert = NULL; + SecTrustResultType trustResult; + CFDictionaryRef allowTestRoot = NULL; + + isnt(cert0 = SecCertificateCreateWithBytes(NULL, _ast2TestLeaf, sizeof(_ast2TestLeaf)), NULL, "create cert0"); + isnt(cert1 = SecCertificateCreateWithBytes(NULL, _AppleTestServerAuthCA, sizeof(_AppleTestServerAuthCA)), NULL, "create cert1"); + isnt(rootcert = SecCertificateCreateWithBytes(NULL, _AppleTestRoot, sizeof(_AppleTestRoot)), NULL, "create root cert"); + + const void *v_certs[] = { cert0, cert1 }; + CFArrayRef certs = CFArrayCreate(NULL, v_certs, sizeof(v_certs)/sizeof(*v_certs), &kCFTypeArrayCallBacks); + CFArrayRef anchor_certs = CFArrayCreate(NULL, (const void**)&rootcert, 1, &kCFTypeArrayCallBacks); + + /* Set explicit verify date: 15 Dec 2015 */ + CFDateRef date = NULL; + isnt(date = CFDateCreate(NULL, 471907305.0), NULL, "Create verify date"); + + /* Evaluate test certs with production policy. Should fail. */ + isnt(policy = SecPolicyCreateAppleAST2Service(CFSTR("ast2.test.domain.here"), NULL), NULL, "create prod policy"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); + ok_status(SecTrustSetAnchorCertificates(trust, anchor_certs), "set anchor"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trustResult is kSecTrustResultRecoverableTrustFailure"); + + CFReleaseSafe(trust); + CFReleaseSafe(policy); + + /* Evaluate test certs with test root allowed */ + CFStringRef key = CFSTR("AppleServerAuthenticationAllowUATAST2"); + isnt(allowTestRoot = CFDictionaryCreate(NULL, (const void **)&key, (const void **)&kCFBooleanTrue, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks), + NULL, "create context dictionary"); + isnt(policy = SecPolicyCreateAppleAST2Service(CFSTR("ast2.test.domain.here"), allowTestRoot), NULL, "create test policy"); + + ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); + ok_status(SecTrustSetAnchorCertificates(trust, anchor_certs), "set anchor"); + ok_status(SecTrustSetVerifyDate(trust, date), "set date"); + + ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); + is_status(trustResult, kSecTrustResultUnspecified, "trustResult is kSecTrustResultUnspecified"); + is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); + + CFReleaseSafe(date); + CFReleaseSafe(trust); + CFReleaseSafe(policy); + CFReleaseSafe(certs); + CFReleaseSafe(cert0); + CFReleaseSafe(cert1); + CFReleaseSafe(anchor_certs); + CFReleaseSafe(rootcert); + CFReleaseSafe(key); + +} + + +int si_91_sectrust_ast2(int argc, char *const *argv) +{ + plan_tests(18); + + tests(); + + return 0; +} diff --git a/OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.h b/OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.h new file mode 100644 index 00000000..1bccf35a --- /dev/null +++ b/OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.h @@ -0,0 +1,265 @@ +/* + * 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 si_91_sectrust_ast2_h +#define si_91_sectrust_ast2_h + +#include + +/* subject:/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ +unsigned char _AppleTestRoot[1232]={ + 0x30,0x82,0x04,0xCC,0x30,0x82,0x03,0xB4,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x3D, + 0x00,0x4B,0x90,0x3E,0xDE,0xE0,0xD0,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x05,0x05,0x00,0x30,0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73, + 0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30, + 0x1E,0x17,0x0D,0x31,0x35,0x30,0x34,0x32,0x32,0x30,0x32,0x31,0x35,0x34,0x38,0x5A, + 0x17,0x0D,0x33,0x35,0x30,0x32,0x30,0x39,0x32,0x31,0x34,0x30,0x33,0x36,0x5A,0x30, + 0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13, + 0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49, + 0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03,0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70, + 0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F, + 0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x1B,0x30,0x19,0x06, + 0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65, + 0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0F,0x00, + 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xC7,0xD1,0x43,0x53,0x7F,0x0D,0x88, + 0x6B,0xE6,0xB1,0x67,0x9D,0xEE,0x67,0xB6,0xE7,0x77,0x12,0x81,0xC4,0xDF,0x24,0x6B, + 0x7A,0x75,0x24,0xF7,0x01,0x09,0xCE,0x34,0x92,0xF5,0x38,0x08,0x42,0x7E,0xEC,0x9D, + 0xF2,0x5D,0x38,0x91,0xB4,0x93,0x98,0x35,0x11,0x3C,0x98,0x00,0x77,0xD9,0xD7,0xF3, + 0x4A,0xF8,0xF0,0xBC,0xEB,0x97,0x5D,0x4B,0x61,0x2E,0xFB,0xC5,0xCC,0x68,0xB7,0x6D, + 0x69,0x10,0xCC,0xA5,0x61,0x78,0xA8,0x81,0x02,0x9E,0xE7,0x63,0xC5,0xFF,0x29,0x22, + 0x82,0x68,0xAA,0xAA,0x0E,0xFB,0xA9,0xD8,0x16,0x73,0x25,0xBF,0x9D,0x08,0x62,0x2F, + 0x78,0x04,0xF6,0xF6,0x44,0x07,0x37,0x6E,0x99,0x1B,0x93,0xD8,0x7F,0xEE,0x72,0xDE, + 0xE8,0x32,0xF6,0x6D,0x78,0x04,0xA0,0xA8,0x21,0x26,0x8A,0x32,0xE3,0xB1,0x65,0x85, + 0xA1,0x7B,0x1A,0xA9,0x02,0xB2,0xBB,0xEE,0xDD,0xDD,0x8F,0x41,0x49,0xC8,0x3F,0xDC, + 0x1E,0xDF,0x21,0xA3,0x95,0x99,0xBB,0xFC,0x29,0xBA,0x40,0x43,0xB9,0x1C,0xCD,0xC9, + 0x21,0x45,0x73,0xAD,0xFF,0xFD,0xA2,0x6C,0x5C,0x3B,0x1C,0x37,0x91,0x34,0x8E,0x5C, + 0xD3,0xD5,0x03,0x58,0x28,0xC7,0xF2,0x76,0x6F,0x11,0xC0,0xB5,0xBD,0x7E,0xEF,0x23, + 0xB3,0x3D,0xB8,0xBD,0x38,0x66,0x8C,0xF2,0x78,0x95,0xC1,0x8B,0x32,0x65,0x3A,0x9B, + 0x49,0x1A,0x5C,0x41,0x3C,0xC6,0x85,0x50,0xEC,0x85,0xF0,0x59,0x17,0x81,0xE8,0x96, + 0xE8,0x6A,0xCC,0xB3,0xC7,0x46,0xBF,0x81,0x48,0xD1,0x09,0x1B,0xBC,0x73,0x1E,0xD7, + 0xE8,0x27,0xA8,0x49,0x48,0xA2,0x1C,0x41,0x1D,0x02,0x03,0x01,0x00,0x01,0xA3,0x82, + 0x01,0x7A,0x30,0x82,0x01,0x76,0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04, + 0x14,0x59,0xB8,0x2B,0x94,0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52,0x23,0x33, + 0xC9,0x59,0xC3,0x54,0x98,0x30,0x0F,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04, + 0x05,0x30,0x03,0x01,0x01,0xFF,0x30,0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30, + 0x16,0x80,0x14,0x59,0xB8,0x2B,0x94,0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52, + 0x23,0x33,0xC9,0x59,0xC3,0x54,0x98,0x30,0x82,0x01,0x11,0x06,0x03,0x55,0x1D,0x20, + 0x04,0x82,0x01,0x08,0x30,0x82,0x01,0x04,0x30,0x82,0x01,0x00,0x06,0x09,0x2A,0x86, + 0x48,0x86,0xF7,0x63,0x64,0x05,0x01,0x30,0x81,0xF2,0x30,0x2A,0x06,0x08,0x2B,0x06, + 0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1E,0x68,0x74,0x74,0x70,0x73,0x3A,0x2F,0x2F, + 0x77,0x77,0x77,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x61,0x70, + 0x70,0x6C,0x65,0x63,0x61,0x2F,0x30,0x81,0xC3,0x06,0x08,0x2B,0x06,0x01,0x05,0x05, + 0x07,0x02,0x02,0x30,0x81,0xB6,0x0C,0x81,0xB3,0x52,0x65,0x6C,0x69,0x61,0x6E,0x63, + 0x65,0x20,0x6F,0x6E,0x20,0x74,0x68,0x69,0x73,0x20,0x63,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x65,0x20,0x62,0x79,0x20,0x61,0x6E,0x79,0x20,0x70,0x61,0x72, + 0x74,0x79,0x20,0x61,0x73,0x73,0x75,0x6D,0x65,0x73,0x20,0x61,0x63,0x63,0x65,0x70, + 0x74,0x61,0x6E,0x63,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x68,0x65, + 0x6E,0x20,0x61,0x70,0x70,0x6C,0x69,0x63,0x61,0x62,0x6C,0x65,0x20,0x73,0x74,0x61, + 0x6E,0x64,0x61,0x72,0x64,0x20,0x74,0x65,0x72,0x6D,0x73,0x20,0x61,0x6E,0x64,0x20, + 0x63,0x6F,0x6E,0x64,0x69,0x74,0x69,0x6F,0x6E,0x73,0x20,0x6F,0x66,0x20,0x75,0x73, + 0x65,0x2C,0x20,0x63,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x70, + 0x6F,0x6C,0x69,0x63,0x79,0x20,0x61,0x6E,0x64,0x20,0x63,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x70,0x72,0x61,0x63,0x74,0x69,0x63,0x65, + 0x20,0x73,0x74,0x61,0x74,0x65,0x6D,0x65,0x6E,0x74,0x73,0x2E,0x30,0x0E,0x06,0x03, + 0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x0D,0x06,0x09, + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00, + 0x10,0x5E,0x6C,0x69,0xFC,0xA6,0x0F,0xE2,0x09,0xD5,0x94,0x90,0xA6,0x7C,0x22,0xDC, + 0xEE,0xB0,0x8F,0x24,0x22,0x4F,0xB3,0x67,0xDB,0x32,0xB0,0xD6,0x24,0x87,0xE6,0xF3, + 0xEA,0x9E,0xD0,0x95,0x75,0xAA,0xA7,0x08,0xFF,0xB0,0x35,0xD7,0x1F,0xA3,0xBF,0x89, + 0x55,0x0C,0x1C,0xA4,0xD0,0xF8,0x00,0x17,0x44,0x94,0x36,0x63,0x3B,0x83,0xFE,0x4E, + 0xE5,0xB3,0xEC,0x7B,0x7D,0xCE,0xFE,0xA9,0x54,0xED,0xBB,0x12,0xA6,0x72,0x2B,0xB3, + 0x48,0x00,0xC7,0x8E,0xF5,0x5B,0x68,0xC9,0x24,0x22,0x7F,0xA1,0x4D,0xFC,0x54,0xD9, + 0xD0,0x5D,0x82,0x53,0x71,0x29,0x66,0xCF,0x0F,0x6D,0x32,0xA6,0x3F,0xAE,0x54,0x27, + 0xC2,0x8C,0x12,0x4C,0xF0,0xD6,0xC1,0x80,0x75,0xC3,0x33,0x19,0xD1,0x8B,0x58,0xE6, + 0x00,0x69,0x76,0xE7,0xE5,0x3D,0x47,0xF9,0xC0,0x9C,0xE7,0x19,0x1E,0x95,0xBC,0x52, + 0x15,0xCE,0x94,0xF8,0x30,0x14,0x0B,0x39,0x0E,0x8B,0xAF,0x29,0x30,0x56,0xAF,0x5A, + 0x28,0xAC,0xE1,0x0F,0x51,0x76,0x76,0x9A,0xE7,0xB9,0x7D,0xA3,0x30,0xE8,0xE3,0x71, + 0x15,0xE8,0xBF,0x0D,0x4F,0x12,0x9B,0x65,0xAB,0xEF,0xA4,0xE9,0x42,0xF0,0xD2,0x4D, + 0x20,0x55,0x29,0x88,0x58,0x5C,0x82,0x67,0x63,0x20,0x50,0xC6,0xCA,0x04,0xE8,0xBC, + 0x3D,0x93,0x06,0x21,0xB2,0xC0,0xBF,0x53,0x1E,0xE1,0x8B,0x48,0xA9,0xB9,0xD7,0xE6, + 0x5F,0x4E,0x5A,0x2F,0x43,0xAC,0x35,0xBD,0x26,0x60,0x2F,0x01,0xD5,0x86,0x6B,0x64, + 0xFA,0x67,0x05,0x44,0x55,0x83,0x5B,0x93,0x9C,0x7C,0xA7,0x26,0x4E,0x02,0x2B,0x48, +}; + +/* subject:/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ +/* issuer :/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Test Apple Root CA */ +unsigned char _AppleTestServerAuthCA[1043]={ + 0x30,0x82,0x04,0x0F,0x30,0x82,0x02,0xF7,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x4B, + 0x28,0xA9,0x3B,0x57,0x8B,0xF6,0x26,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x67,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04, + 0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A, + 0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x26,0x30,0x24,0x06,0x03, + 0x55,0x04,0x0B,0x0C,0x1D,0x41,0x70,0x70,0x6C,0x65,0x20,0x43,0x65,0x72,0x74,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69, + 0x74,0x79,0x31,0x1B,0x30,0x19,0x06,0x03,0x55,0x04,0x03,0x0C,0x12,0x54,0x65,0x73, + 0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x52,0x6F,0x6F,0x74,0x20,0x43,0x41,0x30, + 0x1E,0x17,0x0D,0x31,0x35,0x30,0x36,0x30,0x38,0x30,0x37,0x35,0x38,0x34,0x35,0x5A, + 0x17,0x0D,0x32,0x39,0x30,0x33,0x30,0x38,0x30,0x31,0x35,0x33,0x30,0x34,0x5A,0x30, + 0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04,0x03,0x0C,0x23,0x54,0x65,0x73,0x74, + 0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x41,0x75, + 0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x43,0x41,0x31, + 0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C,0x17,0x43,0x65,0x72,0x74,0x69,0x66, + 0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41,0x75,0x74,0x68,0x6F,0x72,0x69,0x74, + 0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C, + 0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13, + 0x02,0x55,0x53,0x30,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,0xC5,0x7B,0x3F,0x48,0xD3,0x62,0x93,0x93,0x7C,0x0C,0x37,0x69, + 0xDB,0x28,0x05,0x40,0x12,0xD7,0x1F,0x0A,0xB8,0xC3,0xBA,0x24,0x39,0x22,0xDC,0x39, + 0x42,0x1F,0xFD,0x93,0x45,0x3C,0x23,0x0B,0x3E,0xB4,0x96,0xA6,0x55,0x59,0xBA,0xC4, + 0x99,0xE7,0x8A,0x5F,0x8F,0xAE,0x66,0xA7,0x28,0xE2,0x9E,0x68,0xD9,0xEC,0x52,0x67, + 0xFE,0xDD,0xBE,0x59,0xB4,0xAD,0x97,0x63,0x64,0xB0,0x08,0x3C,0xBB,0x6E,0xD1,0x29, + 0xD8,0x58,0xA1,0x99,0x6C,0x2F,0x2F,0xB3,0xF5,0x5C,0x59,0xCA,0xA1,0xE6,0x67,0x44, + 0x3C,0x13,0xB4,0xAE,0x0D,0x00,0xC7,0x53,0xB7,0xF5,0x61,0x58,0xD5,0xC8,0x42,0xFC, + 0xE2,0xFD,0xD5,0x39,0x18,0x80,0xE2,0x72,0xBC,0xF8,0xC3,0x9F,0xCB,0xD8,0x2F,0x83, + 0x40,0x9A,0x3E,0x55,0x5E,0x61,0xA9,0xC4,0x81,0x14,0x2B,0x7B,0x19,0x15,0xAD,0x84, + 0x5E,0x80,0xA8,0x67,0x79,0x05,0x16,0x48,0x5C,0xAE,0x1A,0x2B,0x59,0x9F,0xAA,0x62, + 0x0B,0x2F,0x57,0xCD,0xE8,0xA8,0x5D,0x38,0xAD,0x7C,0x90,0x79,0x50,0xAC,0x4D,0x13, + 0xA4,0xA7,0xF3,0x73,0xED,0xD6,0x93,0x45,0xDD,0xA8,0xC6,0xFE,0x03,0x28,0x4D,0x58, + 0xC1,0x8B,0xC1,0x03,0x0E,0xE7,0xDF,0x78,0xDD,0x21,0xC6,0x6D,0x1E,0xA0,0x38,0xD7, + 0xA7,0xD7,0x04,0x8C,0x7F,0xCA,0x15,0xEA,0x88,0xE9,0xAE,0x8D,0x46,0xE0,0x87,0x94, + 0x3E,0x8F,0x53,0x11,0x88,0x23,0x99,0x7B,0x9D,0xD8,0x69,0x1A,0x22,0xAE,0xB5,0x18, + 0xA5,0x9F,0xEA,0x71,0x31,0x0B,0x27,0x93,0x85,0x1D,0xF7,0xA0,0xC3,0x82,0x0A,0x3F, + 0xEE,0xD2,0xD4,0xEF,0x02,0x03,0x01,0x00,0x01,0xA3,0x81,0xB3,0x30,0x81,0xB0,0x30, + 0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xA8,0xCA,0x7A,0x9B,0xA8,0x37, + 0x71,0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2,0x30,0x0F, + 0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x05,0x30,0x03,0x01,0x01,0xFF,0x30, + 0x1F,0x06,0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x59,0xB8,0x2B,0x94, + 0x3A,0x1B,0xBA,0xF1,0x00,0xAE,0xEE,0x50,0x52,0x23,0x33,0xC9,0x59,0xC3,0x54,0x98, + 0x30,0x3B,0x06,0x03,0x55,0x1D,0x1F,0x04,0x34,0x30,0x32,0x30,0x30,0xA0,0x2E,0xA0, + 0x2C,0x86,0x2A,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61, + 0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D, + 0x2F,0x74,0x65,0x73,0x74,0x72,0x6F,0x6F,0x74,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06, + 0x03,0x55,0x1D,0x0F,0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x10,0x06, + 0x0A,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x02,0x0C,0x04,0x02,0x05,0x00,0x30, + 0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,0x05,0x00,0x03,0x82, + 0x01,0x01,0x00,0x11,0x24,0x61,0x2B,0x7C,0x5E,0x67,0x29,0x94,0x14,0x19,0x16,0xD5, + 0xD4,0x7A,0xEE,0x53,0x1A,0x64,0xA2,0x6A,0x2B,0x04,0xE6,0x2C,0xA1,0x08,0xBA,0xCA, + 0x81,0xF5,0x28,0x2A,0xCE,0xD5,0x6B,0x52,0xAC,0xE7,0xBD,0xB3,0x23,0xB9,0x67,0x2C, + 0xC7,0x9E,0x61,0xA1,0xD9,0x6C,0x3F,0x4F,0x55,0xD4,0x75,0xAF,0x44,0xAD,0xF8,0xCE, + 0x58,0xA7,0x2E,0xF8,0x6A,0xF0,0x76,0x51,0x31,0x75,0x4C,0xCA,0xF6,0xC3,0x59,0xC7, + 0xE6,0xAE,0x4A,0x20,0x4E,0x5F,0xB9,0xAB,0x1C,0xB6,0x36,0x25,0x60,0x02,0x32,0x47, + 0x7D,0xA0,0xE2,0x36,0xB3,0x3B,0x40,0x20,0x9E,0x38,0x40,0x1C,0x7E,0x83,0x35,0x9C, + 0x9D,0x8B,0xD1,0xF9,0xEA,0xD4,0xF2,0x83,0xE0,0x30,0xEA,0xC3,0xEE,0x3D,0x76,0x98, + 0x9E,0x0A,0x07,0xB5,0xB6,0xFC,0x38,0x32,0xF6,0x41,0xEF,0x8E,0x25,0x2C,0xE3,0xC7, + 0xA7,0xAD,0x88,0x77,0x4D,0x10,0x1D,0x67,0x50,0x64,0xB0,0x02,0x04,0x2C,0xEA,0x4C, + 0x81,0x33,0xBE,0xF3,0xCD,0x43,0x63,0x97,0x44,0xDF,0xBB,0xC6,0xE2,0x37,0x32,0xF1, + 0xE4,0x19,0x1F,0xF5,0xAE,0xDA,0x05,0xC4,0x0B,0xFA,0x30,0xCA,0x77,0x78,0x65,0xD6, + 0x4F,0x2D,0xFE,0x63,0xD3,0x4C,0x3D,0xA9,0x0E,0xC4,0x0F,0xD6,0xCC,0x2A,0x2D,0x06, + 0x9B,0xDE,0x94,0xF6,0x22,0x2E,0x89,0xCB,0x68,0x4E,0xDE,0x79,0xE5,0x83,0xDE,0x64, + 0x63,0xE9,0x77,0x88,0xF1,0x57,0xF2,0x5C,0xB4,0x77,0x3A,0xC8,0x1F,0x6D,0x80,0x4C, + 0x8B,0x68,0xA5,0xFA,0xAD,0x1F,0x5C,0x8C,0x50,0x27,0xED,0xF7,0x43,0x68,0xAD,0x34, + 0x5E,0xF6,0x74, +}; + +/* subject:/CN=ast2.test.domain.here/OU=IS&T/O=Apple Inc./C=US */ +/* issuer :/CN=Test Apple Server Authentication CA/OU=Certification Authority/O=Apple Inc./C=US */ +unsigned char _ast2TestLeaf[1223]={ + 0x30,0x82,0x04,0xC3,0x30,0x82,0x03,0xAB,0xA0,0x03,0x02,0x01,0x02,0x02,0x08,0x51, + 0x24,0x24,0xE7,0xA6,0xFC,0x66,0x24,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7, + 0x0D,0x01,0x01,0x0B,0x05,0x00,0x30,0x72,0x31,0x2C,0x30,0x2A,0x06,0x03,0x55,0x04, + 0x03,0x0C,0x23,0x54,0x65,0x73,0x74,0x20,0x41,0x70,0x70,0x6C,0x65,0x20,0x53,0x65, + 0x72,0x76,0x65,0x72,0x20,0x41,0x75,0x74,0x68,0x65,0x6E,0x74,0x69,0x63,0x61,0x74, + 0x69,0x6F,0x6E,0x20,0x43,0x41,0x31,0x20,0x30,0x1E,0x06,0x03,0x55,0x04,0x0B,0x0C, + 0x17,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6F,0x6E,0x20,0x41, + 0x75,0x74,0x68,0x6F,0x72,0x69,0x74,0x79,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04, + 0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E,0x31,0x0B,0x30, + 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x1E,0x17,0x0D,0x31,0x35, + 0x31,0x32,0x30,0x39,0x31,0x36,0x30,0x31,0x34,0x31,0x5A,0x17,0x0D,0x31,0x37,0x30, + 0x31,0x30,0x37,0x31,0x36,0x30,0x31,0x34,0x31,0x5A,0x30,0x51,0x31,0x1E,0x30,0x1C, + 0x06,0x03,0x55,0x04,0x03,0x0C,0x15,0x61,0x73,0x74,0x32,0x2E,0x74,0x65,0x73,0x74, + 0x2E,0x64,0x6F,0x6D,0x61,0x69,0x6E,0x2E,0x68,0x65,0x72,0x65,0x31,0x0D,0x30,0x0B, + 0x06,0x03,0x55,0x04,0x0B,0x0C,0x04,0x49,0x53,0x26,0x54,0x31,0x13,0x30,0x11,0x06, + 0x03,0x55,0x04,0x0A,0x0C,0x0A,0x41,0x70,0x70,0x6C,0x65,0x20,0x49,0x6E,0x63,0x2E, + 0x31,0x0B,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x30,0x82,0x01, + 0x22,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,0x05,0x00, + 0x03,0x82,0x01,0x0F,0x00,0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xB8,0x3F, + 0x03,0x68,0x0F,0xEB,0x75,0x69,0x6F,0xAB,0x1A,0x2A,0x5F,0x48,0x97,0x73,0x4A,0x90, + 0xD9,0xB2,0x60,0x88,0x3D,0xD6,0xA3,0x7B,0xFE,0x37,0xF1,0x2B,0x57,0xDB,0xE2,0xFE, + 0xDA,0xE9,0x35,0x90,0x4E,0xC1,0x9B,0xB7,0x07,0x7D,0x0C,0xB7,0xAE,0xAF,0x5C,0xD8, + 0xDC,0xD8,0x5A,0x65,0x4D,0x34,0x11,0xDF,0x75,0x27,0x4F,0xA0,0xC0,0x3B,0xF0,0x85, + 0x16,0xDD,0x25,0x6C,0x21,0x23,0xFA,0xD0,0xF7,0x3D,0x37,0x66,0xF2,0x32,0x10,0x95, + 0xA0,0x36,0xE0,0x33,0xB5,0x4D,0x5A,0x33,0xAC,0xB6,0x2E,0xBC,0x22,0xA5,0x20,0xA7, + 0xA9,0x16,0xE4,0xDB,0xE7,0x42,0xC9,0x6A,0xF7,0xDF,0x55,0xF4,0xC3,0x9C,0x1B,0xE9, + 0x56,0x7F,0xF3,0x1F,0xD7,0x94,0x19,0xB0,0x2B,0xBC,0x4B,0xF8,0xDF,0xB2,0x4A,0xDD, + 0xAA,0x1A,0x67,0xD8,0xEA,0xF7,0x30,0xF8,0xB1,0x6B,0x3C,0xC4,0xF7,0xA2,0x70,0xEF, + 0xAA,0xDD,0x49,0x8A,0x27,0x8E,0x71,0xF7,0xC1,0xFE,0x7B,0xD5,0xF2,0x45,0xC8,0xE4, + 0xA9,0x73,0x53,0x90,0xB0,0xFA,0xA0,0xDE,0x71,0xFF,0x58,0x74,0x2C,0xC4,0xD1,0x54, + 0x14,0xCC,0x00,0xF4,0x95,0xEB,0x81,0x85,0xBB,0xCC,0x3D,0xCF,0x7D,0xF3,0xEE,0x75, + 0xE6,0x82,0xCB,0x93,0x79,0x8F,0xD9,0xED,0xE7,0x45,0x6F,0xA8,0xBE,0xA4,0xDE,0x45, + 0x46,0x38,0x14,0xDC,0x79,0xF6,0x1F,0x64,0xD3,0x05,0x45,0xBF,0x50,0x1B,0x81,0x7E, + 0x6C,0x77,0x1B,0xF2,0xBC,0x57,0xFD,0x25,0x94,0xB4,0x9A,0x0B,0x48,0x59,0x8F,0x8A, + 0x0C,0x8F,0xBD,0x4C,0xE2,0x53,0x49,0xBC,0xC6,0x16,0x99,0xF4,0xE6,0x6F,0x02,0x03, + 0x01,0x00,0x01,0xA3,0x82,0x01,0x7C,0x30,0x82,0x01,0x78,0x30,0x53,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x47,0x30,0x45,0x30,0x43,0x06,0x08,0x2B, + 0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x37,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F, + 0x6F,0x63,0x73,0x70,0x2D,0x75,0x61,0x74,0x2E,0x63,0x6F,0x72,0x70,0x2E,0x61,0x70, + 0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x6F,0x63,0x73,0x70,0x30,0x33,0x2D,0x61, + 0x70,0x70,0x6C,0x65,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75,0x74,0x68,0x30,0x31, + 0x30,0x1D,0x06,0x03,0x55,0x1D,0x0E,0x04,0x16,0x04,0x14,0xC2,0x1E,0xBD,0xED,0x39, + 0xF8,0x62,0x73,0x86,0x05,0xF3,0xBC,0x85,0x73,0xB3,0xA9,0x3C,0x12,0xBA,0xA8,0x30, + 0x0C,0x06,0x03,0x55,0x1D,0x13,0x01,0x01,0xFF,0x04,0x02,0x30,0x00,0x30,0x1F,0x06, + 0x03,0x55,0x1D,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0xA8,0xCA,0x7A,0x9B,0xA8,0x37, + 0x71,0x9E,0x3D,0xEC,0x5A,0xAB,0x66,0x2E,0xDC,0xD7,0x14,0x3D,0x7B,0xF2,0x30,0x49, + 0x06,0x03,0x55,0x1D,0x1F,0x04,0x42,0x30,0x40,0x30,0x3E,0xA0,0x3C,0xA0,0x3A,0x86, + 0x38,0x68,0x74,0x74,0x70,0x3A,0x2F,0x2F,0x63,0x72,0x6C,0x2D,0x75,0x61,0x74,0x2E, + 0x63,0x6F,0x72,0x70,0x2E,0x61,0x70,0x70,0x6C,0x65,0x2E,0x63,0x6F,0x6D,0x2F,0x74, + 0x65,0x73,0x74,0x61,0x70,0x70,0x6C,0x65,0x73,0x65,0x72,0x76,0x65,0x72,0x61,0x75, + 0x74,0x68,0x63,0x61,0x31,0x2E,0x63,0x72,0x6C,0x30,0x0E,0x06,0x03,0x55,0x1D,0x0F, + 0x01,0x01,0xFF,0x04,0x04,0x03,0x02,0x05,0xA0,0x30,0x13,0x06,0x03,0x55,0x1D,0x25, + 0x04,0x0C,0x30,0x0A,0x06,0x08,0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x50, + 0x06,0x03,0x55,0x1D,0x11,0x04,0x49,0x30,0x47,0x82,0x15,0x61,0x73,0x74,0x32,0x2E, + 0x74,0x65,0x73,0x74,0x2E,0x64,0x6F,0x6D,0x61,0x69,0x6E,0x2E,0x68,0x65,0x72,0x65, + 0x82,0x16,0x61,0x73,0x74,0x32,0x2E,0x74,0x65,0x73,0x74,0x2E,0x64,0x6F,0x6D,0x61, + 0x69,0x6E,0x32,0x2E,0x68,0x65,0x72,0x65,0x82,0x16,0x61,0x73,0x74,0x32,0x2E,0x74, + 0x65,0x73,0x74,0x2E,0x64,0x6F,0x6D,0x61,0x69,0x6E,0x33,0x2E,0x68,0x65,0x72,0x65, + 0x30,0x11,0x06,0x0B,0x2A,0x86,0x48,0x86,0xF7,0x63,0x64,0x06,0x1B,0x08,0x02,0x04, + 0x02,0x05,0x00,0x30,0x0D,0x06,0x09,0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, + 0x05,0x00,0x03,0x82,0x01,0x01,0x00,0xA1,0xF3,0x96,0x32,0xD2,0x94,0x78,0x0F,0x03, + 0xF5,0xCF,0x96,0x8F,0xAC,0xDA,0xA9,0x1E,0x39,0xE5,0xCE,0x24,0xFD,0xA6,0x66,0x06, + 0x00,0xBC,0x66,0x69,0xC1,0xE1,0xF2,0x31,0xB6,0x70,0xBB,0xD6,0xCA,0x7A,0xCC,0xCF, + 0x01,0x1E,0x47,0x80,0x60,0x43,0x05,0x48,0x8E,0x33,0xF7,0xA9,0xFD,0xE8,0xB9,0x05, + 0x9F,0x7E,0xD1,0xF2,0xDA,0x13,0x45,0xD9,0x96,0x16,0x64,0xD5,0x74,0x0F,0xBD,0x1C, + 0x95,0x72,0xD6,0x31,0xBD,0xFB,0x66,0xC6,0xC0,0xD4,0x4C,0x52,0x1D,0xFB,0xB0,0x65, + 0x4F,0xF2,0x4C,0x4D,0xF5,0x68,0xD6,0xB5,0x4C,0x14,0xC1,0xFA,0xF1,0xDF,0x70,0x4E, + 0x14,0x07,0x8C,0xD6,0x55,0x66,0x91,0x97,0xE0,0x95,0x46,0x15,0x25,0x9B,0xCA,0xC4, + 0x64,0x10,0xFA,0xB4,0xDF,0xF3,0x2E,0x3A,0x26,0x74,0xFB,0x44,0x8E,0x8A,0xEA,0xC9, + 0x2E,0x31,0xD9,0xA2,0xB3,0xA0,0xAF,0x5E,0x48,0xE1,0x5A,0xEC,0xE0,0xA7,0x3B,0x35, + 0x1C,0x8F,0xFF,0xAA,0x02,0xBB,0x2F,0x95,0x11,0xA8,0x8B,0xE6,0x3D,0x65,0x1B,0xC0, + 0xBD,0x6C,0xCC,0x11,0x0C,0xFE,0xCD,0x0D,0x30,0xF1,0xE7,0x53,0xA4,0x7E,0xAC,0x50, + 0xC9,0x23,0x01,0xEE,0xD3,0xD5,0xE5,0xAC,0x0F,0x04,0x22,0xDA,0x30,0x14,0x25,0x6A, + 0x64,0x7B,0xA9,0x9E,0xB9,0x59,0x07,0x0B,0x0C,0x39,0x88,0x18,0x5B,0x35,0x61,0x31, + 0x3D,0x4E,0xCE,0xD5,0xB3,0x67,0x82,0x88,0x3C,0x10,0x12,0xA6,0xC0,0x08,0xC3,0xA5, + 0x41,0x39,0x69,0xAE,0x84,0x34,0x9C,0xED,0x4A,0xED,0x3A,0x85,0x9D,0x98,0xF7,0x12, + 0xD1,0x1D,0xCD,0x9B,0xC8,0x60,0x57, +}; + +#endif /* si_91_sectrust_ast2_h */ diff --git a/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c b/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c index 25ac732e..0079cb65 100644 --- a/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c +++ b/OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c @@ -52,7 +52,7 @@ static CFTypeRef kSecAccessControlKeyProtection = CFSTR("prot"); -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED static bool aks_consistency_test(bool currentAuthDataFormat, kern_return_t expectedAksResult, SecAccessControlRef access_control, CFDataRef acm_context); static CFDataRef kc_create_auth_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes); static CFDataRef kc_copy_constraints_data(SecAccessControlRef access_control, CFDictionaryRef auth_attributes); @@ -274,7 +274,7 @@ static void tests(void) CFReleaseNull(acl); -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED // AKS consistency test: acl = SecAccessControlCreateWithFlags(allocator, protection, kSecAccessControlUserPresence, &error); @@ -352,7 +352,7 @@ static void tests(void) CFReleaseNull(acl); } -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED static bool aks_consistency_test(bool currentAuthDataFormat, kern_return_t expectedAksResult, SecAccessControlRef access_control, CFDataRef acm_context) { @@ -512,7 +512,7 @@ static CFDataRef kc_copy_constraints_data(SecAccessControlRef access_control, CF int si_77_SecAccessControl(int argc, char *const *argv) { -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED plan_tests(71); #else plan_tests(63); diff --git a/OSX/sec/Security/SecCMS.c b/OSX/sec/Security/SecCMS.c index a442f863..e08a1a35 100644 --- a/OSX/sec/Security/SecCMS.c +++ b/OSX/sec/Security/SecCMS.c @@ -411,7 +411,7 @@ static OSStatus SecCMSVerifySignedData_internal(CFDataRef message, CFDataRef det out, status = errSecAuthFailed); } - #if 0 +#if 0 if (nsigners > 1) trustrefs = CFArrayCreateMutable(kCFAllocatorDefault, nsigners, &kCFTypeArrayCallBacks); diff --git a/OSX/sec/Security/SecCertificate.c b/OSX/sec/Security/SecCertificate.c index b342758c..acbd1466 100644 --- a/OSX/sec/Security/SecCertificate.c +++ b/OSX/sec/Security/SecCertificate.c @@ -68,6 +68,11 @@ #include "SecBase64.h" #include "AppleBaselineEscrowCertificates.h" #include +#include + +/* The minimum key sizes necessary to not be considered "weak" */ +#define MIN_RSA_KEY_SIZE 128 // 1024-bit +#define MIN_EC_KEY_SIZE 20 // 160-bit typedef struct SecCertificateExtension { DERItem extnID; @@ -192,7 +197,7 @@ struct __SecCertificate { SecCertificateExtension *_extensions; /* Optional cached fields. */ - SecKeyRef _pubKey; + SecKeyRef _pubKey; /* never set, never used */ CFDataRef _der_data; CFArrayRef _properties; CFDataRef _serialNumber; @@ -4941,6 +4946,31 @@ SecKeyRef SecCertificateCopyPublicKey(SecCertificateRef certificate) &keyData1); } +bool SecCertificateIsWeak(SecCertificateRef certificate) { + bool weak = true; + SecKeyRef pubKey = NULL; +#if SECTRUST_OSX + require_quiet(pubKey = SecCertificateCopyPublicKey_ios(certificate), out); +#else + require_quiet(pubKey = SecCertificateCopyPublicKey(certificate) ,out); +#endif + size_t size = SecKeyGetBlockSize(pubKey); + switch (SecKeyGetAlgorithmIdentifier(pubKey)) { + case kSecRSAAlgorithmID: + if (MIN_RSA_KEY_SIZE <= size) weak = false; + break; + case kSecECDSAAlgorithmID: + if (MIN_EC_KEY_SIZE <= size) weak = false; + break; + default: + weak = true; + } + +out: + CFReleaseSafe(pubKey); + return weak; +} + CFDataRef SecCertificateGetSHA1Digest(SecCertificateRef certificate) { if (!certificate->_sha1Digest) { certificate->_sha1Digest = diff --git a/OSX/sec/Security/SecCertificate.h b/OSX/sec/Security/SecCertificate.h index 0979efb5..aea0830a 100644 --- a/OSX/sec/Security/SecCertificate.h +++ b/OSX/sec/Security/SecCertificate.h @@ -83,6 +83,7 @@ CFDataRef SecCertificateCopyData(SecCertificateRef certificate) @result A CFStringRef which the caller should CFRelease() once it's no longer needed. */ +__nullable CFStringRef SecCertificateCopySubjectSummary(SecCertificateRef certificate) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0); diff --git a/OSX/sec/Security/SecCertificateInternal.h b/OSX/sec/Security/SecCertificateInternal.h index e038fd1b..750faa96 100644 --- a/OSX/sec/Security/SecCertificateInternal.h +++ b/OSX/sec/Security/SecCertificateInternal.h @@ -329,6 +329,8 @@ OSStatus SecCertificateParseGeneralNameContentProperty(DERTag tag, OSStatus SecCertificateParseGeneralNames(const DERItem *generalNames, void *context, parseGeneralNameCallback callback); +bool SecCertificateIsWeak(SecCertificateRef certificate); + __END_DECLS #endif /* !_SECURITY_SECCERTIFICATEINTERNAL_H_ */ diff --git a/OSX/sec/Security/SecEMCS.m b/OSX/sec/Security/SecEMCS.m new file mode 100644 index 00000000..1aa12152 --- /dev/null +++ b/OSX/sec/Security/SecEMCS.m @@ -0,0 +1,273 @@ +/* + * 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@ + */ + +#define __KEYCHAINCORE__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "SecEMCSPriv.h" + +static CFStringRef kiDMSSalt = CFSTR("salt"); +static CFStringRef kiDMSIterrations = CFSTR("iter"); +static CFStringRef kiDMSWrapEMCSKey = CFSTR("wkey"); + +#define MIN_ITERATIONS 1000 +#define MIN_SALTLEN 16 +#define KEY_LENGTH 16 + +/* + * + */ + +static CFDataRef +CopyWrappedKey(CFDataRef wrappingKey, CFDataRef unwrappedKey) +{ + const struct ccmode_ecb *ecb_mode = ccaes_ecb_encrypt_mode(); + ccecb_ctx_decl(ccecb_context_size(ecb_mode), key); + CFMutableDataRef wrappedKey = NULL; + + require(CFDataGetLength(wrappingKey) == KEY_LENGTH, out); + + ccecb_init(ecb_mode, key, CFDataGetLength(wrappingKey), CFDataGetBytePtr(wrappingKey)); + + wrappedKey = CFDataCreateMutableWithScratch(NULL, ccwrap_wrapped_size(CFDataGetLength(unwrappedKey))); + require(wrappingKey, out); + + size_t obytes = 0; + int wrap_status = ccwrap_auth_encrypt(ecb_mode, key, CFDataGetLength(unwrappedKey), CFDataGetBytePtr(unwrappedKey), + &obytes, CFDataGetMutableBytePtr(wrappedKey)); + if (wrap_status == 0) { + assert(obytes == (size_t)CFDataGetLength(wrappedKey)); + } else { + CFReleaseNull(wrappedKey); + goto out; + } + + out: + ccecb_ctx_clear(ccecb_context_size(ecb_mode), key); + return wrappedKey; +} + +static CFDataRef +CopyUnwrappedKey(CFDataRef wrappingKey, CFDataRef wrappedKey) +{ + const struct ccmode_ecb *ecb_mode = ccaes_ecb_decrypt_mode(); + ccecb_ctx_decl(ccecb_context_size(ecb_mode), key); + CFMutableDataRef unwrappedKey = NULL; + + require(CFDataGetLength(wrappedKey) >= CCWRAP_SEMIBLOCK, out); + require(CFDataGetLength(wrappingKey) == KEY_LENGTH, out); + + ccecb_init(ecb_mode, key, CFDataGetLength(wrappingKey), CFDataGetBytePtr(wrappingKey)); + + unwrappedKey = CFDataCreateMutableWithScratch(CFAllocatorSensitive(), ccwrap_unwrapped_size(CFDataGetLength(wrappedKey))); + require(unwrappedKey, out); + + size_t obytes = 0; + int unwrap_status = ccwrap_auth_decrypt(ecb_mode, key, CFDataGetLength(wrappedKey), CFDataGetBytePtr(wrappedKey), + &obytes, CFDataGetMutableBytePtr(unwrappedKey)); + if (unwrap_status == 0) { + assert(obytes == (size_t)CFDataGetLength(unwrappedKey)); + } else { + CFReleaseNull(unwrappedKey); + goto out; + } + + out: + ccecb_ctx_clear(ccecb_context_size(ecb_mode), key); + return unwrappedKey; +} + +/* + * + */ + +static CFDataRef +CreateDerivedKey(CFDataRef salt, long iterations, NSString *managedCredential) +{ + if (iterations < MIN_ITERATIONS || CFDataGetLength(salt) < MIN_SALTLEN) + return NULL; + + /* + * Assume users use the same normalization rules always + */ + + CFIndex strLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength((__bridge CFStringRef)managedCredential), kCFStringEncodingUTF8); + strLength += 1; + char buffer[strLength]; + if (!CFStringGetCString((__bridge CFStringRef)managedCredential, buffer, strLength, kCFStringEncodingUTF8)) { + return NULL; + } + + + CFMutableDataRef key = CFDataCreateMutable(CFAllocatorSensitive(), KEY_LENGTH); + if (key == NULL) { + memset_s(buffer, strLength, 0, strLength); + return NULL; + } + + CFDataSetLength(key, KEY_LENGTH); + + int ret; + ret = ccpbkdf2_hmac(ccsha256_di(), + strlen(buffer), buffer, + CFDataGetLength(salt), CFDataGetBytePtr(salt), + iterations, + KEY_LENGTH, CFDataGetMutableBytePtr(key)); + memset_s(buffer, strLength, 0, strLength); + if (ret) { + CFRelease(key); + return NULL; + } + return key; +} + + +/* + * Given a dictionary stored in iDMS and a passcode, return a crypto key + */ + +NSData * +SecEMCSCreateDerivedEMCSKey(NSDictionary *iDMSData, NSString *managedCredential, NSError **error) +{ + CFDataRef key = NULL, emcsKey = NULL; + CFDataRef userDerivedKey = NULL; + CFNumberRef number = NULL; + CFDataRef salt = NULL; + long iterations; + + salt = CFDictionaryGetValue((__bridge CFDictionaryRef)iDMSData, kiDMSSalt); + number = CFDictionaryGetValue((__bridge CFDictionaryRef)iDMSData, kiDMSIterrations); + emcsKey = CFDictionaryGetValue((__bridge CFDictionaryRef)iDMSData, kiDMSWrapEMCSKey); + + /* validate parameters */ + if (!isData(salt) || !isNumber(number) || !isData(emcsKey)) + return NULL; + + if (!CFNumberGetValue(number, kCFNumberLongType, &iterations)) + return NULL; + + userDerivedKey = CreateDerivedKey(salt, iterations, managedCredential); + if (userDerivedKey == NULL) + return NULL; + + key = CopyUnwrappedKey(userDerivedKey, emcsKey); + CFRelease(userDerivedKey); + + return (__bridge NSData *)key; +} + +/* + * Return a dictionary to be stored in iDMS + */ + +NSDictionary * +SecEMCSCreateNewiDMSKey(NSDictionary *options, + NSData *oldEMCSKey, + NSString *managedCredential, + NSData **emcsKey, + NSError **error) +{ + CFMutableDataRef salt = NULL; + const long iter = MIN_ITERATIONS; + CFDataRef wrappedEMCSKey = NULL; + CFMutableDataRef localEmcsKey = NULL; + CFNumberRef iterations = NULL; + CFDataRef userDerivedKey = NULL; + CFDictionaryRef key = NULL; + + if (emcsKey) + *emcsKey = NULL; + + if (oldEMCSKey) { + if (CFGetTypeID(oldEMCSKey) != CFDataGetTypeID()) + return NULL; + if (CFDataGetLength((__bridge CFDataRef)oldEMCSKey) != KEY_LENGTH) + return NULL; + } + + salt = CFDataCreateMutableWithScratch(NULL, MIN_SALTLEN); + if (salt == NULL) + goto out; + + if (SecRandomCopyBytes(NULL, CFDataGetLength(salt), CFDataGetMutableBytePtr(salt)) != 0) + goto out; + + + iterations = CFNumberCreate(NULL, kCFNumberLongType, &iter); + if (iterations == NULL) + goto out; + + if (oldEMCSKey) { + localEmcsKey = CFDataCreateMutableCopy(CFAllocatorSensitive(), 0, (__bridge CFDataRef)oldEMCSKey); + } else { + localEmcsKey = CFDataCreateMutableWithScratch(CFAllocatorSensitive(), KEY_LENGTH); + if (localEmcsKey == NULL) + goto out; + if (SecRandomCopyBytes(NULL, CFDataGetLength(localEmcsKey), CFDataGetMutableBytePtr(localEmcsKey)) != 0) + goto out; + } + + userDerivedKey = CreateDerivedKey(salt, iter, managedCredential); + if (userDerivedKey == NULL) + goto out; + + wrappedEMCSKey = CopyWrappedKey(userDerivedKey, localEmcsKey); + CFRelease(userDerivedKey); + if (wrappedEMCSKey == NULL) + goto out; + + const void *keys[] = { + kiDMSSalt, + kiDMSIterrations, + kiDMSWrapEMCSKey, + }; + const void *values[] = { + salt, + iterations, + wrappedEMCSKey, + }; + _Static_assert(sizeof(keys)/sizeof(keys[0]) == sizeof(values)/sizeof(values[0]), "keys != values"); + + key = CFDictionaryCreate(NULL, keys, values, sizeof(keys)/sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (key && emcsKey) + *emcsKey = CFRetain(localEmcsKey); + + out: + CFReleaseNull(salt); + CFReleaseNull(iterations); + CFReleaseNull(localEmcsKey); + CFReleaseNull(wrappedEMCSKey); + + return (__bridge NSDictionary *)key; +} diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.h b/OSX/sec/Security/SecEMCSPriv.h similarity index 54% rename from OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.h rename to OSX/sec/Security/SecEMCSPriv.h index 9fe87bfa..fc647c80 100644 --- a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.h +++ b/OSX/sec/Security/SecEMCSPriv.h @@ -22,33 +22,20 @@ */ -/*! - @header SOSViewManager.h - View creation and management. - */ - -#ifndef _SEC_SOSVIEWMANAGER_H_ -#define _SEC_SOSVIEWMANAGER_H_ - -#include - -__BEGIN_DECLS - -extern const CFStringRef kSOSViewNamesChildInfoKey; -extern const CFStringRef kSOSFunctionChildInfoKey; -extern const CFStringRef kSOSViewNamesChildInfoKey; - -typedef struct __OpaqueSOSViewManager *SOSViewManagerRef; - -//typedef struct __OpaqueSOSViewManager *SOSViewChildRef; - -//SOSViewManagerRef SOSViewManagerCreate(CFAllocatorRef allocator, CFErrorRef *error); -bool SOSViewManagerSetChildren(SOSViewManagerRef vmgr, CFArrayRef children, CFErrorRef *error); +#ifndef SecEMCS_h +#define SecEMCS_h +NSData * +SecEMCSCreateDerivedEMCSKey(NSDictionary *iDMSData, NSString *passcode, NSError **error); -//SOSViewQueryRef SOSViewManagerCopyQueryWithViewName(SOSViewManagerRef vmgr, CFStringRef name); +NSDictionary * +SecEMCSCreateNewiDMSKey(NSDictionary *options, + NSData *oldEMCSKey, + NSString *managedCredential, + NSData **emcsKey, + NSError **error); -__END_DECLS -#endif /* !_SEC_SOSVIEWMANAGER_H_ */ +#endif /* SecEMCS_h */ diff --git a/OSX/sec/Security/SecExports.exp-in b/OSX/sec/Security/SecExports.exp-in index 6d95a578..2a2fb56f 100644 --- a/OSX/sec/Security/SecExports.exp-in +++ b/OSX/sec/Security/SecExports.exp-in @@ -76,6 +76,8 @@ _kSecPolicyAppleATVAppSigning _kSecPolicyAppleTestATVAppSigning _kSecPolicyAppleATVVPNProfileSigning _kSecPolicyApplePayIssuerEncryption +_kSecPolicyAppleAST2DiagnosticsServerAuth +_kSecPolicyAppleAnchorAllowTestRootsOnProduction _kSecPolicyAppleAnchorIncludeTestRoots _kSecPolicyCheckAnchorSHA1 _kSecPolicyCheckAnchorApple @@ -98,6 +100,9 @@ _kSecPolicyCheckIdLinkage _kSecPolicyCheckIntermediateMarkerOid _kSecPolicyCheckIntermediateSPKISHA256 _kSecPolicyCheckIssuerCommonName +_kSecPolicyCheckWeakIntermediates +_kSecPolicyCheckWeakLeaf +_kSecPolicyCheckWeakRoot _kSecPolicyCheckKeyUsage _kSecPolicyCheckLeafMarkerOid _kSecPolicyCheckNoNetworkAccess @@ -143,6 +148,7 @@ _SecPolicyCreateApplePushService _SecPolicyCreateApplePushServiceLegacy _SecPolicyCreateAppleMMCSService _SecPolicyCreateApplePPQService +_SecPolicyCreateAppleAST2Service _SecPolicyCreateAppleSSLService _SecPolicyCreateApplePackageSigning _SecPolicyCreateAppleSWUpdateSigning @@ -329,6 +335,7 @@ _SecCertificateHasUnknownCriticalExtension _SecCertificateIsSelfSigned _SecCertificateIsSelfSignedCA _SecCertificateIsValid +_SecCertificateIsWeak _SecCertificateNotValidAfter _SecCertificateNotValidBefore _SecCertificateParseGeneralNameContentProperty @@ -557,6 +564,7 @@ _SecCmsSignerInfoAddMSSMIMEEncKeyPrefs _SecCmsSignerInfoAddSMIMECaps _SecCmsSignerInfoAddSMIMEEncKeyPrefs _SecCmsSignerInfoAddSigningTime +_SecCmsSignerInfoAddAppleCodesigningHashAgility _SecCmsSignerInfoCreate _SecCmsSignerInfoCreateWithSubjKeyID _SecCmsSignerInfoGetCertList @@ -566,6 +574,7 @@ _SecCmsSignerInfoGetSignerCommonName _SecCmsSignerInfoGetSignerEmailAddress _SecCmsSignerInfoGetSigningCertificate _SecCmsSignerInfoGetSigningTime +_SecCmsSignerInfoGetAppleCodesigningHashAgility _SecCmsSignerInfoGetVerificationStatus _SecCmsSignerInfoIncludeCerts _SecCmsSignerInfoSaveSMIMEProfile @@ -712,6 +721,8 @@ _kSecAttrKeyTypeEC _kSecAttrKeyTypeRSA _kSecAttrLabel _kSecAttrModificationDate +_kSecAttrMultiUser +_kSecAttrNoLegacy _kSecAttrPath _kSecAttrPort _kSecAttrProtocol @@ -793,6 +804,7 @@ _kSecImportItemLabel _kSecImportItemTrust _kSecUseItemList _kSecUseTombstones +_kSecUseSystemKeychain _kSecValueData _kSecValuePersistentRef _kSecValueRef @@ -826,6 +838,8 @@ __SecKeychainRestoreBackup __SecKeychainSyncUpdateMessage __SecKeychainBackupSyncable __SecKeychainRestoreSyncable +__SecKeychainRestoreBackupFromFileDescriptor +__SecKeychainWriteBackupToFileDescriptor _SecItemBackupWithRegisteredBackups _SecItemBackupSetConfirmedManifest _SecItemBackupRestore @@ -836,6 +850,10 @@ _SecAddSharedWebCredential _SecRequestSharedWebCredential _SecCreateSharedWebCredentialPassword _kSecSharedPassword +__SecSecuritydCopyWhoAmI +__SecSyncBubbleTransfer +__SecSystemKeychainTransfer +__SecSyncDeleteUserViews _kSecXPCKeyAttributesToUpdate _kSecXPCKeyBackup @@ -881,3 +899,10 @@ _CFPropertyListCreateWithDERData // DER // _DERDecodeItem + +// +// EMCS +// + +_SecEMCSCreateDerivedEMCSKey +_SecEMCSCreateNewiDMSKey diff --git a/OSX/sec/Security/SecFrameworkStrings.h b/OSX/sec/Security/SecFrameworkStrings.h index 38fd63d3..6635514a 100644 --- a/OSX/sec/Security/SecFrameworkStrings.h +++ b/OSX/sec/Security/SecFrameworkStrings.h @@ -189,6 +189,7 @@ __BEGIN_DECLS #define SEC_HOSTNAME_MISMATCH_KEY SecStringWithDefaultValue("Hostname mismatch.", "Certificate", 0, "Hostname mismatch.", "") #define SEC_POLICY__REQ_NOT_MET_KEY SecStringWithDefaultValue("Policy requirements not met.", "Certificate", 0, "Policy requirements not met.", "") #define SEC_CHAIN_VALIDITY_ERR_KEY SecStringWithDefaultValue("One or more certificates have expired or are not valid yet.", "Certificate", 0, "One or more certificates have expired or are not valid yet.", "") +#define SEC_WEAK_KEY_ERR_KEY SecStringWithDefaultValue("One or more certificates is using a weak key size.", "Certificate", 0, "One or more certificates is using a weak key size.", "") #define SEC_CK_PASSWORD_INCORRECT SecStringWithDefaultValue("Incorrect Password For “%@”", "CloudKeychain", 0, "Incorrect Password For “%@”", "Title for alert when password has been entered incorrectly") #define SEC_CK_TRY_AGAIN SecStringWithDefaultValue("Try Again", "CloudKeychain", 0, "Try Again", "Button for try again after incorrect password") @@ -214,7 +215,7 @@ __BEGIN_DECLS #define SEC_CK_APPROVAL_TITLE_OSX SecStringWithDefaultValue("Apple ID Sign In Alert", "CloudKeychain", 0, "Apple ID Sign In Alert", "Title for alert when approving another device") #define SEC_CK_APPROVAL_BODY_OSX SecStringWithDefaultValue("“%@” wants to use your iCloud account.", "CloudKeychain", 0, "“%@” wants to use your iCloud account.", "Body text when approving another device") -#define SEC_CK_APPROVAL_TITLE_IOS SecStringWithDefaultValue("Allow “%@” to Use iCloud?", "CloudKeychain", 0, "Allow “%@” to Use iCloud?", "Title for alert when approving another device") +#define SEC_CK_APPROVAL_TITLE_IOS SecStringWithDefaultValue("Allow “%@” to use iCloud?", "CloudKeychain", 0, "Allow “%@” to use iCloud?", "Title for alert when approving another device") #define SEC_CK_APPROVAL_BODY_IOS_IPAD SecStringWithDefaultValue("Enter the password for “%@” to allow this new iPad to use your iCloud account.", "CloudKeychain", 0, "Enter the password for “%@” to allow this new iPad to use your iCloud account.", "Body text when approving an iPad") #define SEC_CK_APPROVAL_BODY_IOS_IPHONE SecStringWithDefaultValue("Enter the password for “%@” to allow this new iPhone to use your iCloud account.", "CloudKeychain", 0, "Enter the password for “%@” to allow this new iPhone to use your iCloud account.", "Body text when approving an iPhone") #define SEC_CK_APPROVAL_BODY_IOS_IPOD SecStringWithDefaultValue("Enter the password for “%@” to allow this new iPod to use your iCloud account.", "CloudKeychain", 0, "Enter the password for “%@” to allow this new iPod to use your iCloud account.", "Body text when approving an iPod") diff --git a/OSX/sec/Security/SecItem.c b/OSX/sec/Security/SecItem.c index 112335be..1595e0bf 100644 --- a/OSX/sec/Security/SecItem.c +++ b/OSX/sec/Security/SecItem.c @@ -1161,7 +1161,7 @@ static CFArrayRef dict_to_array_error_request(enum SecXPCOperation op, CFDiction return result; } -bool cftype_ag_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeRef attributes, __unused CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) { +bool cftype_client_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeRef attributes, __unused SecurityClient *client, CFTypeRef *result, CFErrorRef *error) { return cftype_to_bool_cftype_error_request(op, attributes, result, error); } @@ -1172,7 +1172,7 @@ static bool dict_to_error_request(enum SecXPCOperation op, CFDictionaryRef query }, NULL); } -static bool dict_ag_to_error_request(enum SecXPCOperation op, CFDictionaryRef query, __unused CFArrayRef accessGroups, CFErrorRef *error) +static bool dict_client_to_error_request(enum SecXPCOperation op, CFDictionaryRef query, __unused SecurityClient *client, CFErrorRef *error) { return dict_to_error_request(op, query, error); } @@ -1269,8 +1269,8 @@ static bool SecTokenItemAdd(TKTokenRef token, CFDictionaryRef attributes, CFDict if (!CFEqualSafe(CFDictionaryGetValue(attrs, kSecAttrIsPermanent), kCFBooleanFalse)) { // IsPermanent is not present or is true, so add item to the db. - require_quiet(SECURITYD_XPC(sec_item_add, cftype_ag_to_bool_cftype_error_request, attrs, - SecAccessGroupsGetCurrent(), &db_result, error), out); + require_quiet(SECURITYD_XPC(sec_item_add, cftype_client_to_bool_cftype_error_request, attrs, + SecSecurityClientGet(), &db_result, error), out); } else { // Process directly result of token call. db_result = CFRetain(attrs); @@ -1309,7 +1309,7 @@ SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result) return SecItemAuthDoQuery(&attrs, NULL, SecItemAdd, error, ^bool(TKTokenRef token, CFDictionaryRef attributes, CFDictionaryRef unused, CFDictionaryRef auth_params, CFErrorRef *error) { if (token == NULL) { CFTypeRef raw_result = NULL; - if (!SECURITYD_XPC(sec_item_add, cftype_ag_to_bool_cftype_error_request, attributes, SecAccessGroupsGetCurrent(), &raw_result, error)) + if (!SECURITYD_XPC(sec_item_add, cftype_client_to_bool_cftype_error_request, attributes, SecSecurityClientGet(), &raw_result, error)) return false; bool ok = SecItemResultProcess(attributes, auth_params, token, raw_result, result, error); @@ -1360,7 +1360,7 @@ SecItemCopyMatching(CFDictionaryRef inQuery, CFTypeRef *result) status = SecOSStatusWith(^bool(CFErrorRef *error) { return SecItemAuthDoQuery(&query, NULL, SecItemCopyMatching, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { CFTypeRef raw_result = NULL; - if (!SECURITYD_XPC(sec_item_copy_matching, cftype_ag_to_bool_cftype_error_request, query, SecAccessGroupsGetCurrent(), &raw_result, error)) + if (!SECURITYD_XPC(sec_item_copy_matching, cftype_client_to_bool_cftype_error_request, query, SecSecurityClientGet(), &raw_result, error)) return false; // We intentionally pass NULL as token argument, because we want to be able to decide about token on which the item lives @@ -1399,8 +1399,8 @@ static bool SecTokenItemForEachMatching(CFDictionaryRef query, CFErrorRef *error } CFDictionarySetValue(list_query, kSecReturnData, kCFBooleanTrue); CFDictionarySetValue(list_query, kSecReturnPersistentRef, kCFBooleanTrue); - require_quiet(SECURITYD_XPC(sec_item_copy_matching, cftype_ag_to_bool_cftype_error_request, list_query, - SecAccessGroupsGetCurrent(), &items, error), out); + require_quiet(SECURITYD_XPC(sec_item_copy_matching, cftype_client_to_bool_cftype_error_request, list_query, + SecSecurityClientGet(), &items, error), out); if (CFGetTypeID(items) != CFArrayGetTypeID()) { // Wrap single returned item into the array. CFArrayRef item_array = CFArrayCreateForCFTypes(NULL, items, NULL); @@ -1439,7 +1439,7 @@ static bool SecItemRawUpdate(CFDictionaryRef query, CFDictionaryRef attributesTo // Ensure the dictionary passed to securityd has proper kCFTypeDictionaryKeyCallBacks. CFMutableDictionaryRef tmp = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); CFDictionaryForEach(attributesToUpdate, ^(const void *key, const void *value) { CFDictionaryAddValue(tmp, key, value); }); - ok = gSecurityd->sec_item_update(query, tmp, SecAccessGroupsGetCurrent(), error); + ok = gSecurityd->sec_item_update(query, tmp, SecSecurityClientGet(), error); CFRelease(tmp); } else { xpc_object_t message = securityd_create_message(sec_item_update_id, error); @@ -1555,7 +1555,7 @@ SecItemDelete(CFDictionaryRef inQuery) status = SecOSStatusWith(^bool(CFErrorRef *error) { return SecItemAuthDoQuery(&query, NULL, SecItemDelete, error, ^bool(TKTokenRef token, CFDictionaryRef query, CFDictionaryRef attributes, CFDictionaryRef auth_params, CFErrorRef *error) { if (token == NULL) { - return SECURITYD_XPC(sec_item_delete, dict_ag_to_error_request, query, SecAccessGroupsGetCurrent(), error); + return SECURITYD_XPC(sec_item_delete, dict_client_to_error_request, query, SecSecurityClientGet(), error); } else { return SecTokenItemForEachMatching(query, error, ^bool(CFDictionaryRef object_data, CFDictionaryRef item_query, CFErrorRef *error) { bool ok = false; @@ -1566,8 +1566,8 @@ SecItemDelete(CFDictionaryRef inQuery) SecTokenProcessError(kAKSKeyOpDelete, token, object_id, error)); // Delete the item from the keychain. - require_quiet(SECURITYD_XPC(sec_item_delete, dict_ag_to_error_request, item_query, - SecAccessGroupsGetCurrent(), error), out); + require_quiet(SECURITYD_XPC(sec_item_delete, dict_client_to_error_request, item_query, + SecSecurityClientGet(), error), out); ok = true; out: diff --git a/OSX/sec/Security/SecItemBackup.c b/OSX/sec/Security/SecItemBackup.c index e42c11d4..ff08afe6 100644 --- a/OSX/sec/Security/SecItemBackup.c +++ b/OSX/sec/Security/SecItemBackup.c @@ -47,7 +47,7 @@ #include #include -static CFDataRef data_data_to_data_error_request(enum SecXPCOperation op, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { +static CFDataRef client_data_data_to_data_error_request(enum SecXPCOperation op, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { __block CFDataRef result = NULL; securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { return SecXPCDictionarySetDataOptional(message, kSecXPCKeyKeybag, keybag, error) @@ -58,7 +58,7 @@ static CFDataRef data_data_to_data_error_request(enum SecXPCOperation op, CFData return result; } -static bool data_data_data_to_error_request(enum SecXPCOperation op, CFDataRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { +static bool data_client_data_data_to_error_request(enum SecXPCOperation op, CFDataRef backup, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { return securityd_send_sync_and_do(op, error, ^bool(xpc_object_t message, CFErrorRef *error) { return SecXPCDictionarySetData(message, kSecXPCKeyBackup, backup, error) && SecXPCDictionarySetData(message, kSecXPCKeyKeybag, keybag, error) @@ -145,7 +145,7 @@ static int SecItemBackupHandoffFD(CFStringRef backupName, CFErrorRef *error) { CFDataRef _SecKeychainCopyOTABackup(void) { __block CFDataRef result; os_activity_initiate("_SecKeychainCopyOTABackup", OS_ACTIVITY_FLAG_DEFAULT, ^{ - result = SECURITYD_XPC(sec_keychain_backup, data_data_to_data_error_request, NULL, NULL, NULL); + result = SECURITYD_XPC(sec_keychain_backup, client_data_data_to_data_error_request, SecSecurityClientGet(), NULL, NULL, NULL); }); return result; } @@ -153,22 +153,55 @@ CFDataRef _SecKeychainCopyOTABackup(void) { CFDataRef _SecKeychainCopyBackup(CFDataRef backupKeybag, CFDataRef password) { __block CFDataRef result; os_activity_initiate("_SecKeychainCopyBackup", OS_ACTIVITY_FLAG_DEFAULT, ^{ - result = SECURITYD_XPC(sec_keychain_backup, data_data_to_data_error_request, backupKeybag, password, NULL); + result = SECURITYD_XPC(sec_keychain_backup, client_data_data_to_data_error_request, SecSecurityClientGet(), backupKeybag, password, NULL); }); return result; } +bool _SecKeychainWriteBackupToFileDescriptor(CFDataRef backupKeybag, CFDataRef password, int fd, CFErrorRef *error) { + __block bool result = false; + os_activity_initiate("_SecKeychainWriteBackupToFile", OS_ACTIVITY_FLAG_DEFAULT, ^{ + + securityd_send_sync_and_do(sec_keychain_backup_id, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetDataOptional(message, kSecXPCKeyKeybag, backupKeybag, error) + && SecXPCDictionarySetDataOptional(message, kSecXPCKeyUserPassword, password, error) + && SecXPCDictionarySetFileDescriptor(message, kSecXPCKeyFileDescriptor, fd, error); + }, ^bool(xpc_object_t response, CFErrorRef *error) { + return (result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, error)); + }); + }); + return result; +} + +bool +_SecKeychainRestoreBackupFromFileDescriptor(int fd, CFDataRef backupKeybag, CFDataRef password, CFErrorRef *error) +{ + __block bool result; + os_activity_initiate("_SecKeychainRestoreBackup", OS_ACTIVITY_FLAG_DEFAULT, ^{ + securityd_send_sync_and_do(sec_keychain_restore_id, error, ^bool(xpc_object_t message, CFErrorRef *error) { + return SecXPCDictionarySetFileDescriptor(message, kSecXPCKeyFileDescriptor, fd, error) + && SecXPCDictionarySetData(message, kSecXPCKeyKeybag, backupKeybag, error) + && SecXPCDictionarySetDataOptional(message, kSecXPCKeyUserPassword, password, error); + }, ^bool(xpc_object_t response, CFErrorRef *error) { + return (result = SecXPCDictionaryGetBool(response, kSecXPCKeyResult, error)); + }); + }); + return result; +} + + OSStatus _SecKeychainRestoreBackup(CFDataRef backup, CFDataRef backupKeybag, CFDataRef password) { __block OSStatus result; os_activity_initiate("_SecKeychainRestoreBackup", OS_ACTIVITY_FLAG_DEFAULT, ^{ result = SecOSStatusWith(^bool (CFErrorRef *error) { - return SECURITYD_XPC(sec_keychain_restore, data_data_data_to_error_request, backup, backupKeybag, password, error); + return SECURITYD_XPC(sec_keychain_restore, data_client_data_data_to_error_request, backup, SecSecurityClientGet(), backupKeybag, password, error); }); }); return result; } + static int compareDigests(const void *l, const void *r) { return memcmp(l, r, CCSHA1_OUTPUT_SIZE); } @@ -197,78 +230,6 @@ CFDataRef SecItemBackupCreateManifest(CFDictionaryRef backup, CFErrorRef *error) return manifest; } -/* - client code in CloudServices calls SecItemBackupWithChanges in the loop of SecItemBackupWithRegisteredBackups - */ -__unused static CFDictionaryRef SecItemBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFErrorRef *error) -{ - const CFStringRef backupName = kSOSViewKeychainV0_tomb; - __block bool complete = false; - __block CFMutableDictionaryRef backup = backup_in ? CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, backup_in) : CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDataRef keybagDigest = CFDataCopySHA1Digest(keybag, NULL); // Used to confirm we are in sync keybag wise. - do { - CFErrorRef localError = NULL; - if (!SecItemBackupWithChanges(backupName, &localError, ^(SecBackupEventType et, CFTypeRef key, CFTypeRef item) { - CFStringRef hexDigest = key ? CFDataCopyHexString(key) : NULL; - complete = false; - switch(et) { - case kSecBackupEventReset: - CFDictionaryRemoveAllValues(backup); - break; - case kSecBackupEventAdd: - CFDictionarySetValue(backup, hexDigest, item); - break; - case kSecBackupEventRemove: - CFDictionaryRemoveValue(backup, hexDigest); - break; - case kSecBackupEventComplete: - complete = true; - break; - } - CFReleaseSafe(hexDigest); - - })) { - if (localError && CFEqual(CFErrorGetDomain(localError), kSecErrnoDomain) && CFErrorGetCode(localError) == ENOENT) { - // No journal file returned by securityd, nothing left to do, ignore error and exit. - CFReleaseNull(localError); - } else { - CFErrorPropagate(localError, error); - CFReleaseNull(backup); - } - break; - } - - CFDataRef mconfirmed = SecItemBackupCreateManifest(backup, error); - if (!mconfirmed) { - CFReleaseNull(backup); - break; - } - bool ok = SecItemBackupSetConfirmedManifest(backupName, keybagDigest, mconfirmed, error); - CFReleaseSafe(mconfirmed); - if (!ok) { - CFReleaseNull(backup); - break; - } - } while (!complete); - CFReleaseSafe(keybagDigest); - - return backup; -} - -#if 0 // interim code to call SecItemBackupSyncable -OSStatus _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out) -{ - __block OSStatus result; - os_activity_initiate("_SecKeychainBackupSyncable", OS_ACTIVITY_FLAG_DEFAULT, ^{ - result = SecOSStatusWith(^bool (CFErrorRef *error) { - *backup_out = SecItemBackupSyncable(keybag, password, backup_in, error); - return *backup_out != NULL; - }); - }); - return result; -} -#endif - OSStatus _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out) { return SecOSStatusWith(^bool (CFErrorRef *error) { @@ -296,6 +257,10 @@ static bool SecKeychainWithBackupFile(CFStringRef backupName, CFErrorRef *error, secdebug("backup", "SecItemBackupHandoffFD returned %d", fd); return false; } + + // Rewind file to start + lseek(fd, 0, SEEK_SET); + FILE *backup = fdopen(fd, "r"); if (!backup) { close(fd); @@ -305,8 +270,6 @@ static bool SecKeychainWithBackupFile(CFStringRef backupName, CFErrorRef *error, secdebug("backup", "Receiving file for %@ with fd %d of size %llu", backupName, fd, lseek(fd, 0, SEEK_END)); } - // Rewind file to start - lseek(fd, 0, SEEK_SET); with(backup); fclose(backup); return true; diff --git a/OSX/sec/Security/SecItemBackup.h b/OSX/sec/Security/SecItemBackup.h index 3dbaa10c..18dea32f 100644 --- a/OSX/sec/Security/SecItemBackup.h +++ b/OSX/sec/Security/SecItemBackup.h @@ -54,7 +54,7 @@ typedef enum SecBackupEventType { bool SecItemBackupWithRegisteredBackups(CFErrorRef *error, void(^backup)(CFStringRef backupName)); /*! - @function SecBackupWithChanges + @function SecItemBackupWithChanges @abstract Tell securityd which keybag (via a persistent ref) to use to backup items for each of the built in dataSources to. @param backupName Name of this backup set. diff --git a/OSX/sec/Security/SecItemConstants.c b/OSX/sec/Security/SecItemConstants.c index c98df7bf..d09ce9d4 100644 --- a/OSX/sec/Security/SecItemConstants.c +++ b/OSX/sec/Security/SecItemConstants.c @@ -106,6 +106,8 @@ SEC_CONST_DECL (kSecAttrCRLType, "crlt"); SEC_CONST_DECL (kSecAttrCRLEncoding, "crle"); SEC_CONST_DECL (kSecAttrSynchronizable, "sync"); SEC_CONST_DECL (kSecAttrTombstone, "tomb"); +SEC_CONST_DECL (kSecAttrMultiUser, "musr"); +SEC_CONST_DECL (kSecAttrNoLegacy, "nleg"); /* Search Constants */ SEC_CONST_DECL (kSecMatchPolicy, "m_Policy"); @@ -133,18 +135,15 @@ SEC_CONST_DECL (kSecValueData, "v_Data"); SEC_CONST_DECL (kSecValueRef, "v_Ref"); SEC_CONST_DECL (kSecValuePersistentRef, "v_PersistentRef"); -/* Other Constants */ +/* kSecUse Constants */ SEC_CONST_DECL (kSecUseItemList, "u_ItemList"); SEC_CONST_DECL (kSecUseTombstones, "u_Tomb"); SEC_CONST_DECL (kSecUseCredentialReference, "u_CredRef"); SEC_CONST_DECL (kSecUseOperationPrompt, "u_OpPrompt"); SEC_CONST_DECL (kSecUseNoAuthenticationUI, "u_NoAuthUI"); SEC_CONST_DECL (kSecUseAuthenticationUI, "u_AuthUI"); -#if defined(MULTIPLE_KEYCHAINS) -/* Other Constants (Private) */ -SEC_CONST_DECL (kSecUseKeychain, "u_Keychain"); -SEC_CONST_DECL (kSecUseKeychainList, "u_KeychainList"); -#endif /* !defined(MULTIPLE_KEYCHAINS) */ +SEC_CONST_DECL (kSecUseSystemKeychain, "u_SystemKeychain"); +SEC_CONST_DECL (kSecUseSyncBubbleKeychain, "u_SyncBubbleKeychain"); /* kSecAttrAccessible Value Constants. */ SEC_CONST_DECL (kSecAttrAccessibleWhenUnlocked, "ak"); diff --git a/OSX/sec/Security/SecItemInternal.h b/OSX/sec/Security/SecItemInternal.h index b2070c44..71bdb50c 100644 --- a/OSX/sec/Security/SecItemInternal.h +++ b/OSX/sec/Security/SecItemInternal.h @@ -47,7 +47,7 @@ OSStatus _SecRestoreKeychain(const char *path); OSStatus SecOSStatusWith(bool (^perform)(CFErrorRef *error)); -bool cftype_ag_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeRef attributes, __unused CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); +bool cftype_client_to_bool_cftype_error_request(enum SecXPCOperation op, CFTypeRef attributes, __unused SecurityClient *client, CFTypeRef *result, CFErrorRef *error); /* Structure representing copy-on-write dictionary. Typical use is: int bar(CFDictionaryRef input); diff --git a/OSX/sec/Security/SecItemPriv.h b/OSX/sec/Security/SecItemPriv.h index e477ed06..e8fab148 100644 --- a/OSX/sec/Security/SecItemPriv.h +++ b/OSX/sec/Security/SecItemPriv.h @@ -277,12 +277,15 @@ extern const CFStringRef kSecAttrCanSignRecover; extern const CFStringRef kSecAttrCanVerifyRecover; extern const CFStringRef kSecAttrTombstone; extern const CFStringRef kSecAttrNoLegacy - __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_NA); + __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); + /* View Hint Constants */ extern const CFStringRef kSecAttrViewHintPCSMasterKey; @@ -301,6 +304,23 @@ extern const CFStringRef kSecAttrViewHintAppleTV; extern const CFStringRef kSecAttrViewHintHomeKit; extern const CFStringRef kSecAttrViewHintThumper; +/* + * + */ + +extern const CFStringRef kSecUseSystemKeychain + __TVOS_AVAILABLE(9.2) + __WATCHOS_AVAILABLE(3.0) + __OSX_AVAILABLE(10.11.4) + __IOS_AVAILABLE(9.3); + +extern const CFStringRef kSecUseSyncBubbleKeychain + __TVOS_AVAILABLE(9.2) + __WATCHOS_AVAILABLE(3.0) + __OSX_AVAILABLE(10.11.4) + __IOS_AVAILABLE(9.3); + + /*! @enum Other Constants (Private) @discussion Predefined constants used to set values in a dictionary. @@ -330,10 +350,6 @@ extern const CFStringRef kSecUseTombstones __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0); extern const CFStringRef kSecUseCredentialReference __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); -#if defined(MULTIPLE_KEYCHAINS) -extern const CFStringRef kSecUseKeychain; -extern const CFStringRef kSecUseKeychainList; -#endif /* !defined(MULTIPLE_KEYCHAINS) */ /*! @@ -374,6 +390,15 @@ CFDataRef _SecKeychainCopyOTABackup(void); OSStatus _SecKeychainRestoreBackup(CFDataRef backup, CFDataRef backupKeybag, CFDataRef password); + +bool +_SecKeychainWriteBackupToFileDescriptor(CFDataRef backupKeybag, CFDataRef password, int fd, CFErrorRef *error); + +bool +_SecKeychainRestoreBackupFromFileDescriptor(int fd, CFDataRef backupKeybag, CFDataRef password, CFErrorRef *error); + + + OSStatus _SecKeychainBackupSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in, CFDictionaryRef *backup_out); OSStatus _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDictionaryRef backup_in); @@ -381,16 +406,21 @@ OSStatus _SecKeychainRestoreSyncable(CFDataRef keybag, CFDataRef password, CFDic Requires caller to have the kSecEntitlementKeychainSyncUpdates entitlement. */ CFArrayRef _SecKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#if !TARGET_OS_IPHONE CFDataRef _SecItemGetPersistentReference(CFTypeRef raw_item); #endif -/* 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). */ +/* 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); bool _SecKeychainRollKeys(bool force, CFErrorRef *error); +CFDictionaryRef _SecSecuritydCopyWhoAmI(CFErrorRef *error); +bool _SecSyncBubbleTransfer(CFArrayRef services, uid_t uid, CFErrorRef *error); +bool _SecSystemKeychainTransfer(CFErrorRef *error); +bool _SecSyncDeleteUserViews(uid_t uid, CFErrorRef *error); + __END_DECLS #endif /* !_SECURITY_SECITEMPRIV_H_ */ diff --git a/OSX/sec/Security/SecOTRPacketData.h b/OSX/sec/Security/SecOTRPacketData.h index 4fb761e1..81dc4409 100644 --- a/OSX/sec/Security/SecOTRPacketData.h +++ b/OSX/sec/Security/SecOTRPacketData.h @@ -349,8 +349,8 @@ static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef all CFDataAppendBytes(result, *bytesPtr, (CFIndex)sizeInStream); *bytesPtr += sizeInStream; - *sizePtr += sizeInStream; - + *sizePtr -= sizeInStream; + exit: return result; } diff --git a/OSX/sec/Security/SecPasswordGenerate.c b/OSX/sec/Security/SecPasswordGenerate.c index 2d9afcea..e3e01d06 100644 --- a/OSX/sec/Security/SecPasswordGenerate.c +++ b/OSX/sec/Security/SecPasswordGenerate.c @@ -382,6 +382,25 @@ static bool SecPasswordIsPasscodeIncrementingOrDecrementingDigits(CFStringRef pa return false; } +static bool SecPasswordIsPasswordRepeatingTwoNumbers(CFStringRef passcode){ + char* pin = CFStringToCString(passcode); + + for(int i = 0; i < CFStringGetLength(passcode); i++) + { + if(i+2 == CFStringGetLength(passcode)-1){ + free(pin); + return true; + } + else if(pin[i] == pin[i+2]) + continue; + else + break; + } + + free(pin); + return false; +} + bool SecPasswordIsPasswordWeak2(bool isSimple, CFStringRef passcode) { uppercaseLetterCharacterSet = CFCharacterSetGetPredefined(kCFCharacterSetUppercaseLetter); @@ -465,6 +484,11 @@ bool SecPasswordIsPasswordWeak2(bool isSimple, CFStringRef passcode) free(pin); return true; } + //passcode does not consist of 2 repeating digits + if(SecPasswordIsPasswordRepeatingTwoNumbers(passcode)){ + free(pin); + return true; + } } else//should be a 4 or 6digit number return false; @@ -486,6 +510,11 @@ bool SecPasswordIsPasswordWeak2(bool isSimple, CFStringRef passcode) free(pin); return true; } + if(SecPasswordIsPasswordRepeatingTwoNumbers(passcode)){ + free(pin); + return true; + } + } else{ // password is complex, evaluate entropy int u = 0; diff --git a/OSX/sec/Security/SecPolicy.c b/OSX/sec/Security/SecPolicy.c index 94053fd1..72d35c51 100644 --- a/OSX/sec/Security/SecPolicy.c +++ b/OSX/sec/Security/SecPolicy.c @@ -124,6 +124,7 @@ SEC_CONST_DECL (kSecPolicyCheckAnchorApple, "AnchorApple"); /* options for kSecPolicyCheckAnchorApple */ SEC_CONST_DECL (kSecPolicyAppleAnchorIncludeTestRoots, "AnchorAppleTestRoots"); +SEC_CONST_DECL (kSecPolicyAppleAnchorAllowTestRootsOnProduction, "AnchorAppleTestRootsOnProduction"); /******************************************************** *********** Unverified Certificate Checks ************** @@ -138,6 +139,9 @@ SEC_CONST_DECL (kSecPolicyCheckValidityExpired, "ValidExpired"); SEC_CONST_DECL (kSecPolicyCheckValidIntermediates, "ValidIntermediates"); SEC_CONST_DECL (kSecPolicyCheckValidLeaf, "ValidLeaf"); SEC_CONST_DECL (kSecPolicyCheckValidRoot, "ValidRoot"); +SEC_CONST_DECL (kSecPolicyCheckWeakIntermediates, "WeakIntermediates"); +SEC_CONST_DECL (kSecPolicyCheckWeakLeaf, "WeakLeaf"); +SEC_CONST_DECL (kSecPolicyCheckWeakRoot, "WeakRoot"); #endif @@ -217,7 +221,7 @@ 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 (kSecPolicyAppleATVVPNProfileSigning, "1.2.840.113625.100.1.41"); -// TODO need confirmation that OID for kSecPolicyAppleATVVPNProfileSigning is reserved +SEC_CONST_DECL (kSecPolicyAppleAST2DiagnosticsServerAuth, "1.2.840.113625.100.1.42"); SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); @@ -271,11 +275,14 @@ static CFStringRef kSecPolicyOIDAppleQAProfileSigner = CFSTR("AppleQAProfileSign static CFStringRef kSecPolicyOIDAppleOTAPKIAssetSigner = CFSTR("AppleOTAPKIAssetSigner"); static CFStringRef kSecPolicyOIDAppleTestOTAPKIAssetSigner = CFSTR("AppleTestOTAPKIAssetSigner"); static CFStringRef kSecPolicyOIDAppleIDValidationRecordSigningPolicy = CFSTR("AppleIDValidationRecordSigningPolicy"); +#if TARGET_OS_EMBEDDED static CFStringRef kSecPolicyOIDAppleATVAppSigning = CFSTR("AppleATVAppSigning"); static CFStringRef kSecPolicyOIDAppleTestATVAppSigning = CFSTR("AppleTestATVAppSigning"); +#endif static CFStringRef kSecPolicyOIDApplePayIssuerEncryption = CFSTR("ApplePayIssuerEncryption"); static CFStringRef kSecPolicyOIDAppleOSXProvisioningProfileSigning = CFSTR("AppleOSXProvisioningProfileSigning"); static CFStringRef kSecPolicyOIDAppleATVVPNProfileSigning = CFSTR("AppleATVVPNProfileSigning"); +static CFStringRef kSecPolicyOIDAppleAST2Service = CFSTR("AST2Service"); /* Policies will now change to multiple categories of checks. @@ -643,6 +650,9 @@ SecPolicyRef SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, } else if (CFEqual(policyIdentifier, kSecPolicyAppleATVVPNProfileSigning)) { policy = SecPolicyCreateAppleATVVPNProfileSigning(); + } + else if (CFEqual(policyIdentifier, kSecPolicyAppleAST2DiagnosticsServerAuth)) { + policy = SecPolicyCreateAppleAST2Service(name, NULL); } else { secerror("ERROR: policy \"%@\" is unsupported", policyIdentifier); @@ -724,7 +734,7 @@ CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) { else if (CFEqual(oid, kSecPolicyOIDAppleQAProfileSigner)) { outOid = kSecPolicyAppleQAProfileSigner; } -#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR +#if TARGET_OS_EMBEDDED else if (CFEqual(oid, kSecPolicyOIDAppleOTAPKIAssetSigner)) { outOid = kSecPolicyAppleOTAPKISigner; } @@ -750,6 +760,9 @@ CFDictionaryRef SecPolicyCopyProperties(SecPolicyRef policyRef) { else if (CFEqual(oid, kSecPolicyOIDAppleATVVPNProfileSigning)) { outOid = kSecPolicyAppleATVVPNProfileSigning; } + else if (CFEqual(oid, kSecPolicyOIDAppleAST2Service)) { + outOid = kSecPolicyAppleAST2DiagnosticsServerAuth; + } // Set kSecPolicyOid CFDictionarySetValue(properties, (const void *)kSecPolicyOid, @@ -1149,6 +1162,9 @@ static void SecPolicyAddBasicCertOptions(CFMutableDictionaryRef options) CFDictionaryAddValue(options, kSecPolicyCheckBasicContraints, kCFBooleanTrue); CFDictionaryAddValue(options, kSecPolicyCheckNonEmptySubject, kCFBooleanTrue); CFDictionaryAddValue(options, kSecPolicyCheckQualifiedCertStatements, kCFBooleanTrue); + CFDictionaryAddValue(options, kSecPolicyCheckWeakIntermediates, kCFBooleanTrue); + CFDictionaryAddValue(options, kSecPolicyCheckWeakLeaf, kCFBooleanTrue); + CFDictionaryAddValue(options, kSecPolicyCheckWeakRoot, kCFBooleanTrue); } static void SecPolicyAddBasicX509Options(CFMutableDictionaryRef options) @@ -2434,10 +2450,10 @@ errOut: } static bool -allowUATRoot(CFStringRef service, CFDictionaryRef context) +allowUATRoot(bool allowNonProd, CFStringRef service, CFDictionaryRef context) { bool UATAllowed = false; - if (SecIsInternalRelease()) { + if (SecIsInternalRelease() || allowNonProd) { CFStringRef setting = CFStringCreateWithFormat(NULL, NULL, CFSTR("AppleServerAuthenticationAllowUAT%@"), service); CFTypeRef value = NULL; require(setting, fail); @@ -2460,11 +2476,11 @@ fail: } static bool -requirePinning(CFStringRef service) +requirePinning(bool allowNonProd, CFStringRef service) { bool pinningRequired = true; - if (SecIsInternalRelease()) { + if (SecIsInternalRelease() || allowNonProd) { CFStringRef setting = CFStringCreateWithFormat(NULL, NULL, CFSTR("AppleServerAuthenticationNoPinning%@"), service); require(setting, fail); if (CFPreferencesGetAppBooleanValue(setting, CFSTR("com.apple.Security"), NULL)) @@ -2492,7 +2508,7 @@ fail: static SecPolicyRef SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, CFDictionaryRef __unused context, - CFStringRef service, + CFStringRef service, bool allowNonProd, const DERItem *leafMarkerOID, const DERItem *UATLeafMarkerOID) { @@ -2513,8 +2529,8 @@ SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, add_eku(options, &oidExtendedKeyUsageServerAuth); - if (requirePinning(service)) { - bool allowUAT = allowUATRoot(service, context); + if (requirePinning(allowNonProd, service)) { + bool allowUAT = allowUATRoot(allowNonProd, service, context); /* * Require pinning to the Apple CA's (and if UAT environment, @@ -2527,6 +2543,10 @@ SecPolicyCreateAppleServerAuthCommon(CFStringRef hostname, if (allowUAT) { CFDictionarySetValue(appleAnchorOptions, kSecPolicyAppleAnchorIncludeTestRoots, kCFBooleanTrue); + if (allowNonProd) { + CFDictionarySetValue(appleAnchorOptions, + kSecPolicyAppleAnchorAllowTestRootsOnProduction, kCFBooleanTrue); + } } add_element(options, kSecPolicyCheckAnchorApple, appleAnchorOptions); @@ -2581,7 +2601,7 @@ SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) #if 1 return SecPolicyCreateSSL(true, hostname); #else - return SecPolicyCreateAppleServerAuthCommon(hostname, NULL, CFSTR("IDS"), + return SecPolicyCreateAppleServerAuthCommon(hostname, NULL, CFSTR("IDS"), false, &oidAppleCertExtAppleServerAuthenticationIDSProd, &oidAppleCertExtAppleServerAuthenticationIDSTest); #endif @@ -2593,7 +2613,7 @@ SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) */ SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDictionaryRef context) { - return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("IDS"), + return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("IDS"), false, &oidAppleCertExtAppleServerAuthenticationIDSProd, &oidAppleCertExtAppleServerAuthenticationIDSTest); } @@ -2604,7 +2624,7 @@ SecPolicyRef SecPolicyCreateAppleIDSServiceContext(CFStringRef hostname, CFDicti */ SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef context) { - return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("GS"), + return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("GS"), false, &oidAppleCertExtAppleServerAuthenticationGS, NULL); } @@ -2615,7 +2635,7 @@ SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef */ SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryRef context) { - return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("APN"), + return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("APN"), false, &oidAppleCertExtAppleServerAuthenticationAPNProd, &oidAppleCertExtAppleServerAuthenticationAPNTest); } @@ -2626,11 +2646,22 @@ SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname, CFDictionaryR */ SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef context) { - return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("PPQ"), + return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("PPQ"), false, &oidAppleCertExtAppleServerAuthenticationPPQProd , &oidAppleCertExtAppleServerAuthenticationPPQTest); } +/*! + @function SecPolicyCreateAppleAST2Service + @abstract Ensure we're appropriately pinned to the AST2 Diagnostic service (SSL + Apple restrictions) + */ +SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef context) +{ + return SecPolicyCreateAppleServerAuthCommon(hostname, context, CFSTR("AST2"), true, + &oidAppleCertExtAST2DiagnosticsServerAuthProd, + &oidAppleCertExtAST2DiagnosticsServerAuthTest); +} + /* should use verbatim copy, but since this is the deprecated way, don't care right now */ static const UInt8 entrustSPKIL1C[kSecPolicySHA256Size] = { 0x54, 0x5b, 0xf9, 0x35, 0xe9, 0xad, 0xa1, 0xda, diff --git a/OSX/sec/Security/SecPolicyInternal.h b/OSX/sec/Security/SecPolicyInternal.h index 03d96ca3..b1884743 100644 --- a/OSX/sec/Security/SecPolicyInternal.h +++ b/OSX/sec/Security/SecPolicyInternal.h @@ -58,6 +58,9 @@ struct __SecPolicy { @constant kSecPolicyCheckExtendedKeyUsage @@@ @constant kSecPolicyCheckIdLinkage Fails if the AuthorityKeyID -> SubjectKeyID chaining isn't right. @constant kSecPolicyCheckKeyUsage @@@ + @constant kSecPolicyCheckWeakIntermediates Fails if any certificates in the chain (other than the leaf and root) have a too small key size. + @constant kSecPolicyCheckWeakLeaf Fails if the leaf has a too small key size. + @constant kSecPolicyCheckWeakRoot Fails fi the root has a too small key size. @constant kSecPolicyCheckNonEmptySubject Perform the following check: RFC 3280, 4.1.2.6, says that an empty subject name can only appear in a leaf cert, and only if subjectAltName is present and marked critical. @constant kSecPolicyCheckQualifiedCertStatements Perform the following check: RFC 3739: if this cert has a Qualified Cert Statements extension, and it's Critical, make sure we understand all of the extension's statementIds. @constant kSecPolicyCheckValidIntermediates Fails if any certificates in the chain are not valid at the verify time other than the leaf and the root. @@ -83,6 +86,9 @@ extern const CFStringRef kSecPolicyCheckBasicContraints; extern const CFStringRef kSecPolicyCheckCriticalExtensions; extern const CFStringRef kSecPolicyCheckExtendedKeyUsage; extern const CFStringRef kSecPolicyCheckIdLinkage; +extern const CFStringRef kSecPolicyCheckWeakIntermediates; +extern const CFStringRef kSecPolicyCheckWeakLeaf; +extern const CFStringRef kSecPolicyCheckWeakRoot; extern const CFStringRef kSecPolicyCheckKeyUsage; extern const CFStringRef kSecPolicyCheckNonEmptySubject; extern const CFStringRef kSecPolicyCheckQualifiedCertStatements; @@ -92,7 +98,6 @@ extern const CFStringRef kSecPolicyCheckValidRoot; extern const CFStringRef kSecPolicyCheckAnchorTrusted; extern const CFStringRef kSecPolicyCheckAnchorSHA1; extern const CFStringRef kSecPolicyCheckAnchorApple; -extern const CFStringRef kSecPolicyAppleAnchorIncludeTestRoots; extern const CFStringRef kSecPolicyCheckSSLHostname; extern const CFStringRef kSecPolicyCheckEmail; extern const CFStringRef kSecPolicyCheckIssuerCommonName; @@ -119,6 +124,10 @@ extern const CFStringRef kSecPolicyCheckIntermediateSPKISHA256; extern const CFStringRef kSecPolicyCheckGrayListedKey; extern const CFStringRef kSecPolicyCheckCertificateTransparency; +/* Special options for checking Apple Anchors */ +extern const CFStringRef kSecPolicyAppleAnchorIncludeTestRoots; +extern const CFStringRef kSecPolicyAppleAnchorAllowTestRootsOnProduction; + SecPolicyRef SecPolicyCreate(CFStringRef oid, CFDictionaryRef options); CFStringRef SecPolicyGetOidString(SecPolicyRef policy); diff --git a/OSX/sec/Security/SecPolicyPriv.h b/OSX/sec/Security/SecPolicyPriv.h index d0debccc..5bfd8f32 100644 --- a/OSX/sec/Security/SecPolicyPriv.h +++ b/OSX/sec/Security/SecPolicyPriv.h @@ -98,6 +98,8 @@ extern const CFStringRef kSecPolicyAppleTestATVAppSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); extern const CFStringRef kSecPolicyAppleOSXProvisioningProfileSigning __OSX_AVAILABLE_STARTING(__MAC_10_11, __IPHONE_9_0); +extern const CFStringRef kSecPolicyAppleAST2DiagnosticsServerAuth + __OSX_AVAILABLE_STARTING(__MAC_10_11_4, __IPHONE_9_3); /*! @@ -519,6 +521,13 @@ SecPolicyRef SecPolicyCreateAppleGSService(CFStringRef hostname, CFDictionaryRef SecPolicyRef SecPolicyCreateApplePPQService(CFStringRef hostname, CFDictionaryRef 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) + */ +SecPolicyRef SecPolicyCreateAppleAST2Service(CFStringRef hostname, CFDictionaryRef 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) diff --git a/OSX/sec/Security/SecSharedCredential.c b/OSX/sec/Security/SecSharedCredential.c index 43d77a13..a1f6963f 100644 --- a/OSX/sec/Security/SecSharedCredential.c +++ b/OSX/sec/Security/SecSharedCredential.c @@ -67,7 +67,7 @@ OSStatus SecAddSharedWebCredentialSync(CFStringRef fqdn, if(internal_spi && gSecurityd && gSecurityd->sec_add_shared_web_credential) { xpc_result = gSecurityd->sec_add_shared_web_credential(args, NULL, NULL, SecAccessGroupsGetCurrent(), &raw_result, error); } else { - xpc_result = cftype_ag_to_bool_cftype_error_request(sec_add_shared_web_credential_id, args, SecAccessGroupsGetCurrent(), &raw_result, error); + xpc_result = cftype_client_to_bool_cftype_error_request(sec_add_shared_web_credential_id, args, SecSecurityClientGet(), &raw_result, error); } CFReleaseSafe(args); if (!xpc_result) { @@ -164,7 +164,7 @@ OSStatus SecCopySharedWebCredentialSync(CFStringRef fqdn, if(internal_spi && gSecurityd && gSecurityd->sec_copy_shared_web_credential) { xpc_result = gSecurityd->sec_copy_shared_web_credential(args, NULL, NULL, SecAccessGroupsGetCurrent(), &raw_result, error); } else { - xpc_result = cftype_ag_to_bool_cftype_error_request(sec_copy_shared_web_credential_id, args, SecAccessGroupsGetCurrent(), &raw_result, error); + xpc_result = cftype_client_to_bool_cftype_error_request(sec_copy_shared_web_credential_id, args, SecSecurityClientGet(), &raw_result, error); } CFReleaseSafe(args); if (!xpc_result) { diff --git a/OSX/sec/Security/SecTrust.c b/OSX/sec/Security/SecTrust.c index a7e7158d..806f8b76 100644 --- a/OSX/sec/Security/SecTrust.c +++ b/OSX/sec/Security/SecTrust.c @@ -1218,6 +1218,7 @@ CFStringRef kSecPolicyCheckAnchorSHA1 = CFSTR("AnchorSHA1"); CFStringRef kSecPolicyCheckAnchorApple = CFSTR("AnchorApple"); CFStringRef kSecPolicyAppleAnchorIncludeTestRoots = CFSTR("AnchorAppleTestRoots"); +CFStringRef kSecPolicyAppleAnchorAllowTestRootsOnProduction = CFSTR("AnchorAppleTestRootsOnProduction"); /* Binding. Only applies to leaf @@ -1279,6 +1280,7 @@ struct TrustFailures { bool hostnameMismatch; bool policyFail; bool invalidCert; + bool weakKey; }; static void applyDetailProperty(const void *_key, const void *_value, @@ -1313,6 +1315,10 @@ static void applyDetailProperty(const void *_key, const void *_value, || CFEqual(key, kSecPolicyCheckValidLeaf) || CFEqual(key, kSecPolicyCheckValidRoot)) { tf->invalidCert = true; + } else if (CFEqual(key, kSecPolicyCheckWeakIntermediates) + || CFEqual(key, kSecPolicyCheckWeakLeaf) + || CFEqual(key, kSecPolicyCheckWeakRoot)) { + tf->weakKey = true; } else /* Anything else is a policy failure. */ #if 0 @@ -1380,6 +1386,9 @@ CFArrayRef SecTrustCopyProperties(SecTrustRef trust) { if (tf.invalidCert) { appendError(properties, CFSTR("One or more certificates have expired or are not valid yet.")); } + if (tf.weakKey) { + appendError(properties, CFSTR("One or more certificates is using a weak key size.")); + } } if (CFArrayGetCount(properties) == 0) { diff --git a/OSX/sec/Security/SecuritydXPC.c b/OSX/sec/Security/SecuritydXPC.c index 01a29884..03e76616 100644 --- a/OSX/sec/Security/SecuritydXPC.c +++ b/OSX/sec/Security/SecuritydXPC.c @@ -67,6 +67,7 @@ const char *kSecXPCKeyDisabledViewsKey = "disabledViews"; const char *kSecXPCKeyEscrowLabel = "escrow"; const char *kSecXPCKeyTriesLabel = "tries"; const char *kSecXPCKeyAvailability = "availability"; +const char *kSecXPCKeyFileDescriptor = "fileDescriptor"; // @@ -241,6 +242,20 @@ CFStringRef SOSCCGetOperationDescription(enum SecXPCOperation op) return CFSTR("SetEscrowRecord"); case kSecXPCOpGetEscrowRecord: return CFSTR("GetEscrowRecord"); + case kSecXPCOpWhoAmI: + return CFSTR("WhoAmI"); + case kSecXPCOpTransmogrifyToSyncBubble: + return CFSTR("TransmogrifyToSyncBubble"); + case kSecXPCOpWrapToBackupSliceKeyBagForView: + return CFSTR("WrapToBackupSliceKeyBagForView"); + case kSecXPCOpCopyAccountData: + return CFSTR("CopyAccountDataFromKeychain"); + case kSecXPCOpDeleteAccountData: + return CFSTR("DeleteAccountDataFromKeychain"); + case kSecXPCOpCopyEngineData: + return CFSTR("CopyEngineDataFromKeychain"); + case kSecXPCOpDeleteEngineData: + return CFSTR("DeleteEngineDataFromKeychain"); default: return CFSTR("Unknown xpc operation"); } @@ -281,6 +296,12 @@ bool SecXPCDictionarySetData(xpc_object_t message, const char *key, CFDataRef da return true; } +bool SecXPCDictionarySetBool(xpc_object_t message, const char *key, bool value, CFErrorRef *error) +{ + xpc_dictionary_set_bool(message, key, value); + return true; +} + bool SecXPCDictionarySetString(xpc_object_t message, const char *key, CFStringRef string, CFErrorRef *error) { if (!string) @@ -361,6 +382,10 @@ CFDataRef SecXPCDictionaryCopyData(xpc_object_t message, const char *key, CFErro return data; } +bool SecXPCDictionaryGetBool(xpc_object_t message, const char *key, CFErrorRef *__unused error) { + return xpc_dictionary_get_bool(message, key); +} + bool SecXPCDictionaryCopyDataOptional(xpc_object_t message, const char *key, CFDataRef *pdata, CFErrorRef *error) { size_t size = 0; if (!xpc_dictionary_get_data(message, key, &size)) { diff --git a/OSX/sec/Security/SecuritydXPC.h b/OSX/sec/Security/SecuritydXPC.h index 31f9254e..bd0b63be 100644 --- a/OSX/sec/Security/SecuritydXPC.h +++ b/OSX/sec/Security/SecuritydXPC.h @@ -31,6 +31,8 @@ bool SecXPCDictionarySetData(xpc_object_t message, const char *key, CFDataRef data, CFErrorRef *error); bool SecXPCDictionarySetDataOptional(xpc_object_t message, const char *key, CFDataRef data, CFErrorRef *error); +bool SecXPCDictionarySetBool(xpc_object_t message, const char *key, bool value, CFErrorRef *error); + bool SecXPCDictionarySetPList(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error); bool SecXPCDictionarySetPListOptional(xpc_object_t message, const char *key, CFTypeRef object, CFErrorRef *error); @@ -51,6 +53,8 @@ bool SecXPCDictionaryCopyArrayOptional(xpc_object_t message, const char *key, CF CFDataRef SecXPCDictionaryCopyData(xpc_object_t message, const char *key, CFErrorRef *error); bool SecXPCDictionaryCopyDataOptional(xpc_object_t message, const char *key, CFDataRef *pdata, CFErrorRef *error); +bool SecXPCDictionaryGetBool(xpc_object_t message, const char *key, CFErrorRef *error); + CFDictionaryRef SecXPCDictionaryCopyDictionary(xpc_object_t message, const char *key, CFErrorRef *error); bool SecXPCDictionaryCopyDictionaryOptional(xpc_object_t message, const char *key, CFDictionaryRef *pdictionary, CFErrorRef *error); diff --git a/OSX/sec/SecurityTool/builtin_commands.h b/OSX/sec/SecurityTool/builtin_commands.h index 6c1610d3..aa526c1e 100644 --- a/OSX/sec/SecurityTool/builtin_commands.h +++ b/OSX/sec/SecurityTool/builtin_commands.h @@ -35,3 +35,11 @@ SECURITY_COMMAND("digest", command_digest, " sha256\n" " sha512\n", "Calculate a digest over the given file(s).") + +SECURITY_COMMAND("whoami", command_whoami, + "", + "Ask securityd who you are.") + +SECURITY_COMMAND("bubble", command_bubble, + "", + "Transfer to sync bubble") diff --git a/OSX/sec/SecurityTool/entitlements.plist b/OSX/sec/SecurityTool/entitlements.plist index a24c7008..f54560d2 100644 --- a/OSX/sec/SecurityTool/entitlements.plist +++ b/OSX/sec/SecurityTool/entitlements.plist @@ -4,6 +4,8 @@ keychain-cloud-circle + restore-keychain + keychain-access-groups test diff --git a/OSX/sec/SecurityTool/syncbubble.m b/OSX/sec/SecurityTool/syncbubble.m new file mode 100644 index 00000000..51eb4554 --- /dev/null +++ b/OSX/sec/SecurityTool/syncbubble.m @@ -0,0 +1,65 @@ +/* + * 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@ + */ + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + +#import +#import +#import +#import + +#include "builtin_commands.h" + + +int +command_bubble(__unused int argc, __unused char * const * argv) +{ + @autoreleasepool { + CFErrorRef error = NULL; + uid_t uid; + + if (argc < 2) + errx(1, "missing uid argument"); + + uid = atoi(argv[1]); + if (uid == 0) + errx(1, "syncbubble for root not supported"); + + NSArray *services = @[@"com.apple.cloudd.sync", @"com.apple.mailq.sync"]; + + if (_SecSyncBubbleTransfer((__bridge CFArrayRef)services, uid, &error)) { + errx(1, "%s", [[NSString stringWithFormat:@"sync bubble populated\n"] UTF8String]); + } else { + errx(1, "%s", [[NSString stringWithFormat:@"sync bubble failed to inflate: %@\n", error] UTF8String]); + } + if (error) + CFRelease(error); + } + + return 0; +} diff --git a/OSX/sec/SecurityTool/whoami.m b/OSX/sec/SecurityTool/whoami.m new file mode 100644 index 00000000..d172d73d --- /dev/null +++ b/OSX/sec/SecurityTool/whoami.m @@ -0,0 +1,56 @@ +/* + * 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@ + */ + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + +#import +#import +#import + +#include "builtin_commands.h" + + +int +command_whoami(__unused int argc, __unused char * const * argv) +{ + @autoreleasepool { + CFErrorRef error = NULL; + NSDictionary *dict = NULL; + + dict = [(__bridge NSDictionary *)_SecSecuritydCopyWhoAmI(&error) autorelease]; + if (dict) { + puts([[NSString stringWithFormat:@"the server thinks we are:\n%@\n", dict] UTF8String]); + } else { + puts([[NSString stringWithFormat:@"no reply from server: %@", error] UTF8String]); + } + if (error) + CFRelease(error); + } + + return 0; +} diff --git a/OSX/sec/ipc/client.c b/OSX/sec/ipc/client.c index 5ed20acb..790d59d7 100644 --- a/OSX/sec/ipc/client.c +++ b/OSX/sec/ipc/client.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -62,24 +64,50 @@ static CFArrayRef SecServerCopyAccessGroups(void) { NULL); } -static CFArrayRef gSecServerAccessGroups; -CFArrayRef SecAccessGroupsGetCurrent(void) { - static dispatch_once_t only_do_this_once; - dispatch_once(&only_do_this_once, ^{ - gSecServerAccessGroups = SecServerCopyAccessGroups(); - assert(gSecServerAccessGroups); +static SecurityClient gClient; + +#if TARGET_OS_IOS +void +SecSecuritySetMusrMode(bool mode, uid_t uid, int activeUser) +{ + gClient.inMultiUser = mode; + gClient.uid = uid; + gClient.activeUser = activeUser; +} +#endif + +SecurityClient * +SecSecurityClientGet(void) +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gClient.task = NULL, + gClient.accessGroups = SecServerCopyAccessGroups(); + gClient.allowSystemKeychain = true; + gClient.allowSyncBubbleKeychain = true; + gClient.isNetworkExtension = false; +#if TARGET_OS_IPHONE + gClient.inMultiUser = false; + gClient.activeUser = 501; +#endif }); - return gSecServerAccessGroups; + return &gClient; +} + +CFArrayRef SecAccessGroupsGetCurrent(void) { + SecurityClient *client = SecSecurityClientGet(); + assert(client && client->accessGroups); + return client->accessGroups; } // Only for testing. void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); void SecAccessGroupsSetCurrent(CFArrayRef accessGroups) { // Not thread safe at all, but OK because it is meant to be used only by tests. - gSecServerAccessGroups = accessGroups; + gClient.accessGroups = accessGroups; } -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)) +#if !TARGET_OS_IPHONE static bool securityd_in_system_context(void) { static bool runningInSystemContext; static dispatch_once_t onceToken; @@ -263,4 +291,89 @@ bool securityd_send_sync_and_do(enum SecXPCOperation op, CFErrorRef *error, } +CFDictionaryRef +_SecSecuritydCopyWhoAmI(CFErrorRef *error) +{ + CFDictionaryRef reply = NULL; + xpc_object_t message = securityd_create_message(kSecXPCOpWhoAmI, error); + if (message) { + xpc_object_t response = securityd_message_with_reply_sync(message, error); + if (response) { + reply = _CFXPCCreateCFObjectFromXPCObject(response); + xpc_release(response); + } else { + securityd_message_no_error(response, error); + } + xpc_release(message); + } + return reply; +} + +bool +_SecSyncBubbleTransfer(CFArrayRef services, uid_t uid, CFErrorRef *error) +{ + xpc_object_t message; + bool reply = false; + + message = securityd_create_message(kSecXPCOpTransmogrifyToSyncBubble, error); + if (message) { + xpc_dictionary_set_int64(message, "uid", uid); + if (SecXPCDictionarySetPList(message, "services", services, error)) { + xpc_object_t response = securityd_message_with_reply_sync(message, error); + if (response) { + reply = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + if (!reply) + securityd_message_no_error(response, error); + xpc_release(response); + } + xpc_release(message); + } + } + return reply; +} + +bool +_SecSystemKeychainTransfer(CFErrorRef *error) +{ + xpc_object_t message; + bool reply = false; + + message = securityd_create_message(kSecXPCOpTransmogrifyToSystemKeychain, error); + if (message) { + xpc_object_t response = securityd_message_with_reply_sync(message, error); + if (response) { + reply = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + if (!reply) + securityd_message_no_error(response, error); + xpc_release(response); + } + xpc_release(message); + } + return reply; +} + +bool +_SecSyncDeleteUserViews(uid_t uid, CFErrorRef *error) +{ + xpc_object_t message; + bool reply = false; + + message = securityd_create_message(kSecXPCOpDeleteUserView, error); + if (message) { + xpc_dictionary_set_int64(message, "uid", uid); + + xpc_object_t response = securityd_message_with_reply_sync(message, error); + if (response) { + reply = xpc_dictionary_get_bool(response, kSecXPCKeyResult); + if (!reply) + securityd_message_no_error(response, error); + xpc_release(response); + } + xpc_release(message); + } + return reply; +} + + + /* vi:set ts=4 sw=4 et: */ diff --git a/OSX/sec/ipc/securityd_client.h b/OSX/sec/ipc/securityd_client.h index c190c5d6..af006ded 100644 --- a/OSX/sec/ipc/securityd_client.h +++ b/OSX/sec/ipc/securityd_client.h @@ -25,7 +25,8 @@ #include -# include +#include +#include #ifndef MINIMIZE_INCLUDES # include # include @@ -39,6 +40,10 @@ typedef struct SecCertificatePath *SecCertificatePathRef; # endif // _SECURITY_SECCERTIFICATEPATH_H_ #endif // MINIMIZE_INCLUDES +#if TARGET_OS_EMBEDDED +#include +#endif + #include #include #include @@ -84,6 +89,7 @@ extern const char *kSecXPCKeyEnabledViewsKey; extern const char *kSecXPCKeyDisabledViewsKey; extern const char *kSecXPCKeyEscrowLabel; extern const char *kSecXPCKeyAvailability; +extern const char *kSecXPCKeyFileDescriptor; // // MARK: Dispatch macros // @@ -224,15 +230,47 @@ enum SecXPCOperation { kSecXPCOpSetEscrowRecord, kSecXPCOpGetEscrowRecord, kSecXPCOpCheckPeerAvailability, + kSecXPCOpCopyAccountData, + kSecXPCOpDeleteAccountData, + kSecXPCOpCopyEngineData, + kSecXPCOpDeleteEngineData, + /* after this is free for all */ + kSecXPCOpWhoAmI, + kSecXPCOpTransmogrifyToSyncBubble, + kSecXPCOpTransmogrifyToSystemKeychain, + kSecXPCOpWrapToBackupSliceKeyBagForView, + kSecXPCOpDeleteUserView, }; +typedef struct { + SecTaskRef task; + CFArrayRef accessGroups; + bool allowSystemKeychain; + bool allowSyncBubbleKeychain; + bool isNetworkExtension; + uid_t uid; + CFDataRef musr; +#if TARGET_OS_EMBEDDED + keybag_handle_t keybag; +#endif +#if TARGET_OS_IPHONE + bool inMultiUser; + int activeUser; +#endif +} SecurityClient; + + +extern SecurityClient * SecSecurityClientGet(void); +#if TARGET_OS_IOS +void SecSecuritySetMusrMode(bool mode, uid_t uid, int activeUser); +#endif struct securityd { - bool (*sec_item_add)(CFDictionaryRef attributes, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef* error); - bool (*sec_item_copy_matching)(CFDictionaryRef query, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef* error); - bool (*sec_item_update)(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef* error); - bool (*sec_item_delete)(CFDictionaryRef query, CFArrayRef accessGroups, CFErrorRef* error); + bool (*sec_item_add)(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *result, CFErrorRef* error); + bool (*sec_item_copy_matching)(CFDictionaryRef query, SecurityClient *client, CFTypeRef *result, CFErrorRef* error); + bool (*sec_item_update)(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, SecurityClient *client, CFErrorRef* error); + bool (*sec_item_delete)(CFDictionaryRef query, SecurityClient *client, CFErrorRef* error); bool (*sec_add_shared_web_credential)(CFDictionaryRef attributes, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); bool (*sec_copy_shared_web_credential)(CFDictionaryRef query, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); SecTrustStoreRef (*sec_trust_store_for_domain)(CFStringRef domainName, CFErrorRef* error); // TODO: remove, has no msg id @@ -242,8 +280,8 @@ struct securityd { bool (*sec_truststore_remove_all)(SecTrustStoreRef ts, CFErrorRef* error); // TODO: remove, has no msg id bool (*sec_item_delete_all)(CFErrorRef* error); SecTrustResultType (*sec_trust_evaluate)(CFArrayRef certificates, CFArrayRef anchors, bool anchorsOnly, CFArrayRef policies, CFArrayRef responses, CFArrayRef SCTs, CFArrayRef trustedLogs, CFAbsoluteTime verifyTime, __unused CFArrayRef accessGroups, CFArrayRef *details, CFDictionaryRef *info, SecCertificatePathRef *chain, CFErrorRef *error); - CFDataRef (*sec_keychain_backup)(CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); - bool (*sec_keychain_restore)(CFDataRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); + CFDataRef (*sec_keychain_backup)(SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); + bool (*sec_keychain_restore)(CFDataRef backup, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); CFDictionaryRef (*sec_keychain_backup_syncable)(CFDictionaryRef backup_in, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); bool (*sec_keychain_restore_syncable)(CFDictionaryRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef* error); CFArrayRef (*sec_item_backup_copy_names)(CFErrorRef *error); @@ -317,6 +355,11 @@ struct securityd { bool (*soscc_SetEscrowRecords)(CFStringRef escrow_label, uint64_t tries, CFErrorRef *error); CFDictionaryRef (*soscc_CopyEscrowRecords)(CFErrorRef *error); bool (*soscc_PeerAvailability)(CFErrorRef *error); + bool (*sosbskb_WrapToBackupSliceKeyBagForView)(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error); + CFDataRef (*soscc_CopyAccountState)(CFErrorRef *error); + bool (*soscc_DeleteAccountState)(CFErrorRef *error); + CFDataRef (*soscc_CopyEngineData)(CFErrorRef *error); + bool (*soscc_DeleteEngineState)(CFErrorRef *error); }; extern struct securityd *gSecurityd; diff --git a/OSX/sec/ipc/server.c b/OSX/sec/ipc/server.c index 4d008578..ff7d1e3f 100644 --- a/OSX/sec/ipc/server.c +++ b/OSX/sec/ipc/server.c @@ -56,9 +56,12 @@ #include #include // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if (TARGET_OS_MAC && TARGET_OS_EMBEDDED) +#if TARGET_OS_EMBEDDED #include -#endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED) +#endif +#if !TARGET_OS_IPHONE +#include +#endif #include #include #include @@ -73,10 +76,11 @@ #include #include -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) -#include +#if TARGET_OS_IPHONE +static int inMultiUser = -1; #endif + static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task, CFStringRef entitlement) { @@ -415,6 +419,49 @@ bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict, const char return success; } +static CFDataRef +SecDataCopyMmapFileDescriptor(int fd, void **mem, size_t *size, CFErrorRef *error) +{ + struct stat sb; + if (fstat(fd, &sb) < 0) { + return NULL; + } + + *size = (size_t)sb.st_size; + if ((off_t)*size != sb.st_size) { + return NULL; + } + + *mem = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0); + if (*mem == MAP_FAILED) { + return NULL; + } + + return CFDataCreateWithBytesNoCopy(NULL, *mem, *size, kCFAllocatorNull); +} + +static CFDataRef +SecDataWriteFileDescriptor(int fd, CFDataRef data) +{ + CFIndex count = CFDataGetLength(data); + const uint8_t *ptr = CFDataGetBytePtr(data); + bool writeResult = false; + + while (count) { + ssize_t ret = write(fd, ptr, count); + if (ret <= 0) + break; + count -= ret; + ptr += ret; + } + if (count == 0) + writeResult = true; + + return writeResult; +} + + + static bool EntitlementMissing(enum SecXPCOperation op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error) { @@ -423,38 +470,87 @@ EntitlementMissing(enum SecXPCOperation op, SecTaskRef clientTask, CFStringRef e } - static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) { xpc_type_t type = xpc_get_type(event); __block CFErrorRef error = NULL; xpc_object_t xpcError = NULL; xpc_object_t replyMessage = NULL; - SecTaskRef clientTask = NULL; CFDataRef clientAuditToken = NULL; - CFArrayRef accessGroups = NULL; CFArrayRef domains = NULL; + SecurityClient client = { + .task = NULL, + .accessGroups = NULL, + .musr = NULL, + .uid = xpc_connection_get_euid(connection), + .allowSystemKeychain = false, + .allowSyncBubbleKeychain = false, + .isNetworkExtension = false, +#if TARGET_OS_IPHONE + .inMultiUser = inMultiUser, +#endif + }; secdebug("serverxpc", "entering"); if (type == XPC_TYPE_DICTIONARY) { // TODO: Find out what we're dispatching. replyMessage = xpc_dictionary_create_reply(event); +#if TARGET_OS_IOS && !TARGET_OS_SIMULATOR + if (inMultiUser) { + assert(inMultiUser != -1); + + client.activeUser = MKBForegroundUserSessionID(&error); + if (client.activeUser == -1 || client.activeUser == 0) { + assert(0); + client.activeUser = 0; + } + + /* + * If we are a edu mode user, and its not the active user, + * then the request is coming from inside the syncbubble. + * + * otherwise we are going to execute the request as the + * active user. + */ + + if (client.uid > 501 && (uid_t)client.activeUser != client.uid) { + secinfo("serverxpc", "securityd client: sync bubble user"); + client.musr = SecMUSRCreateSyncBubbleUserUUID(client.uid); + client.keybag = KEYBAG_DEVICE; + } else { + secinfo("serverxpc", "securityd client: active user"); + client.musr = SecMUSRCreateActiveUserUUID(client.activeUser); + client.uid = (uid_t)client.activeUser; + client.keybag = KEYBAG_DEVICE; + } + } +#endif + uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation); bool hasEntitlement; audit_token_t auditToken = {}; xpc_connection_get_audit_token(connection, &auditToken); - clientTask = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); + client.task = SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken); clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken)); - pthread_setspecific(taskThreadKey, clientTask); - accessGroups = SecTaskCopyAccessGroups(clientTask); + pthread_setspecific(taskThreadKey, client.task); + client.accessGroups = SecTaskCopyAccessGroups(client.task); if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) { - domains = SecTaskCopySharedWebCredentialDomains(clientTask); + domains = SecTaskCopySharedWebCredentialDomains(client.task); + } +#if TARGET_OS_IPHONE + client.allowSystemKeychain = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateSystemKeychain); + client.isNetworkExtension = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateNetworkExtension); +#endif +#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR + if (client.inMultiUser) { + client.allowSyncBubbleKeychain = SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainSyncBubble); } +#endif // TODO: change back to secdebug - secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation); + secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation); if (true) { // Ensure that we remain dirty for a minimum of two seconds to avoid jetsam loops. @@ -468,14 +564,14 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, // operations before kSecXPCOpTryUserCredentials don't need this entitlement. hasEntitlement = (operation < kSecXPCOpTryUserCredentials) || - (clientTask && SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementKeychainCloudCircle)); + (client.task && SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)); // Per Disable the entitlement check for "keychain-cloud-circle" // we disable entitlement enforcement. However, we still log so we know who needs the entitlement if (!hasEntitlement) { CFErrorRef entitlementError = NULL; - SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), clientTask, kSecEntitlementKeychainCloudCircle); + SecError(errSecMissingEntitlement, &entitlementError, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle); secnotice("serverxpc", "MissingEntitlement: %@", entitlementError); CFReleaseSafe(entitlementError); } @@ -488,7 +584,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); if (query) { CFTypeRef result = NULL; - if (_SecItemAdd(query, accessGroups, &result, &error) && result) { + if (_SecItemAdd(query, &client, &result, &error) && result) { SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); CFRelease(result); } @@ -501,7 +597,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); if (query) { CFTypeRef result = NULL; - if (_SecItemCopyMatching(query, accessGroups, &result, &error) && result) { + if (_SecItemCopyMatching(query, &client, &result, &error) && result) { SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); CFRelease(result); } @@ -515,7 +611,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, if (query) { CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error); if (attributesToUpdate) { - bool result = _SecItemUpdate(query, attributesToUpdate, accessGroups, &error); + bool result = _SecItemUpdate(query, attributesToUpdate, &client, &error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); CFRelease(attributesToUpdate); } @@ -527,7 +623,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, { CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); if (query) { - bool result = _SecItemDelete(query, accessGroups, &error); + bool result = _SecItemDelete(query, &client, &error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); CFRelease(query); } @@ -549,7 +645,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } case sec_trust_store_set_trust_settings_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementModifyAnchorCertificates)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementModifyAnchorCertificates)) { SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); if (ts) { SecCertificateRef certificate = SecXPCDictionaryCopyCertificate(event, kSecXPCKeyCertificate, &error); @@ -564,13 +660,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementModifyAnchorCertificates, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementModifyAnchorCertificates, &error); } break; } case sec_trust_store_remove_certificate_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementModifyAnchorCertificates)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementModifyAnchorCertificates)) { SecTrustStoreRef ts = SecXPCDictionaryGetTrustStore(event, kSecXPCKeyDomain, &error); if (ts) { CFDataRef digest = SecXPCDictionaryCopyData(event, kSecXPCKeyDigest, &error); @@ -581,7 +677,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementModifyAnchorCertificates, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementModifyAnchorCertificates, &error); } break; } @@ -602,7 +698,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SecXPCDictionaryGetDouble(event, kSecTrustVerifyDateKey, &verifyTime, &error)) { // If we have no error yet, capture connection and reply in block and properly retain them. xpc_retain(connection); - CFRetainSafe(clientTask); + CFRetainSafe(client.task); CFRetainSafe(clientAuditToken); // Clear replyMessage so we don't send a synchronous reply. @@ -610,7 +706,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, replyMessage = NULL; SecTrustServerEvaluateBlock(clientAuditToken, - certificates, anchors, anchorsOnly, policies, responses, scts, trustedLogs, verifyTime, accessGroups, + certificates, anchors, anchorsOnly, policies, responses, scts, trustedLogs, verifyTime, client.accessGroups, ^(SecTrustResultType tr, CFArrayRef details, CFDictionaryRef info, SecCertificatePathRef chain, CFErrorRef replyError) { // Send back reply now if (replyError) { @@ -622,7 +718,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SecXPCDictionarySetChainOptional(asyncReply, kSecTrustChainKey, chain, &replyError); } if (replyError) { - secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError); + secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyError); xpc_object_t xpcReplyError = SecCreateXPCObjectWithCFError(replyError); if (xpcReplyError) { xpc_dictionary_set_value(asyncReply, kSecXPCKeyError, xpcReplyError); @@ -630,13 +726,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } CFRelease(replyError); } else { - secdebug("ipc", "%@ %@ responding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply); + secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), asyncReply); } xpc_connection_send_message(connection, asyncReply); xpc_release(asyncReply); xpc_release(connection); - CFReleaseSafe(clientTask); + CFReleaseSafe(client.task); CFReleaseSafe(clientAuditToken); }); } @@ -650,13 +746,23 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } case sec_keychain_backup_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFDataRef keybag = NULL, passcode = NULL; if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) { if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { - CFDataRef backup = _SecServerKeychainBackup(keybag, passcode, &error); + CFDataRef backup = _SecServerKeychainCreateBackup(&client, keybag, passcode, &error); if (backup) { - SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error); + int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL); + if (fd < 0) { + SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error); + } else { + bool writeResult = SecDataWriteFileDescriptor(fd, backup); + if (close(fd) != 0) + writeResult = false; + if (!writeResult) + SecError(errSecIO, &error, CFSTR("Failed to write backup file: %d"), errno); + SecXPCDictionarySetBool(replyMessage, kSecXPCKeyResult, writeResult, NULL); + } CFRelease(backup); } CFReleaseSafe(passcode); @@ -664,20 +770,29 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFReleaseSafe(keybag); } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } case sec_keychain_restore_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { - CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error); + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { + CFDataRef backup = NULL; + void *mem = NULL; + size_t size = 0; + + int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL); + if (fd != -1) { + backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error); + } else { + backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error); + } if (backup) { CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); if (keybag) { CFDataRef passcode = NULL; if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) { - bool result = _SecServerKeychainRestore(backup, keybag, passcode, &error); + bool result = _SecServerKeychainRestore(backup, &client, keybag, passcode, &error); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); CFReleaseSafe(passcode); } @@ -685,8 +800,11 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } CFRelease(backup); } + if (mem) { + munmap(mem, size); + } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } @@ -703,7 +821,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } case sec_keychain_backup_syncable_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFDictionaryRef oldbackup = NULL; if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) { @@ -723,13 +841,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFReleaseSafe(oldbackup); } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } case sec_keychain_restore_syncable_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error); if (backup) { @@ -746,24 +864,24 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFRelease(backup); } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } case sec_item_backup_copy_names_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFArrayRef names = SecServerItemBackupCopyNames(&error); SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error); CFReleaseSafe(names); } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } case sec_item_backup_handoff_fd_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error); int fd = -1; if (backupName) { @@ -774,13 +892,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, if (fd != -1) close(fd); } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } case sec_item_backup_set_confirmed_manifest_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFDataRef keybagDigest = NULL; if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) { CFDataRef manifest = NULL; @@ -796,13 +914,13 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFReleaseNull(keybagDigest); } } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } case sec_item_backup_restore_id: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { bool result = false; CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error); if (backupName) { @@ -827,7 +945,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } break; } @@ -842,7 +960,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); if (query) { CFTypeRef result = NULL; - CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL; + CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL; if (_SecAddSharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) { SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); CFRelease(result); @@ -857,7 +975,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error); if (query) { CFTypeRef result = NULL; - CFStringRef appID = (clientTask) ? SecTaskCopyApplicationIdentifier(clientTask) : NULL; + CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL; if (_SecCopySharedWebCredential(query, &auditToken, appID, domains, &result, &error) && result) { SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error); CFRelease(result); @@ -1127,7 +1245,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, break; case kSecXPCOpSetNewPublicBackupKey: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error); SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error); CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL; @@ -1141,19 +1259,19 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, CFReleaseSafe(publicBackupKey); } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } } break; case kSecXPCOpSetBagForAllSlices: { - if (SecTaskGetBooleanValueForEntitlement(clientTask, kSecEntitlementRestoreKeychain)) { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementRestoreKeychain)) { CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error); bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error)); CFReleaseSafe(backupSlice); } else { - EntitlementMissing(((enum SecXPCOperation)operation), clientTask, kSecEntitlementRestoreKeychain, &error); + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementRestoreKeychain, &error); } } break; @@ -1192,15 +1310,79 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, SOSCCCopyViewUnawarePeerInfo_Server(&error), &error); break; + case kSecXPCOpCopyAccountData: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) { + xpc_object_t xpc_account_object = NULL; + CFDataRef accountData = SOSCCCopyAccountState_Server(&error); + if(accountData) + xpc_account_object = _CFXPCCreateXPCObjectFromCFObject(accountData); + + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_account_object); + CFReleaseNull(accountData); + } + else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error); + } + break; + } + case kSecXPCOpDeleteAccountData: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) { + bool status = SOSCCDeleteAccountState_Server(&error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status); + } + else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error); + } + + break; + } + case kSecXPCOpCopyEngineData: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) { + + xpc_object_t xpc_engine_object = NULL; + CFDataRef engineData = SOSCCCopyEngineData_Server(&error); + if(engineData) + xpc_engine_object = _CFXPCCreateXPCObjectFromCFObject(engineData); + + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_engine_object); + CFReleaseNull(engineData); + + } + else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error); + } + break; + } + case kSecXPCOpDeleteEngineData: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) { + + bool status = SOSCCDeleteEngineState_Server(&error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status); + } + else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error); + } + break; + } case kSecXPCOpCopyEngineState: { - CFArrayRef array = SOSCCCopyEngineState_Server(&error); - if (array) { - xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); - xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); - xpc_release(xpc_array); + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementKeychainCloudCircle)) { + + CFArrayRef array = SOSCCCopyEngineState_Server(&error); + if (array) { + xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array); + xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array); + xpc_release(xpc_array); + } + CFReleaseNull(array); + } + else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementKeychainCloudCircle, &error); } - CFReleaseNull(array); } break; case kSecXPCOpCopyPeerPeerInfo: @@ -1272,7 +1454,7 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, { bool force = xpc_dictionary_get_bool(event, "force"); xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, - _SecServerRollKeys(force, &error)); + _SecServerRollKeys(force, &client, &error)); } break; case kSecXPCOpSetHSA2AutoAcceptInfo: @@ -1347,7 +1529,102 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCCheckPeerAvailability_Server(&error)); } break; - default: + case kSecXPCOpWhoAmI: + { + if (client.musr) + xpc_dictionary_set_data(replyMessage, "musr", CFDataGetBytePtr(client.musr), CFDataGetLength(client.musr)); + xpc_dictionary_set_bool(replyMessage, "system-keychain", client.allowSystemKeychain); + xpc_dictionary_set_bool(replyMessage, "syncbubble-keychain", client.allowSyncBubbleKeychain); + xpc_dictionary_set_bool(replyMessage, "network-extension", client.isNetworkExtension); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true); + } + break; + case kSecXPCOpTransmogrifyToSyncBubble: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainSyncBubble)) { +#if TARGET_OS_IOS + uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid"); + CFArrayRef services = SecXPCDictionaryCopyArray(event, "services", &error); + bool res = false; + if (uid && services) { + res = _SecServerTransmogrifyToSyncBubble(services, uid, &client, &error); + } + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res); + CFReleaseNull(services); +#else + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false); +#endif + + } else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementPrivateKeychainSyncBubble, &error); + } + } + break; + case kSecXPCOpTransmogrifyToSystemKeychain: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain)) { +#if TARGET_OS_IOS + bool res = _SecServerTransmogrifyToSystemKeychain(&client, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res); +#else + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false); +#endif + + } else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error); + } + } + break; + case kSecXPCOpDeleteUserView: + { + if (SecTaskGetBooleanValueForEntitlement(client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain)) { + bool res = false; +#if TARGET_OS_IOS + uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid"); + if (uid) { + res = _SecServerDeleteMUSERViews(&client, uid, &error); + } +#endif + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res); + + } else { + EntitlementMissing(((enum SecXPCOperation)operation), client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error); + } + } + break; + case kSecXPCOpWrapToBackupSliceKeyBagForView: + { + CFStringRef viewname = SecXPCDictionaryCopyString(event, kSecXPCKeyViewName, &error); + if(viewname) { + CFDataRef plaintext = SecXPCDictionaryCopyData(event, kSecXPCData, &error); + if (plaintext) { + CFDataRef ciphertext = NULL; + CFDataRef bskbEncoded = NULL; + + bool result = SOSWrapToBackupSliceKeyBagForView_Server(viewname, plaintext, &ciphertext, &bskbEncoded, &error); + xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result); + + if(error) { + xpc_dictionary_set_data(replyMessage, kSecXPCData, NULL, 0); + xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, NULL, 0); + } else if(!result) { + xpc_dictionary_set_data(replyMessage, kSecXPCData, NULL, 0); + xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, NULL, 0); + } else { + if(ciphertext) { + xpc_dictionary_set_data(replyMessage, kSecXPCData, CFDataGetBytePtr(ciphertext), CFDataGetLength(ciphertext)); + } + if(bskbEncoded) { + xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, CFDataGetBytePtr(bskbEncoded), CFDataGetLength(bskbEncoded)); + } + } + } + CFReleaseSafe(plaintext); + } + CFReleaseNull(viewname); + } + break; + default: break; } @@ -1356,22 +1633,22 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, if (error) { if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent)) - secdebug("ipc", "%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); + secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); else if (SecErrorGetOSStatus(error) == errSecAuthNeeded) - secwarning("Authentication is needed %@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); + secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); else - secerror("%@ %@ %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); + secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error); xpcError = SecCreateXPCObjectWithCFError(error); if (replyMessage) { xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError); } } else if (replyMessage) { - secdebug("ipc", "%@ %@ responding %@", clientTask, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage); + secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage); } } else { SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event); - secerror("%@: returning error: %@", clientTask, error); + secerror("%@: returning error: %@", client.task, error); xpcError = SecCreateXPCObjectWithCFError(error); replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError); } @@ -1382,11 +1659,12 @@ static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, } if (xpcError) xpc_release(xpcError); + pthread_setspecific(taskThreadKey, NULL); CFReleaseSafe(error); - CFReleaseSafe(accessGroups); + CFReleaseSafe(client.accessGroups); + CFReleaseSafe(client.musr); + CFReleaseSafe(client.task); CFReleaseSafe(domains); - pthread_setspecific(taskThreadKey, NULL); - CFReleaseSafe(clientTask); CFReleaseSafe(clientAuditToken); } @@ -1424,12 +1702,10 @@ static void securityd_xpc_init(const char *service_name) // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if (TARGET_OS_MAC && TARGET_OS_EMBEDDED) +#if TARGET_OS_EMBEDDED static void securityd_soscc_lock_hack() { dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT); int soscc_tok; - __block MKBAssertionRef lockAssertion = NULL; - uint32_t rc; // Prevent securityd from quitting while holding a keychain assertion // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does, @@ -1441,40 +1717,30 @@ static void securityd_soscc_lock_hack() { }); secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)"); - rc = notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) { - secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: already holding lock %d", (int) (lockAssertion != NULL)); - - // Release previously held assertion (if present) - CFReleaseSafe(lockAssertion); - - // New lock assertion - int k300 = 300; - CFNumberRef cfn300 = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &k300); - const void *keys[] = {kMKBAssertionTypeKey , kMKBAssertionTimeoutKey}; - const void *vals[] = {kMKBAssertionTypeProfile, cfn300}; - CFDictionaryRef lockOptions = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFErrorRef err = NULL; - - lockAssertion = MKBDeviceLockAssertion(lockOptions, &err); - if (lockAssertion) { - // Prevent securityd from quitting while holding a keychain assertion + notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) { + secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock"); + CFErrorRef error = NULL; + + uint64_t one_minute = 60ull; + if(SecAKSLockUserKeybag(one_minute, &error)){ + // Prevent securityd from quitting while holding a keychain assertion xpc_transaction_begin(); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, k300*NSEC_PER_SEC), soscc_lock_queue, ^{ - xpc_transaction_end(); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, one_minute*NSEC_PER_SEC), soscc_lock_queue, ^{ + CFErrorRef localError = NULL; + if(!SecAKSUnLockUserKeybag(&localError)) + secerror("failed to unlock: %@", localError); + CFReleaseNull(localError); + xpc_transaction_end(); }); } else { - secerror("Failed to take device lock assertion: %@", err); + secerror("Failed to take device lock assertion: %@", error); } - CFReleaseSafe(err); + CFReleaseSafe(error); secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done"); - - CFReleaseSafe(cfn300); - CFReleaseSafe(lockOptions); }); } -#endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED) +#endif int main(int argc, char *argv[]) { @@ -1497,10 +1763,26 @@ int main(int argc, char *argv[]) securityd_init_server(); securityd_xpc_init(serviceName); +#if TARGET_OS_IOS && !TARGET_OS_SIMULATOR + if (inMultiUser == -1) { + CFDictionaryRef deviceMode = MKBUserTypeDeviceMode(NULL, NULL); + CFTypeRef value = NULL; + + if (deviceMode && CFDictionaryGetValueIfPresent(deviceMode, kMKBDeviceModeKey, &value) && CFEqual(value, kMKBDeviceModeMultiUser)) { + inMultiUser = 1; + } else { + inMultiUser = 0; + } + CFReleaseNull(deviceMode); + } +#elif TARGET_OS_IPHONE + inMultiUser = 0; +#endif + // 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp -#if (TARGET_OS_MAC && TARGET_OS_EMBEDDED) +#if TARGET_OS_EMBEDDED securityd_soscc_lock_hack(); -#endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED) +#endif dispatch_main(); diff --git a/OSX/sec/sec.xcodeproj/project.pbxproj b/OSX/sec/sec.xcodeproj/project.pbxproj index 337f6fee..c2a5765e 100644 --- a/OSX/sec/sec.xcodeproj/project.pbxproj +++ b/OSX/sec/sec.xcodeproj/project.pbxproj @@ -15,7 +15,7 @@ 0C664AE8175951270092D3D9 /* secd-02-upgrade-while-locked.c in Sources */ = {isa = PBXBuildFile; fileRef = 0C664AE7175951270092D3D9 /* secd-02-upgrade-while-locked.c */; }; 0CBF93F8177B7CFC001E5658 /* secd-03-corrupted-items.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */; }; 0CBF93F9177B7CFC001E5658 /* secd-04-corrupted-items.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */; }; - 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */; }; + 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.m */; }; 0CE7ABDF171383E30088968F /* keychain_backup.c in Sources */ = {isa = PBXBuildFile; fileRef = 0CE7ABDE171383E30088968F /* keychain_backup.c */; }; 18270F5914CF654400B05E7F /* client.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD560614CB6E7A008233F2 /* client.c */; }; 18AD560F14CB6E7A008233F2 /* securityd_client.h in Headers */ = {isa = PBXBuildFile; fileRef = 18AD560814CB6E7A008233F2 /* securityd_client.h */; }; @@ -74,6 +74,7 @@ 4492652A1AB0D6FF00644D4C /* SecCTKKeyPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 449265281AB0D6FF00644D4C /* SecCTKKeyPriv.h */; }; 4802A59616D711060059E5B9 /* SOSUserKeygen.c in Sources */ = {isa = PBXBuildFile; fileRef = 4802A59516D711060059E5B9 /* SOSUserKeygen.c */; }; 4802A59816D7156D0059E5B9 /* SOSUserKeygen.h in Headers */ = {isa = PBXBuildFile; fileRef = 4802A59716D711190059E5B9 /* SOSUserKeygen.h */; settings = {ATTRIBUTES = (); }; }; + 48279BC51C57FEA20043457C /* keychain_log.c in Sources */ = {isa = PBXBuildFile; fileRef = 48279BC31C57FEA20043457C /* keychain_log.c */; }; 484182611A30F2F200211511 /* SOSCirclePriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 484182601A30F2E300211511 /* SOSCirclePriv.h */; }; 484182641A30F8DE00211511 /* SOSPeerInfoPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = 484182631A30F8D300211511 /* SOSPeerInfoPriv.h */; }; 485B5E621AE068D800A3C183 /* secd-82-secproperties-basic.c in Sources */ = {isa = PBXBuildFile; fileRef = 485B5E611AE068D800A3C183 /* secd-82-secproperties-basic.c */; }; @@ -94,14 +95,14 @@ 48A071D01AD6AEA900728AEF /* SOSPeerInfoSecurityProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 48A071CE1AD6AEA900728AEF /* SOSPeerInfoSecurityProperties.h */; }; 48A0FEDE1B6046E2001D6180 /* secd-64-circlereset.c in Sources */ = {isa = PBXBuildFile; fileRef = 48A0FEDD1B6046E2001D6180 /* secd-64-circlereset.c */; }; 48B0B36F1B27B01F003E1EDB /* sc-25-soskeygen.c in Sources */ = {isa = PBXBuildFile; fileRef = 48487D271B1D5E960078C7C9 /* sc-25-soskeygen.c */; }; + 48C34E921C45EF3000B7F29B /* secd60-account-cloud-exposure.c in Sources */ = {isa = PBXBuildFile; fileRef = 48C34E911C45EF3000B7F29B /* secd60-account-cloud-exposure.c */; }; 48C7DF9317FF2DB500904F1A /* SOSAccountCredentials.c in Sources */ = {isa = PBXBuildFile; fileRef = 48C7DF9217FF2DB500904F1A /* SOSAccountCredentials.c */; }; 48C7DF9617FF351A00904F1A /* SOSAccountPeers.c in Sources */ = {isa = PBXBuildFile; fileRef = 48C7DF9517FF351A00904F1A /* SOSAccountPeers.c */; }; 48C7DF9817FF360F00904F1A /* SOSAccountFullPeerInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 48C7DF9717FF360F00904F1A /* SOSAccountFullPeerInfo.c */; }; 48C7DF9A17FF44EF00904F1A /* SOSAccountCloudParameters.c in Sources */ = {isa = PBXBuildFile; fileRef = 48C7DF9917FF44EF00904F1A /* SOSAccountCloudParameters.c */; }; - 48C7E8341A8976E400494D9B /* (null) in Sources */ = {isa = PBXBuildFile; }; - 48C7E8351A8976E400494D9B /* (null) in Headers */ = {isa = PBXBuildFile; }; 48CE733E1731C49A004C2946 /* sc-130-resignationticket.c in Sources */ = {isa = PBXBuildFile; fileRef = 48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */; }; 48E928C5179DD05500A7F755 /* secd-51-account-inflate.c in Sources */ = {isa = PBXBuildFile; fileRef = 48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */; }; + 48E9CDFC1C597FED00574D6B /* SOSSysdiagnose.c in Sources */ = {isa = PBXBuildFile; fileRef = 48E9CDFB1C597FED00574D6B /* SOSSysdiagnose.c */; }; 48F32D7E1777AFA3001B84BA /* secd-59-account-cleanup.c in Sources */ = {isa = PBXBuildFile; fileRef = 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */; }; 48F7DF261A6DB32900046644 /* SOSViews.c in Sources */ = {isa = PBXBuildFile; fileRef = 48F7DF241A6DB32900046644 /* SOSViews.c */; }; 48F7DF271A6DB32900046644 /* SOSViews.h in Headers */ = {isa = PBXBuildFile; fileRef = 48F7DF251A6DB32900046644 /* SOSViews.h */; }; @@ -112,6 +113,7 @@ 48FB17021A76F56C00B586C7 /* SOSPeerInfoV2.c in Sources */ = {isa = PBXBuildFile; fileRef = 48FB17001A76F56C00B586C7 /* SOSPeerInfoV2.c */; }; 48FB17031A76F56C00B586C7 /* SOSPeerInfoV2.h in Headers */ = {isa = PBXBuildFile; fileRef = 48FB17011A76F56C00B586C7 /* SOSPeerInfoV2.h */; }; 48FB17061A771E5700B586C7 /* secd-80-views-basic.c in Sources */ = {isa = PBXBuildFile; fileRef = 48FB17041A77181A00B586C7 /* secd-80-views-basic.c */; }; + 48FEA77C1C53000A0020C148 /* secToolFileIO.c in Sources */ = {isa = PBXBuildFile; fileRef = 48FEA7771C52FFE70020C148 /* secToolFileIO.c */; }; 4A5CCA5415ACEFD400702357 /* SecOTRDHKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971683158FDEB800D439B7 /* SecOTRDHKey.c */; }; 4A5CCA5515ACEFD400702357 /* SecOTRFullIdentity.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971686158FDEB800D439B7 /* SecOTRFullIdentity.c */; }; 4A5CCA5615ACEFD400702357 /* SecOTRMath.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A971688158FDEB800D439B7 /* SecOTRMath.c */; }; @@ -273,7 +275,6 @@ 5284629B1AE6FCF0004C1BA2 /* SOSBackupEvent.c in Sources */ = {isa = PBXBuildFile; fileRef = 528462991AE6FCF0004C1BA2 /* SOSBackupEvent.c */; }; 5284629C1AE6FCF0004C1BA2 /* SOSBackupEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 5284629A1AE6FCF0004C1BA2 /* SOSBackupEvent.h */; }; 529F46F31AEC7A2E0002392C /* secd-34-backup-der-parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 529F46F11AEC759E0002392C /* secd-34-backup-der-parse.c */; }; - 52A126D51AAF6C86006AC7CB /* SOSViewQueries.c in Sources */ = {isa = PBXBuildFile; fileRef = 52A126D31AAF6C86006AC7CB /* SOSViewQueries.c */; }; 52BF439C1AFC50EC00821B5D /* SecItemConstants.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563914CB6EB9008233F2 /* SecItemConstants.c */; }; 52D0F028169CA72800F07D79 /* SecOnOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 52D0F026169CA72800F07D79 /* SecOnOSX.h */; }; 52EAF4BE163C52EB00803D0F /* SOSCloudKeychainClient.c in Sources */ = {isa = PBXBuildFile; fileRef = 521C685C1614A6E100E31C3E /* SOSCloudKeychainClient.c */; }; @@ -296,7 +297,7 @@ ACFD56BE19007B2D00F5F5D9 /* ios6_1_keychain_2_db.h in Headers */ = {isa = PBXBuildFile; fileRef = ACFD56BD19007B2D00F5F5D9 /* ios6_1_keychain_2_db.h */; }; BE061FCF1899E5BD00C739F6 /* si-76-shared-credentials.c in Sources */ = {isa = PBXBuildFile; fileRef = BE061FCE1899E5BD00C739F6 /* si-76-shared-credentials.c */; }; BE0CC6081A96B69000662E69 /* si-83-seccertificate-sighashalg.c in Sources */ = {isa = PBXBuildFile; fileRef = BE0CC6061A96B68400662E69 /* si-83-seccertificate-sighashalg.c */; }; - BE3171931BB3559600BBB212 /* si-20-sectrust.h in Headers */ = {isa = PBXBuildFile; fileRef = BE3171921BB3559600BBB212 /* si-20-sectrust.h */; settings = {ASSET_TAGS = (); }; }; + BE3171931BB3559600BBB212 /* si-20-sectrust.h in Headers */ = {isa = PBXBuildFile; fileRef = BE3171921BB3559600BBB212 /* si-20-sectrust.h */; }; BE4AC9B518B8022D00B84964 /* swcagent_client.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF9640918B418A400813FA3 /* swcagent_client.h */; }; BE4AC9B618B8038400B84964 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; BE53FA301B0AC5C300719A63 /* SecKey.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD563C14CB6EB9008233F2 /* SecKey.c */; }; @@ -313,8 +314,8 @@ BE8D22921ABB726A009A4E18 /* SecTrustSettings.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD564F14CB6EB9008233F2 /* SecTrustSettings.c */; }; BE8D22931ABB7272009A4E18 /* SecTrustStore.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD565214CB6EB9008233F2 /* SecTrustStore.c */; }; BE8D22C21ABBA4D0009A4E18 /* SecCertificatePath.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562314CB6EB9008233F2 /* SecCertificatePath.c */; }; - BECC54E51B98FF0000FB91DC /* si-86-sectrust-eap-tls.c in Sources */ = {isa = PBXBuildFile; fileRef = BECC54E31B98FF0000FB91DC /* si-86-sectrust-eap-tls.c */; settings = {ASSET_TAGS = (); }; }; - BECC54E61B98FF0000FB91DC /* si-86-sectrust-eap-tls.h in Headers */ = {isa = PBXBuildFile; fileRef = BECC54E41B98FF0000FB91DC /* si-86-sectrust-eap-tls.h */; settings = {ASSET_TAGS = (); }; }; + BECC54E51B98FF0000FB91DC /* si-86-sectrust-eap-tls.c in Sources */ = {isa = PBXBuildFile; fileRef = BECC54E31B98FF0000FB91DC /* si-86-sectrust-eap-tls.c */; }; + BECC54E61B98FF0000FB91DC /* si-86-sectrust-eap-tls.h in Headers */ = {isa = PBXBuildFile; fileRef = BECC54E41B98FF0000FB91DC /* si-86-sectrust-eap-tls.h */; }; BEF9640D18B418A400813FA3 /* swcagent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = BEF9640A18B418A400813FA3 /* swcagent_client.c */; }; BEFE994E14F2E17200356A97 /* SecDH.c in Sources */ = {isa = PBXBuildFile; fileRef = 18AD562A14CB6EB9008233F2 /* SecDH.c */; }; C6766768189884D200E9A12C /* SecAccessControl.c in Sources */ = {isa = PBXBuildFile; fileRef = C6766767189884D200E9A12C /* SecAccessControl.c */; }; @@ -323,6 +324,7 @@ CD16F89A1AE84842004AE09C /* sc-150-ring.c in Sources */ = {isa = PBXBuildFile; fileRef = CD16F8941AE84822004AE09C /* sc-150-ring.c */; }; CD32776B18F8AEFD006B5280 /* SOSPeerCoder.c in Sources */ = {isa = PBXBuildFile; fileRef = CD32776A18F8AEFD006B5280 /* SOSPeerCoder.c */; }; CD32776D18F8B06E006B5280 /* SOSPeerCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = CD32776C18F8B06E006B5280 /* SOSPeerCoder.h */; }; + CD35B82A1C2650FE00E0852A /* secd-154-engine-backoff.c in Sources */ = {isa = PBXBuildFile; fileRef = CD35B8291C2650FE00E0852A /* secd-154-engine-backoff.c */; }; CD3FD10716C3064B00A83BB6 /* SecuritydXPC.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B01B8816572579000485F1 /* SecuritydXPC.c */; }; CD5D340B1A80391B00EBF353 /* IDSProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD5D34021A80391B00EBF353 /* IDSProxy.m */; }; CD5D340D1A80391B00EBF353 /* idskeychainsyncingproxy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD5D34051A80391B00EBF353 /* idskeychainsyncingproxy.m */; }; @@ -389,8 +391,6 @@ CDE5F8AB1AF026180074958E /* SOSTransportMessageIDS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD2026B31936ABD300AB9D3C /* SOSTransportMessageIDS.h */; }; CDE5F8AC1AF026470074958E /* SOSTransport.c in Sources */ = {isa = PBXBuildFile; fileRef = CD86DE4D18BD554D00C90CDF /* SOSTransport.c */; }; CDE5F8AD1AF026470074958E /* SOSTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = CDF1B82218BD7DDE006309BC /* SOSTransport.h */; }; - CDE5F8AE1AF026470074958E /* SOSTransportCoder.c in Sources */ = {isa = PBXBuildFile; fileRef = CDC0DC3C1AE83E390020BA6C /* SOSTransportCoder.c */; }; - CDE5F8AF1AF026470074958E /* SOSTransportCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC0DC3D1AE83E390020BA6C /* SOSTransportCoder.h */; }; CDE5F8B01AF026470074958E /* SOSTransportCircle.c in Sources */ = {isa = PBXBuildFile; fileRef = CD0F8AF51899BF46003E0C52 /* SOSTransportCircle.c */; }; CDE5F8B11AF026470074958E /* SOSTransportCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = CD0F8AF91899BF63003E0C52 /* SOSTransportCircle.h */; }; CDE5F8B21AF026470074958E /* SOSTransportCircleKVS.c in Sources */ = {isa = PBXBuildFile; fileRef = CD32777218F8B31E006B5280 /* SOSTransportCircleKVS.c */; }; @@ -405,9 +405,13 @@ CDE5F8BB1AF026470074958E /* SOSTransportMessageKVS.h in Headers */ = {isa = PBXBuildFile; fileRef = CD32777818F8B3B4006B5280 /* SOSTransportMessageKVS.h */; }; CDF42C071A884BB10080BB05 /* idksmain.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF42C061A884BB10080BB05 /* idksmain.m */; }; CDF9BBE11B03E24D00D1AF0F /* secd-52-offering-gencount-reset.c in Sources */ = {isa = PBXBuildFile; fileRef = CDF9BBE01B03E24D00D1AF0F /* secd-52-offering-gencount-reset.c */; }; + D40294A91C20A806008CE4B6 /* si-91-sectrust-ast2.c in Sources */ = {isa = PBXBuildFile; fileRef = D40294A71C20A806008CE4B6 /* si-91-sectrust-ast2.c */; }; + D40294AA1C20A806008CE4B6 /* si-91-sectrust-ast2.h in Headers */ = {isa = PBXBuildFile; fileRef = D40294A81C20A806008CE4B6 /* si-91-sectrust-ast2.h */; }; D4273AA61B5D54E70007D67B /* nameconstraints.c in Sources */ = {isa = PBXBuildFile; fileRef = D4273AA21B5D54CA0007D67B /* nameconstraints.c */; }; D445CDE11B44D53C005040AC /* si-84-sectrust-atv-appsigning.c in Sources */ = {isa = PBXBuildFile; fileRef = D445CDDF1B44D372005040AC /* si-84-sectrust-atv-appsigning.c */; }; D4B4A9A81B8BB9B70097B393 /* si-85-sectrust-ssl-policy.c in Sources */ = {isa = PBXBuildFile; fileRef = D4B4A9A61B8801960097B393 /* si-85-sectrust-ssl-policy.c */; }; + D4CBC1481BE9A89E00C5795E /* si-89-cms-hash-agility.c in Sources */ = {isa = PBXBuildFile; fileRef = D4CBC1461BE9A89E00C5795E /* si-89-cms-hash-agility.c */; }; + D4CBC1491BE9A89E00C5795E /* si-89-cms-hash-agility.h in Headers */ = {isa = PBXBuildFile; fileRef = D4CBC1471BE9A89E00C5795E /* si-89-cms-hash-agility.h */; }; D4DFC94A1B9958D00040945C /* si-87-sectrust-name-constraints.c in Sources */ = {isa = PBXBuildFile; fileRef = D4DFC9481B9958D00040945C /* si-87-sectrust-name-constraints.c */; }; D4DFC94B1B9958D00040945C /* si-87-sectrust-name-constraints.h in Headers */ = {isa = PBXBuildFile; fileRef = D4DFC9491B9958D00040945C /* si-87-sectrust-name-constraints.h */; }; E703811514E1FEEF007CB458 /* SOSCloudCircle.h in Headers */ = {isa = PBXBuildFile; fileRef = E703811114E1FEE4007CB458 /* SOSCloudCircle.h */; }; @@ -432,9 +436,9 @@ E777C71E15B73F9E004044A8 /* SOSInternal.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C71D15B73F9E004044A8 /* SOSInternal.c */; }; E777C72615B87545004044A8 /* SOSPeerInfo.c in Sources */ = {isa = PBXBuildFile; fileRef = E777C72515B87544004044A8 /* SOSPeerInfo.c */; }; E777C72715B882E5004044A8 /* SOSPeerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = E777C72415B87528004044A8 /* SOSPeerInfo.h */; }; - E7850ED01BB30E80002A54CA /* secd-63-account-resurrection.c in Sources */ = {isa = PBXBuildFile; fileRef = E731829F1B1FC9CD00FC334C /* secd-63-account-resurrection.c */; settings = {ASSET_TAGS = (); }; }; - E7850ED11BB30E87002A54CA /* secd-65-account-retirement-reset.c in Sources */ = {isa = PBXBuildFile; fileRef = E7850ECE1BB30E6E002A54CA /* secd-65-account-retirement-reset.c */; settings = {ASSET_TAGS = (); }; }; - E790C10A169E4FD200E0C0C9 /* digest_calc.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C109169E4FD200E0C0C9 /* digest_calc.c */; }; + E77DE60B1C2882EC005259C2 /* si-17-item-system-bluetooth.m in Sources */ = {isa = PBXBuildFile; fileRef = E7EF51911C24C6E3002D0C23 /* si-17-item-system-bluetooth.m */; }; + E7850ED01BB30E80002A54CA /* secd-63-account-resurrection.c in Sources */ = {isa = PBXBuildFile; fileRef = E731829F1B1FC9CD00FC334C /* secd-63-account-resurrection.c */; }; + E7850ED11BB30E87002A54CA /* secd-65-account-retirement-reset.c in Sources */ = {isa = PBXBuildFile; fileRef = E7850ECE1BB30E6E002A54CA /* secd-65-account-retirement-reset.c */; }; E790C110169E53DF00E0C0C9 /* leaks.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C10E169E53DF00E0C0C9 /* leaks.c */; }; E790C141169E5C6200E0C0C9 /* add_internet_password.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C136169E5C6200E0C0C9 /* add_internet_password.c */; }; E790C142169E5C6200E0C0C9 /* codesign.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C137169E5C6200E0C0C9 /* codesign.c */; }; @@ -465,8 +469,17 @@ E7F18557177A502900177B23 /* secd-56-account-apply.c in Sources */ = {isa = PBXBuildFile; fileRef = E7F18556177A502900177B23 /* secd-56-account-apply.c */; }; E7FEFB87169E363300E18152 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 521C0B9815FA5C4A00604B61 /* Foundation.framework */; }; E7FEFB91169E36D800E18152 /* keychain_sync.c in Sources */ = {isa = PBXBuildFile; fileRef = E7FEFB90169E36D800E18152 /* keychain_sync.c */; }; + EB3409AF1C1D5BBE00D77661 /* secd-20-keychain_upgrade.m in Sources */ = {isa = PBXBuildFile; fileRef = EB3409AE1C1D5BB300D77661 /* secd-20-keychain_upgrade.m */; }; + EB69AB041BF3C42F00913AF1 /* SecEMCS.m in Sources */ = {isa = PBXBuildFile; fileRef = EB69AB031BF3C42F00913AF1 /* SecEMCS.m */; }; + EB69AB061BF425FD00913AF1 /* si-90-emcs.m in Sources */ = {isa = PBXBuildFile; fileRef = EB69AB051BF425F300913AF1 /* si-90-emcs.m */; }; + EB69AB071BF4332700913AF1 /* si-90-emcs.m in Sources */ = {isa = PBXBuildFile; fileRef = EB69AB051BF425F300913AF1 /* si-90-emcs.m */; }; EB8F48DD1AE4CC7000CE93A7 /* si-25-sectrust-apple-authentication.c in Sources */ = {isa = PBXBuildFile; fileRef = EB8F48DC1AE4C81400CE93A7 /* si-25-sectrust-apple-authentication.c */; }; + EB9C1D0A1BDDBDE000F89272 /* si-13-item-system.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9C1D091BDDBDD500F89272 /* si-13-item-system.m */; }; + EBC1B8B81BE96B3A00E6ACA6 /* digest_calc.c in Sources */ = {isa = PBXBuildFile; fileRef = E790C109169E4FD200E0C0C9 /* digest_calc.c */; }; + EBC1B8B91BE96B3A00E6ACA6 /* whoami.m in Sources */ = {isa = PBXBuildFile; fileRef = EBC1B8B61BE96B3200E6ACA6 /* whoami.m */; }; EBDAECBC184D32BD005A18F1 /* sc-31-peerinfo-simplefuzz.c in Sources */ = {isa = PBXBuildFile; fileRef = EBDAECBA184D30C3005A18F1 /* sc-31-peerinfo-simplefuzz.c */; }; + EBE32B591BEEC8C900719AA8 /* syncbubble.m in Sources */ = {isa = PBXBuildFile; fileRef = EBE32B581BEEC8C900719AA8 /* syncbubble.m */; }; + EBF2D7661C1E482B006AB6FF /* secd-21-transmogrify.m in Sources */ = {isa = PBXBuildFile; fileRef = EBF2D7651C1E4823006AB6FF /* secd-21-transmogrify.m */; }; F697632318F6CFD60090438B /* keychain_util.c in Sources */ = {isa = PBXBuildFile; fileRef = F697632118F6CC3F0090438B /* keychain_util.c */; }; F953A6A91B43597D006EC5E1 /* si-81-sectrust-appletv.c in Sources */ = {isa = PBXBuildFile; fileRef = F953A6A71B43538A006EC5E1 /* si-81-sectrust-appletv.c */; }; F9E0BD991AEF196E00554D49 /* secd-82-persistent-ref.c in Sources */ = {isa = PBXBuildFile; fileRef = F9E0BD981AEF196A00554D49 /* secd-82-persistent-ref.c */; }; @@ -531,7 +544,7 @@ 0C664AE7175951270092D3D9 /* secd-02-upgrade-while-locked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = "secd-02-upgrade-while-locked.c"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-03-corrupted-items.c"; sourceTree = ""; }; 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-04-corrupted-items.c"; sourceTree = ""; }; - 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-05-corrupted-items.c"; sourceTree = ""; }; + 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-05-corrupted-items.m"; sourceTree = ""; }; 0CE7ABDE171383E30088968F /* keychain_backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_backup.c; sourceTree = ""; }; 18270C9714CF1AAD00B05E7F /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = ""; }; 18270C9814CF1AAD00B05E7F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = ""; }; @@ -650,6 +663,8 @@ 44B2606C18F82631008DF20F /* SecAccessControlExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SecAccessControlExports.exp-in"; sourceTree = ""; }; 4802A59516D711060059E5B9 /* SOSUserKeygen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSUserKeygen.c; sourceTree = ""; }; 4802A59716D711190059E5B9 /* SOSUserKeygen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSUserKeygen.h; sourceTree = ""; }; + 48279BC31C57FEA20043457C /* keychain_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_log.c; sourceTree = ""; }; + 48279BC41C57FEA20043457C /* keychain_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_log.h; sourceTree = ""; }; 484182601A30F2E300211511 /* SOSCirclePriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCirclePriv.h; sourceTree = ""; }; 484182621A30F38E00211511 /* SOSCircleRings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCircleRings.h; sourceTree = ""; }; 484182631A30F8D300211511 /* SOSPeerInfoPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoPriv.h; sourceTree = ""; }; @@ -675,12 +690,14 @@ 48A071CD1AD6AEA900728AEF /* SOSPeerInfoSecurityProperties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoSecurityProperties.c; sourceTree = ""; }; 48A071CE1AD6AEA900728AEF /* SOSPeerInfoSecurityProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoSecurityProperties.h; sourceTree = ""; }; 48A0FEDD1B6046E2001D6180 /* secd-64-circlereset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-64-circlereset.c"; sourceTree = ""; }; + 48C34E911C45EF3000B7F29B /* secd60-account-cloud-exposure.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd60-account-cloud-exposure.c"; sourceTree = ""; }; 48C7DF9217FF2DB500904F1A /* SOSAccountCredentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCredentials.c; sourceTree = ""; }; 48C7DF9517FF351A00904F1A /* SOSAccountPeers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountPeers.c; sourceTree = ""; }; 48C7DF9717FF360F00904F1A /* SOSAccountFullPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountFullPeerInfo.c; sourceTree = ""; }; 48C7DF9917FF44EF00904F1A /* SOSAccountCloudParameters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCloudParameters.c; sourceTree = ""; }; 48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-130-resignationticket.c"; sourceTree = ""; }; 48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-51-account-inflate.c"; sourceTree = ""; }; + 48E9CDFB1C597FED00574D6B /* SOSSysdiagnose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSSysdiagnose.c; sourceTree = ""; }; 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-59-account-cleanup.c"; sourceTree = ""; }; 48F7DF241A6DB32900046644 /* SOSViews.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSViews.c; sourceTree = ""; }; 48F7DF251A6DB32900046644 /* SOSViews.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSViews.h; sourceTree = ""; }; @@ -691,6 +708,8 @@ 48FB17001A76F56C00B586C7 /* SOSPeerInfoV2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoV2.c; sourceTree = ""; }; 48FB17011A76F56C00B586C7 /* SOSPeerInfoV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoV2.h; sourceTree = ""; }; 48FB17041A77181A00B586C7 /* secd-80-views-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-80-views-basic.c"; sourceTree = ""; }; + 48FEA7771C52FFE70020C148 /* secToolFileIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = secToolFileIO.c; sourceTree = ""; }; + 48FEA7781C52FFE70020C148 /* secToolFileIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = secToolFileIO.h; sourceTree = ""; }; 4A5CCA4F15ACEFA500702357 /* libSecOtrOSX.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecOtrOSX.a; sourceTree = BUILT_PRODUCTS_DIR; }; 4A824B03158FF07000F932C0 /* libSecurityRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecurityRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; 4A971682158FDEB800D439B7 /* SecOTR.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOTR.h; sourceTree = ""; }; @@ -745,8 +764,6 @@ 4C8BDDA117B4FE9400C20EA5 /* SOSDigestVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSDigestVector.h; sourceTree = ""; }; 4C9DC91915B602760036D941 /* SOSEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSEngine.h; sourceTree = ""; }; 4C9DC91C15B602910036D941 /* SOSEngine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSEngine.c; sourceTree = ""; }; - 4CB292D81A9E881C003598A1 /* SOSViewManager.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSViewManager.c; sourceTree = ""; }; - 4CB292D91A9E881C003598A1 /* SOSViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSViewManager.h; sourceTree = ""; }; 4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTestDataSource.c; sourceTree = ""; }; 4CB8A83916164B8C00B52EC7 /* SOSTestDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSTestDataSource.h; sourceTree = ""; }; 4CBDB30B17B70206002FA799 /* SOSMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSMessage.c; sourceTree = ""; }; @@ -864,8 +881,6 @@ 528462991AE6FCF0004C1BA2 /* SOSBackupEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSBackupEvent.c; sourceTree = ""; }; 5284629A1AE6FCF0004C1BA2 /* SOSBackupEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSBackupEvent.h; sourceTree = ""; }; 529F46F11AEC759E0002392C /* secd-34-backup-der-parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-34-backup-der-parse.c"; sourceTree = ""; }; - 52A126D31AAF6C86006AC7CB /* SOSViewQueries.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSViewQueries.c; sourceTree = ""; }; - 52A126D41AAF6C86006AC7CB /* SOSViewQueries.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSViewQueries.h; sourceTree = ""; }; 52C3D18E169A53150091D9D3 /* ckdmain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ckdmain.m; path = SOSCircle/CloudKeychainProxy/ckdmain.m; sourceTree = SOURCE_ROOT; }; 52D0F026169CA72800F07D79 /* SecOnOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecOnOSX.h; sourceTree = ""; }; 52DD7069160CD40B0027A346 /* libutilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libutilities.a; path = ../../build/Release/libutilities.a; sourceTree = ""; }; @@ -929,6 +944,7 @@ CD32777418F8B330006B5280 /* SOSTransportCircleKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircleKVS.h; sourceTree = ""; }; CD32777618F8B39B006B5280 /* SOSTransportMessageKVS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportMessageKVS.c; sourceTree = ""; }; CD32777818F8B3B4006B5280 /* SOSTransportMessageKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportMessageKVS.h; sourceTree = ""; }; + CD35B8291C2650FE00E0852A /* secd-154-engine-backoff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-154-engine-backoff.c"; sourceTree = ""; }; CD3F914B1A802EBF00E07119 /* libIDSKeychainSyncingProxy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIDSKeychainSyncingProxy.a; sourceTree = BUILT_PRODUCTS_DIR; }; CD558FA8193544F800CFB3B1 /* IDSFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDSFoundation.framework; path = ../../../../../../../System/Library/PrivateFrameworks/IDSFoundation.framework; sourceTree = ""; }; CD5D34011A80391B00EBF353 /* IDSProxy.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = IDSProxy.h; sourceTree = ""; }; @@ -964,8 +980,6 @@ CDC0DC391AE83E390020BA6C /* SOSRingUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingUtils.h; sourceTree = ""; }; CDC0DC3A1AE83E390020BA6C /* SOSRingV0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSRingV0.c; sourceTree = ""; }; CDC0DC3B1AE83E390020BA6C /* SOSRingV0.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingV0.h; sourceTree = ""; }; - CDC0DC3C1AE83E390020BA6C /* SOSTransportCoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportCoder.c; sourceTree = ""; }; - CDC0DC3D1AE83E390020BA6C /* SOSTransportCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCoder.h; sourceTree = ""; }; CDC0DC941AE842640020BA6C /* SOSAccountRings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountRings.c; sourceTree = ""; }; CDC0DC951AE842640020BA6C /* SOSAccountRingUpdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountRingUpdate.c; sourceTree = ""; }; CDC0DC961AE842640020BA6C /* SOSCircleV2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCircleV2.c; sourceTree = ""; }; @@ -981,10 +995,14 @@ CDF1B82218BD7DDE006309BC /* SOSTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransport.h; sourceTree = ""; }; CDF42C061A884BB10080BB05 /* idksmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = idksmain.m; sourceTree = ""; }; CDF9BBE01B03E24D00D1AF0F /* secd-52-offering-gencount-reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-52-offering-gencount-reset.c"; sourceTree = ""; }; + D40294A71C20A806008CE4B6 /* si-91-sectrust-ast2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-91-sectrust-ast2.c"; sourceTree = ""; }; + D40294A81C20A806008CE4B6 /* si-91-sectrust-ast2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-91-sectrust-ast2.h"; sourceTree = ""; }; D4273AA21B5D54CA0007D67B /* nameconstraints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nameconstraints.c; sourceTree = ""; }; D4273AA31B5D54CA0007D67B /* nameconstraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nameconstraints.h; sourceTree = ""; }; D445CDDF1B44D372005040AC /* si-84-sectrust-atv-appsigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-84-sectrust-atv-appsigning.c"; sourceTree = ""; }; D4B4A9A61B8801960097B393 /* si-85-sectrust-ssl-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-85-sectrust-ssl-policy.c"; sourceTree = ""; }; + D4CBC1461BE9A89E00C5795E /* si-89-cms-hash-agility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-89-cms-hash-agility.c"; sourceTree = ""; }; + D4CBC1471BE9A89E00C5795E /* si-89-cms-hash-agility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-89-cms-hash-agility.h"; sourceTree = ""; }; D4DFC9481B9958D00040945C /* si-87-sectrust-name-constraints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-87-sectrust-name-constraints.c"; sourceTree = ""; }; D4DFC9491B9958D00040945C /* si-87-sectrust-name-constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-87-sectrust-name-constraints.h"; sourceTree = ""; }; E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecureObjectSync.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1016,7 +1034,7 @@ E777C72515B87544004044A8 /* SOSPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfo.c; sourceTree = ""; }; E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-30-peerinfo.c"; sourceTree = ""; }; E7850ECE1BB30E6E002A54CA /* secd-65-account-retirement-reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-65-account-retirement-reset.c"; sourceTree = ""; }; - E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCommands.h; sourceTree = ""; }; + E790C0F4169E3D7200E0C0C9 /* keychain_sync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychain_sync.h; sourceTree = ""; }; E790C108169E4E7900E0C0C9 /* builtin_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = builtin_commands.h; sourceTree = ""; }; E790C109169E4FD200E0C0C9 /* digest_calc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = digest_calc.c; sourceTree = ""; }; E790C10E169E53DF00E0C0C9 /* leaks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = leaks.c; sourceTree = ""; }; @@ -1061,18 +1079,28 @@ E7DBB6081AEAAF3700488C1F /* SOSPeerInfoDER.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoDER.c; sourceTree = ""; }; E7DBB6091AEAAF3700488C1F /* SOSPeerInfoDER.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoDER.h; sourceTree = ""; }; E7EBD75619145D6400D0F062 /* so_01_serverencryption.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = so_01_serverencryption.c; sourceTree = ""; }; + E7EF51911C24C6E3002D0C23 /* si-17-item-system-bluetooth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-17-item-system-bluetooth.m"; sourceTree = ""; }; E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-55-account-incompatibility.c"; sourceTree = ""; }; E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-60-account-cloud-identity.c"; sourceTree = ""; }; E7F18556177A502900177B23 /* secd-56-account-apply.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-56-account-apply.c"; sourceTree = ""; }; E7FEFB8C169E363300E18152 /* libSOSCommands.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSOSCommands.a; sourceTree = BUILT_PRODUCTS_DIR; }; E7FEFB90169E36D800E18152 /* keychain_sync.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; lineEnding = 0; path = keychain_sync.c; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.c; }; + EB3409AE1C1D5BB300D77661 /* secd-20-keychain_upgrade.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-20-keychain_upgrade.m"; sourceTree = ""; }; + EB69AB031BF3C42F00913AF1 /* SecEMCS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecEMCS.m; sourceTree = ""; }; + EB69AB051BF425F300913AF1 /* si-90-emcs.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-90-emcs.m"; sourceTree = ""; }; + EB69AB081BF4335100913AF1 /* SecEMCSPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecEMCSPriv.h; sourceTree = ""; }; EB8F48DC1AE4C81400CE93A7 /* si-25-sectrust-apple-authentication.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "si-25-sectrust-apple-authentication.c"; sourceTree = ""; }; EB973200189C56310063DFED /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; EB973204189C56310063DFED /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; EB973205189C56310063DFED /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; EB973215189C56310063DFED /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; EB97322D189C56DB0063DFED /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = ../../../../../../../System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + EB9C1D091BDDBDD500F89272 /* si-13-item-system.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-13-item-system.m"; sourceTree = ""; }; + EBC1B8B61BE96B3200E6ACA6 /* whoami.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = whoami.m; sourceTree = ""; }; EBDAECBA184D30C3005A18F1 /* sc-31-peerinfo-simplefuzz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-31-peerinfo-simplefuzz.c"; sourceTree = ""; }; + EBE32B581BEEC8C900719AA8 /* syncbubble.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = syncbubble.m; sourceTree = ""; }; + EBE32B9B1BF00DA500719AA8 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = ""; }; + EBF2D7651C1E4823006AB6FF /* secd-21-transmogrify.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-21-transmogrify.m"; sourceTree = ""; }; F697632118F6CC3F0090438B /* keychain_util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = keychain_util.c; sourceTree = ""; }; F697632218F6CC3F0090438B /* keychain_util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychain_util.h; sourceTree = ""; }; F953A6A71B43538A006EC5E1 /* si-81-sectrust-appletv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-81-sectrust-appletv.c"; sourceTree = ""; }; @@ -1337,6 +1365,8 @@ 18AD562C14CB6EB9008233F2 /* SecECKey.c */, 18AD562D14CB6EB9008233F2 /* SecECKey.h */, E757D42219254B3200AF22D9 /* SecECKeyPriv.h */, + EB69AB031BF3C42F00913AF1 /* SecEMCS.m */, + EB69AB081BF4335100913AF1 /* SecEMCSPriv.h */, 18AD562E14CB6EB9008233F2 /* SecFramework.c */, 18AD562014CB6EB9008233F2 /* SecCertificate.c */, 18AD562F14CB6EB9008233F2 /* SecFramework.h */, @@ -1507,9 +1537,11 @@ 4CC92A1915A3ABD400C6D578 /* si-10-find-internet.c */, 4CC92A1A15A3ABD400C6D578 /* si-11-update-data.c */, 4C2C8C3C17AB374700C24C13 /* si-12-item-stress.c */, + EB9C1D091BDDBDD500F89272 /* si-13-item-system.m */, 4CC92A1B15A3ABD400C6D578 /* si-14-dateparse.c */, 4CC92A1C15A3ABD400C6D578 /* si-15-certificate.c */, 4CC92A1D15A3ABD400C6D578 /* si-16-ec-certificate.c */, + E7EF51911C24C6E3002D0C23 /* si-17-item-system-bluetooth.m */, 4CC92A1E15A3ABD400C6D578 /* si-20-sectrust-activation.c */, 4CC92A1F15A3ABD400C6D578 /* si-20-sectrust.c */, BE3171921BB3559600BBB212 /* si-20-sectrust.h */, @@ -1577,6 +1609,11 @@ D4DFC9491B9958D00040945C /* si-87-sectrust-name-constraints.h */, 858A54641BC6FD3E008A03FA /* si-88-sectrust-vpnprofile.c */, 858A54651BC6FD3E008A03FA /* si-88-sectrust-vpnprofile.h */, + D4CBC1461BE9A89E00C5795E /* si-89-cms-hash-agility.c */, + D4CBC1471BE9A89E00C5795E /* si-89-cms-hash-agility.h */, + EB69AB051BF425F300913AF1 /* si-90-emcs.m */, + D40294A71C20A806008CE4B6 /* si-91-sectrust-ast2.c */, + D40294A81C20A806008CE4B6 /* si-91-sectrust-ast2.h */, ); name = secitem; path = Regressions/secitem; @@ -1647,12 +1684,14 @@ 4483050F1B46FB8700326450 /* ios8-inet-keychain-2.h */, 0CBF93F5177B7CFC001E5658 /* secd-03-corrupted-items.c */, 0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */, - 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */, + 0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.m */, 4CC92AAE15A3ACCE00C6D578 /* securityd_regressions.h */, 4CC92AAC15A3AC4600C6D578 /* sd-10-policytree.c */, 0C0BDB601756882A00BC1A7E /* secd_regressions.h */, 0C0BDB62175688DA00BC1A7E /* secd-01-items.c */, 0C664AE7175951270092D3D9 /* secd-02-upgrade-while-locked.c */, + EB3409AE1C1D5BB300D77661 /* secd-20-keychain_upgrade.m */, + EBF2D7651C1E4823006AB6FF /* secd-21-transmogrify.m */, 0C062B1C175E784B00806CFE /* secd-30-keychain-upgrade.c */, 0C062B1D175E784B00806CFE /* secd-31-keychain-bad.c */, 0C062B1E175E784B00806CFE /* secd-31-keychain-unreadable.c */, @@ -1674,6 +1713,7 @@ 4882C516177521AE0095D04B /* secd-58-password-change.c */, 48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */, E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */, + 48C34E911C45EF3000B7F29B /* secd60-account-cloud-exposure.c */, 486C6C671795F20E00387075 /* secd-61-account-leave-not-in-kansas-anymore.c */, CD655E911AF02B9900BD1B6E /* secd-62-account-backup.c */, 48FABEDF1AD05C7100C061D1 /* secd-62-account-hsa-join.c */, @@ -1693,6 +1733,7 @@ F9E0BD981AEF196A00554D49 /* secd-82-persistent-ref.c */, 48FABEE01AD05C7100C061D1 /* secd-90-hsa2.c */, CD8F442C1B83C435004C0047 /* secd-95-escrow-persistence.c */, + CD35B8291C2650FE00E0852A /* secd-154-engine-backoff.c */, E7A10FAA1771245D00C4602F /* SOSAccountTesting.h */, E79D62BE1767A547005A9743 /* SecdTestKeychainUtilities.c */, E79D62BF1767A55F005A9743 /* SecdTestKeychainUtilities.h */, @@ -1793,6 +1834,9 @@ children = ( E790C108169E4E7900E0C0C9 /* builtin_commands.h */, E790C109169E4FD200E0C0C9 /* digest_calc.c */, + EBE32B9B1BF00DA500719AA8 /* entitlements.plist */, + EBC1B8B61BE96B3200E6ACA6 /* whoami.m */, + EBE32B581BEEC8C900719AA8 /* syncbubble.m */, E790C10E169E53DF00E0C0C9 /* leaks.c */, E790C10F169E53DF00E0C0C9 /* leaks.h */, 4CD1897B169F835400BC96B8 /* print_cert.c */, @@ -1904,6 +1948,7 @@ E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */, 4BD2F7FB1ADCDD8C0037CD5D /* SOSForerunnerSession.c */, 4BD2F7FC1ADCDD8C0037CD5D /* SOSForerunnerSession.h */, + 48E9CDFB1C597FED00574D6B /* SOSSysdiagnose.c */, E777C71D15B73F9E004044A8 /* SOSInternal.c */, E777C71B15B73F59004044A8 /* SOSInternal.h */, 52F8DE4A1AF2E9AE00A2C271 /* SOSTypes.h */, @@ -2021,10 +2066,6 @@ 4CC929B215A3957800C6D578 /* SOSPeer.h */, CD32776A18F8AEFD006B5280 /* SOSPeerCoder.c */, CD32776C18F8B06E006B5280 /* SOSPeerCoder.h */, - 4CB292D81A9E881C003598A1 /* SOSViewManager.c */, - 4CB292D91A9E881C003598A1 /* SOSViewManager.h */, - 52A126D31AAF6C86006AC7CB /* SOSViewQueries.c */, - 52A126D41AAF6C86006AC7CB /* SOSViewQueries.h */, ); name = Engine; sourceTree = ""; @@ -2038,8 +2079,6 @@ CDF1B82218BD7DDE006309BC /* SOSTransport.h */, CD773AC21ADDF8C700C808BA /* SOSTransportBackupPeer.c */, CD773AC31ADDF8C700C808BA /* SOSTransportBackupPeer.h */, - CDC0DC3C1AE83E390020BA6C /* SOSTransportCoder.c */, - CDC0DC3D1AE83E390020BA6C /* SOSTransportCoder.h */, CD0F8AF51899BF46003E0C52 /* SOSTransportCircle.c */, CD0F8AF91899BF63003E0C52 /* SOSTransportCircle.h */, CD32777218F8B31E006B5280 /* SOSTransportCircleKVS.c */, @@ -2061,8 +2100,12 @@ E7FEFB81169E362100E18152 /* Tool */ = { isa = PBXGroup; children = ( - E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */, + E790C0F4169E3D7200E0C0C9 /* keychain_sync.h */, E7FEFB90169E36D800E18152 /* keychain_sync.c */, + 48279BC41C57FEA20043457C /* keychain_log.h */, + 48279BC31C57FEA20043457C /* keychain_log.c */, + 48FEA7771C52FFE70020C148 /* secToolFileIO.c */, + 48FEA7781C52FFE70020C148 /* secToolFileIO.h */, ); path = Tool; sourceTree = ""; @@ -2172,6 +2215,8 @@ 4CC92A9E15A3ABD400C6D578 /* login.skype.com.cer.h in Headers */, 4CC92A9F15A3ABD400C6D578 /* login.yahoo.com.1.cer.h in Headers */, 4CC92AA015A3ABD400C6D578 /* login.yahoo.com.2.cer.h in Headers */, + D40294AA1C20A806008CE4B6 /* si-91-sectrust-ast2.h in Headers */, + D4CBC1491BE9A89E00C5795E /* si-89-cms-hash-agility.h in Headers */, 4CC92AA115A3ABD400C6D578 /* login.yahoo.com.cer.h in Headers */, 4CC92AA215A3ABD400C6D578 /* mail.google.com.cer.h in Headers */, 858A54691BC6FE62008A03FA /* si-88-sectrust-vpnprofile.h in Headers */, @@ -2225,9 +2270,7 @@ 4C8BDD9B17B4FB8F00C20EA5 /* SOSDataSource.h in Headers */, CDE5F8BB1AF026470074958E /* SOSTransportMessageKVS.h in Headers */, 484182641A30F8DE00211511 /* SOSPeerInfoPriv.h in Headers */, - 48C7E8351A8976E400494D9B /* (null) in Headers */, CDE5F87E1AF025AC0074958E /* SOSRingPeerInfoUtils.h in Headers */, - 48C7E8351A8976E400494D9B /* (null) in Headers */, CDE5F8841AF025AC0074958E /* SOSRingV0.h in Headers */, CDE5F8A31AF025D60074958E /* SOSPeerInfoDER.h in Headers */, CDE5F8A41AF025D60074958E /* SOSPeerInfoCollections.h in Headers */, @@ -2255,7 +2298,6 @@ CDE5F8A61AF025D60074958E /* SOSPeerInfoRingState.h in Headers */, 4CBDB31017B70323002FA799 /* SOSPeerInfoInternal.h in Headers */, E7217B2815F8131A00D26031 /* SOSCloudKeychainConstants.h in Headers */, - CDE5F8AF1AF026470074958E /* SOSTransportCoder.h in Headers */, 521C68601614A6E100E31C3E /* SOSCloudKeychainClient.h in Headers */, CDE5F8A11AF025BE0074958E /* SOSBackupSliceKeyBag.h in Headers */, CDE5F8821AF025AC0074958E /* SOSRingUtils.h in Headers */, @@ -2654,6 +2696,7 @@ E7F0D3EA177BBE35001ACBC1 /* secd-55-account-incompatibility.c in Sources */, 0C0BDB63175688DA00BC1A7E /* secd-01-items.c in Sources */, 4882C517177521AE0095D04B /* secd-58-password-change.c in Sources */, + EB3409AF1C1D5BBE00D77661 /* secd-20-keychain_upgrade.m in Sources */, E7A10FAE1771249C00C4602F /* secd-57-account-leave.c in Sources */, 48FABEE31AD06B6B00C061D1 /* secd-62-account-hsa-join.c in Sources */, 4469FC2C1AA0A6C90021AA26 /* secd-32-restore-bad-backup.c in Sources */, @@ -2663,12 +2706,13 @@ F9EF72F21AC0F98400A4D24A /* secd-70-engine-smash.c in Sources */, 5384299418E492A300E91AFE /* secd-70-otr-remote.c in Sources */, E7F18557177A502900177B23 /* secd-56-account-apply.c in Sources */, + EB69AB071BF4332700913AF1 /* si-90-emcs.m in Sources */, E7850ED01BB30E80002A54CA /* secd-63-account-resurrection.c in Sources */, 0C664AE8175951270092D3D9 /* secd-02-upgrade-while-locked.c in Sources */, 48FB17061A771E5700B586C7 /* secd-80-views-basic.c in Sources */, 0CBF93F8177B7CFC001E5658 /* secd-03-corrupted-items.c in Sources */, E75AB91B1AE9964800C5EF3F /* secd-40-cc-gestalt.c in Sources */, - 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.c in Sources */, + 0CBF93FC177BA9D9001E5658 /* secd-05-corrupted-items.m in Sources */, 527258D11981C00F003CFCEC /* secd-70-engine.c in Sources */, E7850ED11BB30E87002A54CA /* secd-65-account-retirement-reset.c in Sources */, 4C495EDF1982145200BC1809 /* SOSTestDevice.c in Sources */, @@ -2677,6 +2721,7 @@ 0C062B1F175E784B00806CFE /* secd-30-keychain-upgrade.c in Sources */, 0C062B20175E784B00806CFE /* secd-31-keychain-bad.c in Sources */, 0C062B21175E784B00806CFE /* secd-31-keychain-unreadable.c in Sources */, + 48C34E921C45EF3000B7F29B /* secd60-account-cloud-exposure.c in Sources */, E79D62BB176798FD005A9743 /* secd-50-account.c in Sources */, 48E928C5179DD05500A7F755 /* secd-51-account-inflate.c in Sources */, F9E0BD991AEF196E00554D49 /* secd-82-persistent-ref.c in Sources */, @@ -2689,6 +2734,7 @@ 529F46F31AEC7A2E0002392C /* secd-34-backup-der-parse.c in Sources */, 486C6C691795F9D600387075 /* secd-61-account-leave-not-in-kansas-anymore.c in Sources */, E79D62BD176799EE005A9743 /* SOSTestDataSource.c in Sources */, + EBF2D7661C1E482B006AB6FF /* secd-21-transmogrify.m in Sources */, 448305111B46FC0D00326450 /* secd-35-keychain-migrate-inet.c in Sources */, 4469FC2D1AA0A6D00021AA26 /* secd-33-keychain-ctk.c in Sources */, E79D62BC176799DB005A9743 /* SOSRegressionUtilities.c in Sources */, @@ -2741,9 +2787,11 @@ 449265291AB0D6FF00644D4C /* SecCTKKey.c in Sources */, CD8F442D1B83C435004C0047 /* secd-95-escrow-persistence.c in Sources */, 18D4044214CE1FE400A2BE4E /* SecECKey.c in Sources */, + CD35B82A1C2650FE00E0852A /* secd-154-engine-backoff.c in Sources */, 18D4044314CE1FE400A2BE4E /* SecFramework.c in Sources */, 18D4044414CE1FE400A2BE4E /* SecIdentity.c in Sources */, 18D4044514CE1FE400A2BE4E /* SecImportExport.c in Sources */, + EB69AB041BF3C42F00913AF1 /* SecEMCS.m in Sources */, 18D4044614CE1FE400A2BE4E /* SecItem.c in Sources */, 18D4044714CE1FE400A2BE4E /* SecItemConstants.c in Sources */, 18D4044814CE1FE400A2BE4E /* SecKey.c in Sources */, @@ -2834,6 +2882,7 @@ D4B4A9A81B8BB9B70097B393 /* si-85-sectrust-ssl-policy.c in Sources */, D445CDE11B44D53C005040AC /* si-84-sectrust-atv-appsigning.c in Sources */, BE794826196DBEAD00F4BA63 /* si-81-sectrust-server-auth.c in Sources */, + D4CBC1481BE9A89E00C5795E /* si-89-cms-hash-agility.c in Sources */, 4CC92A5F15A3ABD400C6D578 /* pbkdf2-00-hmac-sha1.c in Sources */, 4CC92A6015A3ABD400C6D578 /* spbkdf-00-hmac-sha1.c in Sources */, 4CC92A6115A3ABD400C6D578 /* otr-00-identity.c in Sources */, @@ -2862,9 +2911,11 @@ 4CC92A7115A3ABD400C6D578 /* si-24-sectrust-appleid.c in Sources */, 4CC92A7215A3ABD400C6D578 /* si-24-sectrust-digicert-malaysia.c in Sources */, 4CC92A7315A3ABD400C6D578 /* si-24-sectrust-diginotar.c in Sources */, + EB9C1D0A1BDDBDE000F89272 /* si-13-item-system.m in Sources */, D4DFC94A1B9958D00040945C /* si-87-sectrust-name-constraints.c in Sources */, CDB6A8B81A409BC600646CD6 /* otr-60-slowroll.c in Sources */, 4CC92A7415A3ABD400C6D578 /* si-24-sectrust-itms.c in Sources */, + EB69AB061BF425FD00913AF1 /* si-90-emcs.m in Sources */, 4CC92A7515A3ABD400C6D578 /* si-24-sectrust-mobileasset.c in Sources */, 4477A8D918F28AB700B5BB9F /* si-78-query-attrs.c in Sources */, 4CC92A7615A3ABD400C6D578 /* si-24-sectrust-nist.c in Sources */, @@ -2878,6 +2929,7 @@ 4CC92A7D15A3ABD400C6D578 /* si-29-sectrust-codesigning.c in Sources */, 4CC92A7E15A3ABD400C6D578 /* si-30-keychain-upgrade.c in Sources */, 4C2C8C3D17AB374700C24C13 /* si-12-item-stress.c in Sources */, + D40294A91C20A806008CE4B6 /* si-91-sectrust-ast2.c in Sources */, 4CC92A7F15A3ABD400C6D578 /* si-31-keychain-bad.c in Sources */, 4CC92A8015A3ABD400C6D578 /* si-31-keychain-unreadable.c in Sources */, 4CC92A8215A3ABD400C6D578 /* si-33-keychain-backup.c in Sources */, @@ -2909,6 +2961,7 @@ 4CC92AA515A3ABD400C6D578 /* vmdh-40.c in Sources */, 4CC92AA615A3ABD400C6D578 /* vmdh-41-example.c in Sources */, 4CC92AA715A3ABD400C6D578 /* vmdh-42-example2.c in Sources */, + E77DE60B1C2882EC005259C2 /* si-17-item-system-bluetooth.m in Sources */, E748744515A61AF800624935 /* si-68-secmatchissuer.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2988,16 +3041,15 @@ 489E6E4C1A71A87600D7EB8C /* SOSCircleDer.c in Sources */, 4CC929B515A3957800C6D578 /* SOSCircle.c in Sources */, 4CC929B715A3957800C6D578 /* SOSPeer.c in Sources */, - 52A126D51AAF6C86006AC7CB /* SOSViewQueries.c in Sources */, CDE5F88B1AF025B30074958E /* SOSRingBasic.c in Sources */, 48C7DF9A17FF44EF00904F1A /* SOSAccountCloudParameters.c in Sources */, E75216AD1AF1F26500DDA573 /* SOSForerunnerSession.c in Sources */, CDE5F8891AF025B30074958E /* SOSRingBackup.c in Sources */, CDE5F8A21AF025D60074958E /* SOSPeerInfoDER.c in Sources */, - CDE5F8AE1AF026470074958E /* SOSTransportCoder.c in Sources */, 48764AEF17FA36200005C4F1 /* SOSAccountUpdate.c in Sources */, CDE5F8AC1AF026470074958E /* SOSTransport.c in Sources */, CDE5F89E1AF025BE0074958E /* SOSAccountRings.c in Sources */, + 48E9CDFC1C597FED00574D6B /* SOSSysdiagnose.c in Sources */, CDE5F89C1AF025BE0074958E /* SOSAccountBackup.c in Sources */, 48C7DF9617FF351A00904F1A /* SOSAccountPeers.c in Sources */, CDE5F88F1AF025B80074958E /* SOSCircleV2.c in Sources */, @@ -3009,7 +3061,6 @@ E777C71E15B73F9E004044A8 /* SOSInternal.c in Sources */, CDE5F8BA1AF026470074958E /* SOSTransportMessageKVS.c in Sources */, E777C72615B87545004044A8 /* SOSPeerInfo.c in Sources */, - 48C7E8341A8976E400494D9B /* (null) in Sources */, CDE5F8B61AF026470074958E /* SOSTransportKeyParameterKVS.c in Sources */, 48764AE817FA2DD00005C4F1 /* SOSAccountDer.c in Sources */, E7217B2715F8131A00D26031 /* SOSCloudKeychainConstants.c in Sources */, @@ -3068,8 +3119,10 @@ files = ( 0CE7ABDF171383E30088968F /* keychain_backup.c in Sources */, E7104A01169E036E00DB0045 /* SecurityTool.c in Sources */, - E790C10A169E4FD200E0C0C9 /* digest_calc.c in Sources */, + EBC1B8B91BE96B3A00E6ACA6 /* whoami.m in Sources */, + EBC1B8B81BE96B3A00E6ACA6 /* digest_calc.c in Sources */, E790C110169E53DF00E0C0C9 /* leaks.c in Sources */, + EBE32B591BEEC8C900719AA8 /* syncbubble.m in Sources */, 4CD1897D169F835400BC96B8 /* print_cert.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3104,7 +3157,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 48279BC51C57FEA20043457C /* keychain_log.c in Sources */, E7FEFB91169E36D800E18152 /* keychain_sync.c in Sources */, + 48FEA77C1C53000A0020C148 /* secToolFileIO.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/OSX/sec/securityd/Regressions/SecdTestKeychainUtilities.c b/OSX/sec/securityd/Regressions/SecdTestKeychainUtilities.c index 00e76b09..0591aac1 100644 --- a/OSX/sec/securityd/Regressions/SecdTestKeychainUtilities.c +++ b/OSX/sec/securityd/Regressions/SecdTestKeychainUtilities.c @@ -27,6 +27,8 @@ #include #include #include +#include + #include @@ -35,9 +37,7 @@ #include #include -void kc_dbhandle_reset(void); - -void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_reset) +void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_in_reset) { CFStringRef tmp_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/tmp/%s.%X/"), test_prefix, arc4random()); CFStringRef keychain_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@Library/Keychains"), tmp_dir); @@ -52,11 +52,8 @@ void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_ SetCustomHomeURL(tmp_dir_string); }); - if(do_before_reset) - do_before_reset(); - - kc_dbhandle_reset(); - + SecKeychainDbReset(do_in_reset); + CFReleaseNull(tmp_dir); CFReleaseNull(keychain_dir); } diff --git a/OSX/sec/securityd/Regressions/secd-01-items.c b/OSX/sec/securityd/Regressions/secd-01-items.c index f3e70f9a..cb25fe2f 100644 --- a/OSX/sec/securityd/Regressions/secd-01-items.c +++ b/OSX/sec/securityd/Regressions/secd-01-items.c @@ -37,7 +37,6 @@ #if USE_KEYSTORE #include -void kc_dbhandle_reset(void); int secd_01_items(int argc, char *const *argv) { @@ -63,7 +62,7 @@ int secd_01_items(int argc, char *const *argv) ok(state&keybag_state_locked, "keybag locked"); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); /* Creating a password */ int v_eighty = 80; @@ -139,7 +138,7 @@ int secd_01_items(int argc, char *const *argv) /* Reset keybag and custom $HOME */ SecItemServerResetKeychainKeybag(); SetCustomHomeURL(NULL); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); CFReleaseNull(pwdata); diff --git a/OSX/sec/securityd/Regressions/secd-05-corrupted-items.c b/OSX/sec/securityd/Regressions/secd-05-corrupted-items.m similarity index 83% rename from OSX/sec/securityd/Regressions/secd-05-corrupted-items.c rename to OSX/sec/securityd/Regressions/secd-05-corrupted-items.m index 21b9e7ad..b9427afa 100644 --- a/OSX/sec/securityd/Regressions/secd-05-corrupted-items.c +++ b/OSX/sec/securityd/Regressions/secd-05-corrupted-items.m @@ -21,28 +21,36 @@ * @APPLE_LICENSE_HEADER_END@ */ +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + -#include "secd_regressions.h" +#import "secd_regressions.h" -#include -#include -#include -#include -#include +#import +#import +#import +#import +#import +#import -#include -#include +#import +#import -#include +#import -#include +#import -#include -#include -#include -#include +#import +#import +#import +#import -#include "SecdTestKeychainUtilities.h" +#import "SecdTestKeychainUtilities.h" #define N_ITEMS (100) #define N_THREADS (10) @@ -116,16 +124,16 @@ int secd_05_corrupted_items(int argc, char *const *argv) CFReleaseNull(port); } - /* corrupt all the password */ - CFStringRef keychain_path_cf = __SecKeychainCopyPath(); - CFStringPerformWithCString(keychain_path_cf, ^(const char *keychain_path) { - /* Create a new keychain sqlite db */ + + SecKeychainDbReset(^{ + /* corrupt all the password */ + NSString *keychain_path = [(NSString *)__SecKeychainCopyPath() autorelease]; + char corrupt_item_sql[80]; sqlite3 *db; - is(sqlite3_open(keychain_path, &db), SQLITE_OK, "open keychain"); + is(sqlite3_open([keychain_path UTF8String], &db), SQLITE_OK, "open keychain"); - char corrupt_item_sql[80]; for(int i=1;i<=N_ITEMS;i++) { ok_unix(snprintf(corrupt_item_sql, sizeof(corrupt_item_sql), "UPDATE inet SET data=X'12345678' WHERE rowid=%d", i)); is(sqlite3_exec(db, corrupt_item_sql, NULL, NULL, NULL), SQLITE_OK, "corrupting keychain item"); @@ -159,6 +167,5 @@ int secd_05_corrupted_items(int argc, char *const *argv) CFReleaseNull(pwdata); CFReleaseNull(query); - CFReleaseNull(keychain_path_cf); return 0; } diff --git a/OSX/sec/securityd/Regressions/secd-154-engine-backoff.c b/OSX/sec/securityd/Regressions/secd-154-engine-backoff.c new file mode 100644 index 00000000..e75660d4 --- /dev/null +++ b/OSX/sec/securityd/Regressions/secd-154-engine-backoff.c @@ -0,0 +1,279 @@ +/* + * 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 + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" + +static int kTestTestCount = 10; +static int MAX_PENALTY_TIME = 32; + +struct monitor_traffic { + CFStringRef key; + int penalty_box; + int total_consecutive_attempts; + int last_write_timestamp; +}; + +static void clear_penalty(struct monitor_traffic *monitor){ + monitor->penalty_box = 0; + monitor->total_consecutive_attempts = 0; + monitor->last_write_timestamp = 0; +} +static int increase_penalty(int time){ + if(time == 32) + return time; + else if(time == 0) + return 1; + else + return (time * 2); +} + +static int decrease_penalty(int time){ + if(time == 0) + return time; + else if(time == 1) + return 0; + else + return (time/2); +} + +//calculate new penalty time based off time passed +static void calculate_new_penalty(struct monitor_traffic *monitor, int current_time){ + int difference = current_time - monitor->last_write_timestamp; + + while(difference){ + if(difference >= monitor->penalty_box * 2){ + monitor->penalty_box = decrease_penalty(monitor->penalty_box); + difference =- monitor->penalty_box *2; + } + else + break; + } +} + +static void keychain_changed_notification(struct monitor_traffic *monitor){ + clear_penalty(monitor); +} + +static void initialize_monitor(struct monitor_traffic *monitor){ + monitor->key = CFSTR("ak|alskdfj:a;lskdjf"); + monitor->penalty_box = 0; + monitor->total_consecutive_attempts = 0; + monitor->last_write_timestamp = 0; +} + +static int backoff_algorithm(CFArrayRef timestamps, struct monitor_traffic *monitor) +{ + __block int successful_writes = 0; + CFNumberRef timestamp; + + CFArrayForEachC(timestamps, timestamp) { + int current_time; + if(!CFNumberGetValue(timestamp, kCFNumberSInt32Type, ¤t_time)) + return successful_writes; + + if(monitor->last_write_timestamp == 0){ //successful default case, initially sending to another peer + successful_writes++; + } + else if(current_time == 0){ //keychain changed notification fired + keychain_changed_notification(monitor); + + } + else{ + if(monitor->last_write_timestamp == (current_time -1) && monitor->total_consecutive_attempts >= 4){ + monitor->penalty_box= increase_penalty(monitor->penalty_box); + monitor->total_consecutive_attempts++; + } + else if(monitor->last_write_timestamp == (current_time -1) && monitor->total_consecutive_attempts < 4 ){ + monitor->total_consecutive_attempts++; + if(monitor->penalty_box == 0) + successful_writes++; + } + else if((current_time - monitor->last_write_timestamp) >= (2*monitor->penalty_box)){ //we haven't written consecutively for 2* the penalty time + monitor->total_consecutive_attempts = 0; + calculate_new_penalty(monitor, current_time); + successful_writes++; + } + else if((current_time - monitor->last_write_timestamp) <= (2*monitor->penalty_box)){ //nonconsecutive write came in within the penalty time + monitor->penalty_box= increase_penalty(monitor->penalty_box); + if(monitor->last_write_timestamp != (current_time-1)) + monitor->total_consecutive_attempts = 0; + else + monitor->total_consecutive_attempts++; + } + } + if(current_time != 0) + monitor->last_write_timestamp = current_time; + } + + return successful_writes; +} + +static void tests(void) +{ + struct monitor_traffic *monitor = (struct monitor_traffic*)malloc(sizeof(struct monitor_traffic)); + initialize_monitor(monitor); + CFMutableArrayRef write_attempts = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); + CFNumberRef timestamp = NULL; + int time; + +/* + * first test: peer continuously writes for 12 minutes + */ + for(int i = 1; i< 13; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + int successful_writes = backoff_algorithm(write_attempts, monitor); + ok(successful_writes == 5, "successfull writes should have only reached 5 minutes"); + ok(monitor->penalty_box == MAX_PENALTY_TIME, "penalty box should have maxed out to 32 minutes"); + + //reset monitor + initialize_monitor(monitor); + CFArrayRemoveAllValues(write_attempts); + +/* + * first test: peer continuously writes for 12 minutes, then backs off 2*(max penalty timeout) + */ + for(int i = 1; i< 13; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + time = 77; + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + time = 109; + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + successful_writes = backoff_algorithm(write_attempts, monitor); + ok(successful_writes == 7, "successfull writes should have only reached 6"); //5 initial writes, then 1 write after enough time passes + ok(monitor->penalty_box == (MAX_PENALTY_TIME/4), "penalty box should have maxed out to 16 minutes"); + + //reset + initialize_monitor(monitor); + CFArrayRemoveAllValues(write_attempts); + +/* + * first test: peer continuously writes for 12 minutes, then backs off exponentially until everything effectively resets + */ + + for(int i = 1; i< 13; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + time = 76; //+ 32*2 + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + time = 108; //+ 16*2 + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + time = 124; //+ 8*2 + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + time = 132; //+ 4*2 + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + time = 136; //+ 2*2 + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + time = 138; //+ 1*2 + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + + successful_writes = backoff_algorithm(write_attempts, monitor); + ok(successful_writes == 11, "successfull writes should have only reached 11"); + ok(monitor->penalty_box == 0, "penalty box should reset back to 0"); + + //reset + initialize_monitor(monitor); + CFArrayRemoveAllValues(write_attempts); + +/* + * first test: peer continuously writes for 12 minutes, then backs off exponentially until everything effectively resets + */ + + for(int i = 1; i< 13; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + time = 0; //flag that keychain changed notification fired + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + + for(int i = 1; i< 13; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + + successful_writes = backoff_algorithm(write_attempts, monitor); + ok(successful_writes == 10, "successfull writes should have only reached 10"); + ok(monitor->penalty_box == MAX_PENALTY_TIME, "penalty box should reset back to 0"); + + //reset + initialize_monitor(monitor); + CFArrayRemoveAllValues(write_attempts); + +/* + * first test: peer continuously writes for 5 minutes, then attempts to write again for another 5 minutes, the once much later + */ + for(int i = 1; i< 6; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + time = 40; + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + + for(int i = 100; i< 106; i++){ + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i); + CFArrayAppendValue(write_attempts, timestamp); + CFReleaseNull(timestamp); + } + time = 250; + timestamp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &time); + CFArrayAppendValue(write_attempts, timestamp); + + successful_writes = backoff_algorithm(write_attempts, monitor); + ok(successful_writes == 12, "successfull writes should have only reached 10"); + ok(monitor->penalty_box == 0, "penalty box should reset back to 0"); +} + +int secd_154_engine_backoff(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + tests(); + + return 0; +} diff --git a/OSX/sec/securityd/Regressions/secd-20-keychain_upgrade.m b/OSX/sec/securityd/Regressions/secd-20-keychain_upgrade.m new file mode 100644 index 00000000..c33d9904 --- /dev/null +++ b/OSX/sec/securityd/Regressions/secd-20-keychain_upgrade.m @@ -0,0 +1,150 @@ +/* + * 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@ + */ + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + + +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import + +#include "secd_regressions.h" +#include "SecdTestKeychainUtilities.h" + + + +static void +keychain_upgrade(bool musr, const char *dbname) +{ + OSStatus res; + + secd_test_setup_temp_keychain(dbname, NULL); + +#if TARGET_OS_IOS + if (musr) + SecSecuritySetMusrMode(true, 502, 502); +#endif + +#if TARGET_OS_IPHONE + /* + * Check system keychain migration + */ + + res = SecItemAdd((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"system-label-me", + (id)kSecUseSystemKeychain : (id)kCFBooleanTrue, + }, NULL); + is(res, 0, "SecItemAdd(system)"); +#endif + + /* + * Check user keychain + */ + + res = SecItemAdd((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"user-label-me", + }, NULL); + is(res, 0, "SecItemAdd(user)"); + + SecKeychainDbReset(^{ + NSString *keychain_path = (NSString *)__SecKeychainCopyPath(); + [keychain_path autorelease]; + + /* Create a new keychain sqlite db */ + sqlite3 *db; + + is(sqlite3_open([keychain_path UTF8String], &db), SQLITE_OK, "create keychain"); + is(sqlite3_exec(db, "UPDATE tversion SET version = version - 1", NULL, NULL, NULL), SQLITE_OK, + "\"downgrade\" keychain"); + is(sqlite3_close(db), SQLITE_OK, "close db"); + + }); + +#if TARGET_OS_IPHONE + res = SecItemCopyMatching((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"system-label-me", + (id)kSecUseSystemKeychain : (id)kCFBooleanTrue, + }, NULL); + is(res, 0, "SecItemCopyMatching(system)"); +#endif + + res = SecItemCopyMatching((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"user-label-me", + }, NULL); + is(res, 0, "SecItemCopyMatching(user)"); + +#if TARGET_OS_IOS + if (musr) + SecSecuritySetMusrMode(false, 501, -1); +#endif +} + +void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); +CFArrayRef SecAccessGroupsGetCurrent(); + +int +secd_20_keychain_upgrade(int argc, char *const *argv) +{ +#if TARGET_OS_IPHONE +#define have_system_keychain_tests 2 +#else +#define have_system_keychain_tests 0 +#endif + + plan_tests((kSecdTestSetupTestCount + 5 + have_system_keychain_tests) * 2); + + CFArrayRef currentACL = SecAccessGroupsGetCurrent(); + + NSMutableArray *newACL = [NSMutableArray arrayWithArray:(__bridge NSArray *)currentACL]; + [newACL addObjectsFromArray:@[ + @"com.apple.private.system-keychain", + @"com.apple.private.syncbubble-keychain", + @"com.apple.private.migrate-musr-system-keychain", + ]]; + + SecAccessGroupsSetCurrent((__bridge CFArrayRef)newACL); + + keychain_upgrade(false, "secd_20_keychain_upgrade"); + keychain_upgrade(true, "secd_20_keychain_upgrade-musr"); + + SecAccessGroupsSetCurrent(currentACL); + + return 0; +} diff --git a/OSX/sec/securityd/Regressions/secd-21-transmogrify.m b/OSX/sec/securityd/Regressions/secd-21-transmogrify.m new file mode 100644 index 00000000..97bc756d --- /dev/null +++ b/OSX/sec/securityd/Regressions/secd-21-transmogrify.m @@ -0,0 +1,195 @@ +/* + * 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@ + */ + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + + +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import + +#include "secd_regressions.h" +#include "SecdTestKeychainUtilities.h" + +void SecAccessGroupsSetCurrent(CFArrayRef accessGroups); +CFArrayRef SecAccessGroupsGetCurrent(); + +int +secd_21_transmogrify(int argc, char *const *argv) +{ + plan_tests(kSecdTestSetupTestCount + 14); + +#if TARGET_OS_IOS + CFErrorRef error = NULL; + CFDictionaryRef result = NULL; + OSStatus res; + + CFArrayRef currentACL = SecAccessGroupsGetCurrent(); + + NSMutableArray *newACL = [NSMutableArray arrayWithArray:(__bridge NSArray *)currentACL]; + [newACL addObjectsFromArray:@[ + @"com.apple.private.system-keychain", + @"com.apple.private.syncbubble-keychain", + @"com.apple.private.migrate-musr-system-keychain", + @"com.apple.ProtectedCloudStorage", + ]]; + + SecAccessGroupsSetCurrent((__bridge CFArrayRef)newACL); + + + secd_test_setup_temp_keychain("secd_21_transmogrify", NULL); + + /* + * Add to user keychain + */ + + res = SecItemAdd((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"user-label-me", + }, NULL); + is(res, 0, "SecItemAdd(user)"); + + SecurityClient client = { + .task = NULL, + .accessGroups = (__bridge CFArrayRef)@[ + @"com.apple.ProtectedCloudStorage" + ], + .allowSystemKeychain = true, + .allowSyncBubbleKeychain = true, + .uid = 502, + .inMultiUser = false, + .activeUser = 502, + }; + + is(_SecServerTransmogrifyToSystemKeychain(&client, &error), true, "_SecServerTransmogrifyToSystemKeychain: %@", error); + + CFDataRef musr = SecMUSRCreateActiveUserUUID(502); + + client.inMultiUser = true; + client.musr = musr; + + SecSecuritySetMusrMode(true, 502, 502); + + res = SecItemCopyMatching((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"user-label-me", + (id)kSecUseSystemKeychain : (id)kCFBooleanTrue, + (id)kSecReturnAttributes : (id)kCFBooleanTrue, + }, (CFTypeRef *)&result); + is(res, 0, "SecItemCopyMatching(system)"); + + ok(isDictionary(result), "found item"); + if (isDictionary(result)) { + NSData *data = ((NSDictionary *)result)[@"musr"]; + ok([data isEqual:(id)SecMUSRGetSystemKeychainUUID()], "item is system keychain"); + } else { + ok(0, "returned item is: %@", result); + } + CFReleaseNull(result); + + /* + * Check sync bubble + */ + + res = _SecItemAdd((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccessGroup : @"com.apple.ProtectedCloudStorage", + (id)kSecAttrAccessible : (id)kSecAttrAccessibleAfterFirstUnlock, + (id)kSecAttrAccount : @"pcs-label-me", + }, &client, NULL, NULL); + is(res, true, "SecItemAdd(user)"); + + res = _SecItemCopyMatching((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"pcs-label-me", + (id)kSecReturnAttributes : (id)kCFBooleanTrue, + }, &client, (CFTypeRef *)&result, &error); + is(res, true, "SecItemCopyMatching(system): %@", error); + + ok(isDictionary(result), "result is dictionary"); + + /* Check that data are in 502 active user keychain */ + ok (CFEqualSafe(((__bridge NSDictionary *)result)[@"musr"], musr), "not in msr 502"); + + CFReleaseNull(result); + + + ok(_SecServerTransmogrifyToSyncBubble((__bridge CFArrayRef)@[@"com.apple.mailq.sync.xpc" ], client.uid, &client, &error), + "_SecServerTransmogrifyToSyncBubble: %@", error); + + CFReleaseNull(error); + + /* + * first check normal keychain + */ + + res = _SecItemCopyMatching((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"pcs-label-me", + (id)kSecReturnAttributes : (id)kCFBooleanTrue, + }, &client, (CFTypeRef *)&result, &error); + is(res, true, "SecItemCopyMatching(active): %@", error); + + ok(isDictionary(result), "result is dictionary"); + CFReleaseNull(result); + + SecSecuritySetMusrMode(true, 503, 503); + + /* + * then syncbubble keychain + */ + + res = _SecItemCopyMatching((CFDictionaryRef)@{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrAccount : @"pcs-label-me", + (id)kSecReturnAttributes : (id)kCFBooleanTrue, + (id)kSecUseSyncBubbleKeychain : @502, + }, &client, (CFTypeRef *)&result, &error); + is(res, true, "SecItemCopyMatching(syncbubble): %@", error); + ok(isDictionary(result), "result is dictionary"); + + CFReleaseNull(result); + + SecSecuritySetMusrMode(false, 501, -1); + + SecAccessGroupsSetCurrent((__bridge CFArrayRef)currentACL); + + CFRelease(musr); +#else + plan_skip_all("not support on non TARGET_OS_IOS"); +#endif + return 0; +} diff --git a/OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c b/OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c index 794e2ace..c153b4cd 100644 --- a/OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c +++ b/OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c @@ -40,6 +40,7 @@ #include #include +#include #include "secd_regressions.h" @@ -354,7 +355,7 @@ static void test_item_delete(void) { is(phase, 0); phase = 0; -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED LASetErrorCodeBlock(^{ return (CFErrorRef)NULL; }); deleteError = CFErrorCreate(NULL, CFSTR(kTKErrorDomain), kTKErrorCodeAuthenticationFailed, NULL); ok_status(SecItemDelete(query), "delete multiple token items"); @@ -373,7 +374,7 @@ static void test_item_delete(void) { CFRelease(query); CFReleaseSafe(deleteError); } -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED static const int kItemDeleteTestCount = 15; #else static const int kItemDeleteTestCount = 14; @@ -532,7 +533,7 @@ static void test_key_sign(void) { is(CFDataGetLength(sig), CFDataGetLength(valueData)); eq_cf(valueData, sig); -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED phase = 0; CFDataSetLength(sig, 256); sigLen = CFDataGetLength(sig); @@ -551,10 +552,10 @@ static void test_key_sign(void) { CFRelease(privateKey); CFRelease(query); } -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED static const int kKeySignTestCount = 11; #else -static const int kKeySignTestCount = 5; +static const int kKeySignTestCount = 6; #endif static void test_key_generate_with_params(void) { diff --git a/OSX/sec/securityd/Regressions/secd-34-backup-der-parse.c b/OSX/sec/securityd/Regressions/secd-34-backup-der-parse.c index b8d49c89..31f8c345 100644 --- a/OSX/sec/securityd/Regressions/secd-34-backup-der-parse.c +++ b/OSX/sec/securityd/Regressions/secd-34-backup-der-parse.c @@ -434,7 +434,7 @@ static void secd_perform_with_data_in_file(const char* test_prefix, void(^with)( if(do_before_reset) do_before_reset(); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); CFReleaseNull(tmp_dir); CFReleaseNull(keychain_dir); diff --git a/OSX/sec/securityd/Regressions/secd-62-account-backup.c b/OSX/sec/securityd/Regressions/secd-62-account-backup.c index 72b643db..50cae95e 100644 --- a/OSX/sec/securityd/Regressions/secd-62-account-backup.c +++ b/OSX/sec/securityd/Regressions/secd-62-account-backup.c @@ -129,6 +129,8 @@ static void tests(void) ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error); CFReleaseNull(peers); + + is(SOSAccountUpdateView(alice_account, kTestView1, kSOSCCViewEnable, &error), kSOSCCViewMember, "Enable view (%@)", error); CFReleaseNull(error); @@ -140,7 +142,10 @@ static void tests(void) ok(SOSAccountSetBackupPublicKey(bob_account, bob_backup_key, &error), "Set backup public key, alice (%@)", error); CFReleaseNull(error); - + + SOSAccountEnsureBackupStarts(alice_account); + SOSAccountEnsureBackupStarts(bob_account); + ok(SOSAccountIsMyPeerInBackupAndCurrentInView(alice_account, kTestView1), "Is alice is in backup before sync?"); ok(SOSAccountIsMyPeerInBackupAndCurrentInView(bob_account, kTestView1), "Is bob in the backup after sync? - 1"); @@ -184,6 +189,8 @@ static void tests(void) CFReleaseNull(error); ok(SOSAccountSetBackupPublicKey(bob_account, bob_backup_key, &error), "Set backup public key, alice (%@)", error); + SOSAccountEnsureBackupStarts(bob_account); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, NULL), 1, "updates"); @@ -204,6 +211,7 @@ static void tests(void) ok(SOSAccountSetBackupPublicKey(bob_account, bob_backup_key, &error), "Set backup public key, alice (%@)", error); CFReleaseNull(error); + SOSAccountEnsureBackupStarts(bob_account); is(SOSAccountUpdateView(bob_account, kTestView1, kSOSCCViewEnable, &error), kSOSCCViewMember, "Enable view (%@)", error); ok(SOSAccountStartNewBackup(bob_account, kTestView1, &error), "Setting new backup public key for bob account failed: (%@)", error); diff --git a/OSX/sec/securityd/Regressions/secd-70-engine.c b/OSX/sec/securityd/Regressions/secd-70-engine.c index a56bf494..58046edb 100644 --- a/OSX/sec/securityd/Regressions/secd-70-engine.c +++ b/OSX/sec/securityd/Regressions/secd-70-engine.c @@ -62,7 +62,6 @@ __unused static bool SOSCircleHandleCircleWithLock(SOSEngineRef engine, CFString CFDataRef coder = CFDataCreate(kCFAllocatorDefault, expected, resultSize); CFArrayForEachC(SOSEngineGetPeerIDs(engine), peerID){ CFArrayAppendValue(trustedPeers, peerID); - SOSEngineSetCoderData(engine, peerID, coder, error); }; CFReleaseNull(coder); @@ -302,8 +301,7 @@ SKIP: unlink(keychain_path); }); - void kc_dbhandle_reset(void); - kc_dbhandle_reset(); + SecKeychainDbReset(NULL); #else skip("Keychain not reset", kTestTestCount, false); #endif diff --git a/OSX/sec/securityd/Regressions/secd-80-views-basic.c b/OSX/sec/securityd/Regressions/secd-80-views-basic.c index 80b9c85e..2d3bfcf9 100644 --- a/OSX/sec/securityd/Regressions/secd-80-views-basic.c +++ b/OSX/sec/securityd/Regressions/secd-80-views-basic.c @@ -89,7 +89,7 @@ static void tests(void) CFReleaseNull(error); CFReleaseNull(cfpassword); - ok(SOSAccountJoinCircles(account, &error), "Join Cirlce"); + ok(SOSAccountJoinCircles(account, &error), "Join circle: %@", error); ok(NULL != account, "Created"); diff --git a/OSX/sec/securityd/Regressions/secd-81-item-acl-stress.c b/OSX/sec/securityd/Regressions/secd-81-item-acl-stress.c index 87bd8e15..2e0ad638 100644 --- a/OSX/sec/securityd/Regressions/secd-81-item-acl-stress.c +++ b/OSX/sec/securityd/Regressions/secd-81-item-acl-stress.c @@ -32,7 +32,6 @@ #include #endif -void kc_dbhandle_reset(void); #endif enum ItemAttrType { @@ -48,7 +47,7 @@ enum ItemAttrType { extern void LASetErrorCodeBlock(CFErrorRef (^newCreateErrorBlock)(void)); -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED static keybag_handle_t test_keybag; static const char *passcode = "password"; @@ -148,7 +147,7 @@ static void ItemForEachPKAttr(CFMutableDictionaryRef item, void(^each)(CFStringR } } -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED CF_RETURNS_RETAINED static CFErrorRef createCFError(CFStringRef message, CFIndex code) { @@ -211,7 +210,7 @@ static void tests(bool isPasscodeSet) return (CFErrorRef)NULL; }; -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED CFErrorRef (^errorNotInteractiveBlock)(void) = ^ { return createCFError(CFSTR(""), kLAErrorNotInteractive); }; @@ -239,18 +238,16 @@ static void tests(bool isPasscodeSet) LASetErrorCodeBlock(okBlock); CFDictionarySetValue(item, kSecAttrAccessControl, aclRef); CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse); -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED ok_status(SecItemAdd(item, NULL), "add local "); ok_status(SecItemCopyMatching(item, NULL), "find local"); ok_status(SecItemDelete(item), "delete local"); is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find after delete local"); -#endif CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanTrue); is_status(SecItemAdd(item, NULL), errSecParam, "add sync"); is_status(SecItemCopyMatching(item, NULL), errSecItemNotFound, "do not find sync"); CFDictionarySetValue(item, kSecAttrSynchronizable, kCFBooleanFalse); -#if USE_KEYSTORE if(isPasscodeSet) { SecAccessControlRef aclWithUIRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, protectionClass, kSecAccessControlUserPresence, NULL); ok(aclWithUIRef, "Create SecAccessControlRef which require UI interaction"); @@ -339,7 +336,7 @@ static void tests(bool isPasscodeSet) int secd_81_item_acl_stress(int argc, char *const *argv) { -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED secd_test_setup_temp_keychain(__FUNCTION__, ^{ keybag_state_t state; int passcode_len=(int)strlen(passcode); @@ -355,11 +352,11 @@ int secd_81_item_acl_stress(int argc, char *const *argv) bool isPasscodeSet = false; #endif - plan_tests(isPasscodeSet?776:196); + plan_tests(isPasscodeSet?776:140); tests(isPasscodeSet); -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED SecItemServerResetKeychainKeybag(); #endif diff --git a/OSX/sec/securityd/Regressions/secd-81-item-acl.c b/OSX/sec/securityd/Regressions/secd-81-item-acl.c index eb0efa3c..b5c256b3 100644 --- a/OSX/sec/securityd/Regressions/secd-81-item-acl.c +++ b/OSX/sec/securityd/Regressions/secd-81-item-acl.c @@ -33,7 +33,7 @@ #include #endif -void kc_dbhandle_reset(void); +#if LA_CONTEXT_IMPLEMENTED static keybag_handle_t test_keybag; static const char *passcode1 = "passcode1"; static const char *passcode2 = "passcode2"; @@ -54,6 +54,7 @@ static bool changePasscode(const char *old_passcode, const char *new_passcode) } #endif +#endif enum ItemAttrType { @@ -193,7 +194,7 @@ static void fillItem(CFMutableDictionaryRef item, uint32_t num) }); } -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED CF_RETURNS_RETAINED static CFErrorRef createCFError(CFStringRef message, CFIndex code) { @@ -464,7 +465,7 @@ static void item_with_skip_auth_ui(uint32_t *item_num) int secd_81_item_acl(int argc, char *const *argv) { uint32_t item_num = 1; -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED secd_test_setup_temp_keychain(__FUNCTION__, ^{ keybag_state_t state; int passcode_len=(int)strlen(passcode1); @@ -489,7 +490,7 @@ int secd_81_item_acl(int argc, char *const *argv) item_with_skip_auth_ui(&item_num); #endif -#if USE_KEYSTORE +#if LA_CONTEXT_IMPLEMENTED SecItemServerResetKeychainKeybag(); #endif diff --git a/OSX/sec/securityd/Regressions/secd60-account-cloud-exposure.c b/OSX/sec/securityd/Regressions/secd60-account-cloud-exposure.c new file mode 100644 index 00000000..a23cae5e --- /dev/null +++ b/OSX/sec/securityd/Regressions/secd60-account-cloud-exposure.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// secd60-account-cloud-exposure.c +// sec +// + + + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "secd_regressions.h" +#include "SOSTestDataSource.h" + +#include "SOSRegressionUtilities.h" +#include +#include + +#include + +#include "SOSAccountTesting.h" + +#include "SecdTestKeychainUtilities.h" + +static int kTestTestCount = 58; + +static bool SOSAccountAddiCloudIdentity(SOSAccountRef account, SOSCircleRef circle, SecKeyRef user_key, CFErrorRef *error) { + bool result = false; + SOSFullPeerInfoRef cloud_identity = NULL; + SOSPeerInfoRef cloud_peer = GenerateNewCloudIdentityPeerInfo(error); + require_quiet(cloud_peer, err_out); + cloud_identity = CopyCloudKeychainIdentity(cloud_peer, error); + CFReleaseNull(cloud_peer); + require_quiet(cloud_identity, err_out); + require_quiet(SOSCircleRequestAdmission(circle, user_key, cloud_identity, error), err_out); + require_quiet(SOSCircleAcceptRequest(circle, user_key, account->my_identity, SOSFullPeerInfoGetPeerInfo(cloud_identity), error), err_out); + result = true; +err_out: + return result; +} + +static bool SOSAccountResetCircleToNastyOffering(SOSAccountRef account, SecKeyRef userPriv, SOSPeerInfoRef pi, CFErrorRef *error) { + bool result = false; + SecKeyRef userPub = SecKeyCreatePublicFromPrivate(userPriv); + + require(SOSAccountHasCircle(account, error), fail); + require(SOSAccountEnsureFullPeerAvailable(account, error), fail); + + // Save for reclaming + //mygestalt = CFDictionaryCreateCopy(kCFAllocatorDefault, SOSPeerGetGestalt(SOSFullPeerInfoGetPeerInfo(account->my_identity))); + + (void) SOSAccountResetAllRings(account, error); + + SOSAccountModifyCircle(account, error, ^(SOSCircleRef circle) { + bool result = false; + CFErrorRef localError = NULL; + SOSFullPeerInfoRef iCloudfpi = NULL; + + //sleep(10); + require_quiet(SOSCircleResetToEmpty(circle, error), err_out); + require_quiet(SOSAccountAddiCloudIdentity(account, circle, userPriv, error), err_out); + require_quiet(iCloudfpi = SOSCircleCopyiCloudFullPeerInfoRef(circle, error), err_out); + + /* Add the defenders peerInfo to circle */ + require_quiet(SOSCircleRequestReadmission(circle, userPub, pi, error), err_out); + require_quiet(SOSCircleAcceptRequest(circle, userPriv, iCloudfpi, pi, error), err_out); + + account->departure_code = kSOSNeverLeftCircle; + + result = true; + account->trusted_circle = SOSCircleCopyCircle(kCFAllocatorDefault, circle, error); + SOSAccountPublishCloudParameters(account, NULL); + account->my_identity = NULL; + + err_out: + if (result == false) + secerror("error resetting circle (%@) to offering: %@", circle, localError); + if (localError && error && *error == NULL) { + *error = localError; + localError = NULL; + } + CFReleaseNull(localError); + return result; + }); + + result = true; + +fail: + return result; +} + +static bool SOSAccountResetToNastyOffering(SOSAccountRef account, SOSPeerInfoRef pi, CFErrorRef* error) { + SecKeyRef user_key = SOSAccountGetPrivateCredential(account, error); + if (!user_key) + return false; + + CFReleaseNull(account->my_identity); + + return user_key && SOSAccountResetCircleToNastyOffering(account, user_key, pi, error); +} + +static bool performiCloudIdentityAttack(SOSAccountRef attacker, SOSAccountRef defender, SOSAccountRef accomplice, CFMutableDictionaryRef changes) { + CFErrorRef error = NULL; + bool retval = false; // false means the attack succeeds + CFArrayRef applicants = NULL; + + /*----- Carole makes bogus circle with fake iCloud identity and Alice's peerInfo but only signed with fake iCloud identity -----*/ + + require_action_quiet(SOSAccountResetToNastyOffering(attacker, SOSFullPeerInfoGetPeerInfo(defender->my_identity), &error), testDone, retval = true); + CFReleaseNull(error); + + ProcessChangesUntilNoChange(changes, defender, accomplice, attacker, NULL); + + /*----- Now use our fake iCloud identity to get in to the circle for real -----*/ + require_action_quiet(SOSAccountJoinCirclesAfterRestore(attacker, &error), testDone, retval = true); + CFReleaseNull(error); + require_action_quiet(countPeers(attacker) == 2, testDone, retval = true); + + /*----- Let's see if carole can get bob into the circle and have alice believe it -----*/ + require_action_quiet(SOSAccountJoinCircles(accomplice, &error), testDone, retval = true); + CFReleaseNull(error); + + ProcessChangesUntilNoChange(changes, defender, accomplice, attacker, NULL); + + applicants = SOSAccountCopyApplicants(attacker, &error); + CFReleaseNull(error); + + if(CFArrayGetCount(applicants) > 0) { + require_action_quiet(SOSAccountAcceptApplicants(attacker, applicants, &error), testDone, retval = true); + } + + ProcessChangesUntilNoChange(changes, defender, accomplice, attacker, NULL); + + require_action_quiet(countPeers(defender) == 3, testDone, retval = true); + require_action_quiet(countPeers(accomplice) == 3, testDone, retval = true); + require_action_quiet(countPeers(attacker) == 3, testDone, retval = true); + +testDone: + CFReleaseNull(applicants); + CFReleaseNull(error); + return retval; +} + +static void tests(void) +{ + CFErrorRef error = NULL; + CFDataRef cfpassword = CFDataCreate(NULL, (uint8_t *) "FooFooFoo", 10); + CFStringRef cfaccount = CFSTR("test@test.org"); + + CFMutableDictionaryRef changes = CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault); + + SOSAccountRef alice_account = CreateAccountForLocalChanges( CFSTR("Alice"), CFSTR("TestSource")); + SOSAccountRef bob_account = CreateAccountForLocalChanges(CFSTR("Bob"), CFSTR("TestSource")); + SOSAccountRef carole_account = CreateAccountForLocalChanges(CFSTR("Carole"), CFSTR("TestSource")); + + ok(SOSAccountAssertUserCredentialsAndUpdate(bob_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + + // Bob wins writing at this point, feed the changes back to alice. + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 1, "updates"); + + ok(SOSAccountAssertUserCredentialsAndUpdate(alice_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + + ok(SOSAccountAssertUserCredentialsAndUpdate(carole_account, cfaccount, cfpassword, &error), "Credential setting (%@)", error); + CFReleaseNull(error); + ok(SOSAccountResetToOffering(alice_account, &error), "Reset to offering (%@)", error); + CFReleaseNull(error); + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 2, "updates"); + + ok(SOSAccountJoinCircles(bob_account, &error), "Bob Applies (%@)", error); + CFReleaseNull(error); + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 2, "updates"); + + { + CFArrayRef applicants = SOSAccountCopyApplicants(alice_account, &error); + + ok(applicants && CFArrayGetCount(applicants) == 1, "See one applicant %@ (%@)", applicants, error); + ok(SOSAccountAcceptApplicants(alice_account, applicants, &error), "Alice accepts (%@)", error); + CFReleaseNull(error); + CFReleaseNull(applicants); + } + + is(ProcessChangesUntilNoChange(changes, alice_account, bob_account, carole_account, NULL), 3, "updates"); + + accounts_agree("bob&alice pair", bob_account, alice_account); + + + ok(performiCloudIdentityAttack(carole_account, alice_account, bob_account, changes), "Attack is defeated"); + + CFReleaseNull(bob_account); + CFReleaseNull(alice_account); + CFReleaseNull(carole_account); + CFReleaseNull(cfpassword); + + SOSUnregisterAllTransportMessages(); + SOSUnregisterAllTransportCircles(); + SOSUnregisterAllTransportKeyParameters(); + CFArrayRemoveAllValues(key_transports); + CFArrayRemoveAllValues(circle_transports); + CFArrayRemoveAllValues(message_transports); + +} + +int secd_60_account_cloud_exposure(int argc, char *const *argv) +{ + plan_tests(kTestTestCount); + + secd_test_setup_temp_keychain(__FUNCTION__, NULL); + + tests(); + + return 0; +} diff --git a/OSX/sec/securityd/Regressions/secd_regressions.h b/OSX/sec/securityd/Regressions/secd_regressions.h index b4ca0f1e..9f6d66cb 100644 --- a/OSX/sec/securityd/Regressions/secd_regressions.h +++ b/OSX/sec/securityd/Regressions/secd_regressions.h @@ -29,6 +29,8 @@ ONE_TEST(secd_02_upgrade_while_locked) ONE_TEST(secd_03_corrupted_items) DISABLED_ONE_TEST(secd_04_corrupted_items) ONE_TEST(secd_05_corrupted_items) +ONE_TEST(secd_20_keychain_upgrade) +ONE_TEST(secd_21_transmogrify) DISABLED_ONE_TEST(secd_30_keychain_upgrade) //obsolete, needs updating ONE_TEST(secd_31_keychain_bad) ONE_TEST(secd_31_keychain_unreadable) @@ -49,13 +51,14 @@ ONE_TEST(secd_57_account_leave) ONE_TEST(secd_58_password_change) ONE_TEST(secd_59_account_cleanup) ONE_TEST(secd_60_account_cloud_identity) +ONE_TEST(secd_60_account_cloud_exposure) ONE_TEST(secd_61_account_leave_not_in_kansas_anymore) ONE_TEST(secd_62_account_hsa_join) ONE_TEST(secd_62_account_backup) ONE_TEST(secd_63_account_resurrection) ONE_TEST(secd_64_circlereset) ONE_TEST(secd_65_account_retirement_reset) -DISABLED_ONE_TEST(secd_70_engine) +ONE_TEST(secd_70_engine) ONE_TEST(secd_70_engine_corrupt) ONE_TEST(secd_70_engine_smash) DISABLED_ONE_TEST(secd_70_otr_remote) @@ -73,3 +76,5 @@ ONE_TEST(secd_81_item_acl) ONE_TEST(secd_82_persistent_ref) DISABLED_ONE_TEST(secd_90_hsa2) ONE_TEST(secd_95_escrow_persistence) +ONE_TEST(secd_154_engine_backoff) + diff --git a/OSX/sec/securityd/SOSCloudCircleServer.c b/OSX/sec/securityd/SOSCloudCircleServer.c index fbba5450..2647456d 100644 --- a/OSX/sec/securityd/SOSCloudCircleServer.c +++ b/OSX/sec/securityd/SOSCloudCircleServer.c @@ -68,6 +68,8 @@ #include #include +#include +#include #if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR #include @@ -116,8 +118,6 @@ CFStringRef kSOSBurnedRecoveryAttemptCount = CFSTR("Burned Recovery Attempt Coun CFStringRef kSOSBurnedRecoveryAttemptAttestationDate = CFSTR("Burned Recovery Attempt Attestation Date"); -static CFStringRef accountFileName = CFSTR("PersistedAccount.plist"); - static CFDictionaryRef SOSItemCopyQueryForSyncItems(CFStringRef service, bool returnData) { return CFDictionaryCreateForCFTypes(kCFAllocatorDefault, @@ -450,7 +450,7 @@ static SOSAccountRef GetSharedAccount(void) { } sSharedAccount = SOSKeychainAccountCreateSharedAccount(gestalt); - + SOSAccountAddChangeBlock(sSharedAccount, ^(SOSCircleRef circle, CFSetRef peer_additions, CFSetRef peer_removals, CFSetRef applicant_additions, CFSetRef applicant_removals) { @@ -531,6 +531,8 @@ static SOSAccountRef GetSharedAccount(void) { } static void do_with_account_dynamic(void (^action)(SOSAccountRef account), bool sync) { + Boolean keyExistsAndHasValue = false; + whichTransportType = CFPreferencesGetAppIntegerValue(CFSTR("Transport"), CFSTR("com.apple.security"), &keyExistsAndHasValue); SOSAccountRef account = GetSharedAccount(); if(account){ @@ -538,7 +540,7 @@ static void do_with_account_dynamic(void (^action)(SOSAccountRef account), bool SOSPeerInfoRef mpi = SOSAccountGetMyPeerInfo(account); bool wasInCircle = SOSAccountIsInCircle(account, NULL); CFSetRef beforeViews = mpi ? SOSPeerInfoCopyEnabledViews(mpi) : NULL; - + action(account); // Fake transaction around using the account object @@ -1356,34 +1358,121 @@ CFArrayRef SOSCCCopyEngineState_Server(CFErrorRef* error) return result; } +static CFStringRef CreateUUIDString() { + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + CFStringRef result = CFUUIDCreateString(kCFAllocatorDefault, uuid); + CFReleaseNull(uuid); + return result; +} + +static CFStringRef SOSAccountCallWhenInSync(SOSAccountRef account, SOSAccountWaitForInitialSyncBlock syncBlock) { + //if we are not initially synced + CFStringRef id = NULL; + CFTypeRef unSyncedViews = SOSAccountGetValue(account, kSOSUnsyncedViewsKey, NULL); + if (unSyncedViews != NULL) { + id = CreateUUIDString(); + secnotice("initial-sync", "adding sync block [%@] to array!", id); + SOSAccountWaitForInitialSyncBlock copy = Block_copy(syncBlock); + CFDictionarySetValue(account->waitForInitialSync_blocks, id, copy); + Block_release(copy); + } else { + syncBlock(account); + } + + return id; +} + +static bool SOSAccountUnregisterCallWhenInSync(SOSAccountRef account, CFStringRef id) { + bool removed = CFDictionaryGetValueIfPresent(account->waitForInitialSync_blocks, id, NULL); + CFDictionaryRemoveValue(account->waitForInitialSync_blocks, id); + return removed; +} + bool SOSCCWaitForInitialSync_Server(CFErrorRef* error) { + __block dispatch_semaphore_t inSyncSema = NULL; + __block bool result = false; + __block bool synced = false; + bool timed_out = false; - bool result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + __block CFStringRef inSyncCallID = NULL; + + secnotice("initial sync", "Wait for initial sync start!"); + + result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { bool alreadyInSync = SOSAccountCheckHasBeenInSync(account); - int token = -1; + if (!alreadyInSync) { inSyncSema = dispatch_semaphore_create(0); - dispatch_retain(inSyncSema); - notify_register_dispatch(kSOSCCInitialSyncChangedNotification, &token, - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token) { - dispatch_semaphore_signal(inSyncSema); - dispatch_release(inSyncSema); - - notify_cancel(token); - }); + dispatch_retain(inSyncSema); // For the block + + inSyncCallID = SOSAccountCallWhenInSync(account, ^bool(SOSAccountRef mightBeSynced) { + secerror("might be synced!"); + synced = SOSAccountCheckHasBeenInSync(mightBeSynced); + + dispatch_semaphore_signal(inSyncSema); + dispatch_release(inSyncSema); + SOSAccountEnsureBackupStarts(account); + return true; + }); + } + else{ + SOSAccountEnsureBackupStarts(account); + synced = true; } return true; }); - - if (result && inSyncSema != NULL) { - dispatch_semaphore_wait(inSyncSema, DISPATCH_TIME_FOREVER); + + require_quiet(result, fail); + if(inSyncSema){ + timed_out = dispatch_semaphore_wait(inSyncSema, dispatch_time(DISPATCH_TIME_NOW, 300ull * NSEC_PER_SEC)); + } + if (timed_out) { + do_with_account(^(SOSAccountRef account) { + if (SOSAccountUnregisterCallWhenInSync(account, inSyncCallID)) { + dispatch_release(inSyncSema); // if we unregistered we release the sema + } + }); + + if (!synced) { + secerror("waiting for initial sync timed out, resetting account"); + result = false; + + SOSCCLoggedOutOfAccount_Server(error); + SOSErrorCreate(kSOSInitialSyncFailed, error, NULL, CFSTR("InitialSyncTimedOut")); + } + } + if(inSyncSema) dispatch_release(inSyncSema); + inSyncSema = NULL; // We've canceled the timeout so we must be the last. + + require_quiet(result, fail); + + + xpc_transaction_begin(); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + result = do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + result = SOSAccountIsInCircle(account, NULL); + xpc_transaction_end(); + return result; + }); + }); + + if (!synced) { + secerror("waiting for initial sync: left circle"); + result = false; + + SOSErrorCreate(kSOSInitialSyncFailed, error, NULL, CFSTR("Left circle before initial sync.")); } + secnotice("initial sync", "Finished!: %d", result); +fail: + CFReleaseNull(inSyncCallID); return result; } + static CFArrayRef SOSAccountCopyYetToSyncViews(SOSAccountRef account, CFErrorRef *error) { __block CFArrayRef result = NULL; @@ -1419,6 +1508,63 @@ CFArrayRef SOSCCCopyYetToSyncViewsList_Server(CFErrorRef* error) { return views; } +bool SOSWrapToBackupSliceKeyBagForView_Server(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error) { + CFErrorRef localerror = NULL; + SOSBackupSliceKeyBagRef bskb = SOSBackupSliceKeyBagForView(viewName, &localerror); + + if(bskbEncoded && bskb) { + *bskbEncoded = SOSBSKBCopyEncoded(bskb, &localerror); + } + + if(output) { + *output = SOSWrapToBackupSliceKeyBag(bskb, input, &localerror); + } + + if(error) { + *error = localerror; + } + return localerror == NULL; +} + +SOSBackupSliceKeyBagRef SOSBackupSliceKeyBagForView(CFStringRef viewName, CFErrorRef* error){ + __block SOSBackupSliceKeyBagRef bskb = NULL; + (void) do_with_account(^ (SOSAccountRef account) { + bskb = SOSAccountBackupSliceKeyBagForView(account, viewName, error); + }); + return bskb; +} + +CFDataRef SOSWrapToBackupSliceKeyBag(SOSBackupSliceKeyBagRef bskb, CFDataRef input, CFErrorRef* error) { + CFDataRef encrypted = NULL; + bskb_keybag_handle_t bskb_handle = 0; + + require_quiet(bskb, exit); + + bskb_handle = SOSBSKBLoadLocked(bskb, error); + require_quiet(bskb_handle, exit); + + SecAccessControlRef access = NULL; + require_quiet(access = SecAccessControlCreate(kCFAllocatorDefault, error), exit); + require_quiet(SecAccessControlSetProtection(access, kSecAttrAccessibleWhenUnlocked, error), exit); + + // ks_encrypt_data takes a dictionary as its plaintext. + CFMutableDictionaryRef plaintext = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(plaintext, CFSTR("data"), input); + + require_quiet(ks_encrypt_data(bskb_handle, access, NULL, plaintext, NULL, &encrypted, error), exit); + +exit: + CFReleaseNull(bskb); + if(bskb_handle != 0) { + ks_close_keybag(bskb_handle, error); + } + if(error && *error) { + secnotice("backup", "Failed to wrap to a BKSB: %@", *error); + } + return encrypted; + +} + CFDictionaryRef SOSCCCopyEscrowRecord_Server(CFErrorRef *error){ __block CFDictionaryRef result = NULL; @@ -1580,6 +1726,60 @@ SOSPeerInfoRef SOSCCCopyMyPeerInfo_Server(CFErrorRef* error) return result; } +CFDataRef SOSCCCopyAccountState_Server(CFErrorRef* error) +{ + __block CFDataRef accountState = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + // Copy account state from the keychain + accountState = SOSAccountCopyAccountStateFromKeychain(block_error); + return accountState != NULL; + }); + + return accountState; +} + +bool SOSCCDeleteAccountState_Server(CFErrorRef* error) +{ + __block bool result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + // Delete account state from the keychain + result = SOSAccountDeleteAccountStateFromKeychain(block_error); + return result; + }); + + return result; +} + +CFDataRef SOSCCCopyEngineData_Server(CFErrorRef* error) +{ + __block CFDataRef engineState = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + // Copy engine state from the keychain + engineState = SOSAccountCopyEngineStateFromKeychain(block_error); + return engineState != NULL; + }); + + return engineState; +} + +bool SOSCCDeleteEngineState_Server(CFErrorRef* error) +{ + __block bool result = NULL; + + (void) do_with_account_if_after_first_unlock(error, ^bool (SOSAccountRef account, CFErrorRef* block_error) { + // Delete engine state from the keychain + result = SOSAccountDeleteEngineStateFromKeychain(block_error); + return result; + }); + + return result; +} + + + SOSPeerInfoRef SOSCCSetNewPublicBackupKey_Server(CFDataRef newPublicBackup, CFErrorRef *error){ __block SOSPeerInfoRef result = NULL; diff --git a/OSX/sec/securityd/SOSCloudCircleServer.h b/OSX/sec/securityd/SOSCloudCircleServer.h index 2f6631b2..b0355242 100644 --- a/OSX/sec/securityd/SOSCloudCircleServer.h +++ b/OSX/sec/securityd/SOSCloudCircleServer.h @@ -106,7 +106,10 @@ bool SOSCCRegisterSingleRecoverySecret_Server(CFDataRef backupSlice, bool setupV bool SOSCCWaitForInitialSync_Server(CFErrorRef*); CFArrayRef SOSCCCopyYetToSyncViewsList_Server(CFErrorRef*); +bool SOSWrapToBackupSliceKeyBagForView_Server(CFStringRef viewName, CFDataRef input, CFDataRef* output, CFDataRef* bskbEncoded, CFErrorRef* error); +SOSBackupSliceKeyBagRef SOSBackupSliceKeyBagForView(CFStringRef viewName, CFErrorRef* error); +CF_RETURNS_RETAINED CFDataRef SOSWrapToBackupSliceKeyBag(SOSBackupSliceKeyBagRef bskb, CFDataRef input, CFErrorRef* error); // // MARK: Internal kicks. @@ -132,6 +135,10 @@ bool SOSKeychainAccountSetFactoryForAccount(SOSCCAccountDataSourceFactoryBlock f // MARK: Internal SPIs for testing // CFStringRef CopyOSVersion(void); +CFDataRef SOSCCCopyAccountState_Server(CFErrorRef* error); +CFDataRef SOSCCCopyEngineData_Server(CFErrorRef* error); +bool SOSCCDeleteEngineState_Server(CFErrorRef* error); +bool SOSCCDeleteAccountState_Server(CFErrorRef* error); // diff --git a/OSX/sec/securityd/SecCAIssuerRequest.c b/OSX/sec/securityd/SecCAIssuerRequest.c index a18a2002..265aefda 100644 --- a/OSX/sec/securityd/SecCAIssuerRequest.c +++ b/OSX/sec/securityd/SecCAIssuerRequest.c @@ -1,22 +1,15 @@ /* - * SecCAIssuerRequest.c - * Security - * - * Copyright (c) 2009-2014 Apple Inc.. All Rights Reserved. - * - */ -/* - * Copyright (c) 2009-2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2009-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, @@ -24,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@ */ @@ -104,7 +97,7 @@ static CFArrayRef SecCAIssuerConvertToParents(SecCertificateRef certificate, CFArrayRef parents = NULL; if (parent) { CFDataRef parent_nic = SecCertificateGetNormalizedSubjectContent(parent); - if (parent_nic && CFEqual(nic, parent_nic)) { + if (nic && parent_nic && CFEqual(nic, parent_nic)) { const void *ventry = parent; parents = CFArrayCreate(NULL, &ventry, 1, &kCFTypeArrayCallBacks); } @@ -161,7 +154,7 @@ static CFArrayRef SecCAIssuerRequestCacheCopyParents(SecCertificateRef cert, SecCAIssuerCacheCopyMatching(issuer)); if (parents) { secdebug("caissuer", "cache hit, for %@ no request issued", issuer); - CFRelease(scheme); + CFRelease(scheme); return parents; } } diff --git a/OSX/sec/securityd/SecDbItem.c b/OSX/sec/securityd/SecDbItem.c index c42735e7..6f4565f5 100644 --- a/OSX/sec/securityd/SecDbItem.c +++ b/OSX/sec/securityd/SecDbItem.c @@ -71,6 +71,21 @@ CFDataRef copyData(CFTypeRef obj) { } } +CFTypeRef copyUUID(CFTypeRef obj) { + CFTypeID tid = CFGetTypeID(obj); + if (tid == CFDataGetTypeID()) { + CFIndex length = CFDataGetLength(obj); + if (length != 0 && length != 16) + return NULL; + return CFDataCreateCopy(NULL, obj); + } if (tid == CFNullGetTypeID()) { + return CFDataCreate(NULL, NULL, 0); + } else { + return NULL; + } +} + + CFTypeRef copyBlob(CFTypeRef obj) { CFTypeID tid = CFGetTypeID(obj); if (tid == CFDataGetTypeID()) { @@ -160,8 +175,18 @@ static CFNumberRef SecDbColumnCopyNumber(CFAllocatorRef allocator, sqlite3_stmt } } -static CFStringRef SecDbColumnCopyString(CFAllocatorRef allocator, sqlite3_stmt *stmt, int col, CFErrorRef *error) { +static CFTypeRef SecDbColumnCopyString(CFAllocatorRef allocator, sqlite3_stmt *stmt, int col, CFErrorRef *error, + CFOptionFlags flags) { const unsigned char *text = sqlite3_column_text(stmt, col); + if (!text || 0 == strlen((const char *)text)) { + if (flags & kSecDbDefaultEmptyFlag) { + return CFSTR(""); + } else if (flags & kSecDbDefault0Flag) { + return CFSTR("0"); + } else { + return kCFNull; + } + } return CFStringCreateWithBytes(allocator, text, strlen((const char *)text), kCFStringEncodingUTF8, false); } @@ -208,6 +233,9 @@ CFTypeRef SecDbAttrCopyDefaultValue(const SecDbAttr *attr, CFErrorRef *error) { case kSecDbDataAttr: value = CFDataCreate(kCFAllocatorDefault, NULL, 0); break; + case kSecDbUUIDAttr: + value = CFDataCreate(kCFAllocatorDefault, NULL, 0); + break; case kSecDbNumberAttr: case kSecDbSyncAttr: case kSecDbTombAttr: @@ -399,6 +427,9 @@ static CFTypeRef SecDbItemCopyValue(SecDbItemRef item, const SecDbAttr *attr, CF value = kCFNull; } break; + case kSecDbUUIDAttr: + value = CFDataCreate(CFGetAllocator(item), NULL, 0); + break; case kSecDbNumberAttr: case kSecDbSyncAttr: case kSecDbTombAttr: @@ -471,7 +502,7 @@ static CFTypeRef SecDbItemCopyValueForDb(SecDbItemRef item, const SecDbAttr *des CFTypeRef value = NULL; CFStringRef hash_name = NULL; hash_name = SecDbAttrGetHashName(desc); - if ((desc->flags & (kSecDbSHA1ValueInFlag | kSecDbInFlag)) != 0) { + if ((desc->flags & kSecDbSHA1ValueInFlag) && (desc->flags & kSecDbInFlag)) { value = CFRetainSafe(CFDictionaryGetValue(item->attributes, hash_name)); } @@ -554,6 +585,20 @@ static CFStringRef SecDbItemCopyFormatDescription(CFTypeRef cf, CFDictionaryRef } } break; + case kSecDbUUIDAttr: + if ((value = SecDbItemGetValue(item, attr, NULL))) { + if (CFEqual(attr->name, kSecAttrMultiUser)) { + if (isData(value)) { + CFStringAppend(attrs, CFSTR(",")); + if (CFDataGetLength(value)) { + CFStringAppendHexData(attrs, value); + } else { + CFStringAppend(attrs, attr->name); + } + } + } + } + break; case kSecDbCreationDateAttr: // We don't care about this and every object has one. break; @@ -753,6 +798,10 @@ bool SecDbItemSetValue(SecDbItemRef item, const SecDbAttr *desc, CFTypeRef value break; case kSecDbUTombAttr: attr = CFRetainSafe(asBoolean(value, NULL)); + break; + case kSecDbUUIDAttr: + attr = copyUUID(value); + break; } if (attr) { @@ -841,7 +890,8 @@ SecDbColumnCopyValueWithAttr(CFAllocatorRef allocator, sqlite3_stmt *stmt, const value = SecDbColumnCopyDouble(allocator, stmt, col, error); break; case SQLITE_TEXT: - value = SecDbColumnCopyString(allocator, stmt, col, error); + value = SecDbColumnCopyString(allocator, stmt, col, error, + attr->flags); break; case SQLITE_BLOB: value = SecDbColumnCopyData(allocator, stmt, col, error); @@ -853,9 +903,11 @@ SecDbColumnCopyValueWithAttr(CFAllocatorRef allocator, sqlite3_stmt *stmt, const break; case kSecDbAccessAttr: case kSecDbStringAttr: - value = SecDbColumnCopyString(allocator, stmt, col, error); + value = SecDbColumnCopyString(allocator, stmt, col, error, + attr->flags); break; case kSecDbDataAttr: + case kSecDbUUIDAttr: case kSecDbSHA1Attr: case kSecDbPrimaryKeyAttr: case kSecDbEncryptedDataAttr: @@ -1057,7 +1109,7 @@ SecDbAppendWhereOrAndIn(CFMutableStringRef sql, CFStringRef col, bool *needWhere return SecDbAppendWhereOrAndEquals(sql, col, needWhere); SecDbAppendWhereOrAnd(sql, needWhere); CFStringAppend(sql, col); - CFStringAppend(sql, CFSTR(" in (")); + CFStringAppend(sql, CFSTR(" IN (")); SecDbAppendCountArgsAndCloseParen(sql, count); } @@ -1067,7 +1119,7 @@ SecDbAppendWhereOrAndNotIn(CFMutableStringRef sql, CFStringRef col, bool *needWh return SecDbAppendWhereOrAndNotEquals(sql, col, needWhere); SecDbAppendWhereOrAnd(sql, needWhere); CFStringAppend(sql, col); - CFStringAppend(sql, CFSTR(" not in (")); + CFStringAppend(sql, CFSTR(" NOT IN (")); SecDbAppendCountArgsAndCloseParen(sql, count); } @@ -1138,7 +1190,7 @@ bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error return ok; } -static bool SecDbItemClearRowId(SecDbItemRef item, CFErrorRef *error) { +bool SecDbItemClearRowId(SecDbItemRef item, CFErrorRef *error) { bool ok = true; const SecDbAttr *attr = SecDbClassAttrWithKind(item->class, kSecDbRowIdAttr, error); if (attr) { @@ -1196,7 +1248,7 @@ static SecDbQueryRef SecDbQueryCreateWithItemPrimaryKey(SecDbItemRef item, CFErr if (!dict) return NULL; - SecDbQueryRef query = query_create(item->class, NULL, error); + SecDbQueryRef query = query_create(item->class, NULL, NULL, error); if (query) { CFReleaseSafe(query->q_item); query->q_item = dict; diff --git a/OSX/sec/securityd/SecDbItem.h b/OSX/sec/securityd/SecDbItem.h index f7e46130..f0df92ac 100644 --- a/OSX/sec/securityd/SecDbItem.h +++ b/OSX/sec/securityd/SecDbItem.h @@ -59,7 +59,8 @@ typedef enum { kSecDbTombAttr, kSecDbUTombAttr, kSecDbAccessAttr, - kSecDbAccessControlAttr + kSecDbAccessControlAttr, + kSecDbUUIDAttr, } SecDbAttrKind; enum { @@ -77,6 +78,8 @@ enum { kSecDbDefaultEmptyFlag = (1 << 11), // default attr value is "" kSecDbNotNullFlag = (1 << 12), // attr value can't be null kSecDbInAuthenticatedDataFlag = (1 << 13), // attr is in authenticated data + kSecDbSyncPrimaryKeyV0 = (1 << 14), + kSecDbSyncPrimaryKeyV2 = (1 << 15), }; #define SecVersionDbFlag(v) ((v & 0xFF) << 8) @@ -174,6 +177,7 @@ bool SecDbItemSetValueWithName(SecDbItemRef item, CFStringRef name, CFTypeRef va sqlite3_int64 SecDbItemGetRowId(SecDbItemRef item, CFErrorRef *error); bool SecDbItemSetRowId(SecDbItemRef item, sqlite3_int64 rowid, CFErrorRef *error); +bool SecDbItemClearRowId(SecDbItemRef item, CFErrorRef *error); bool SecDbItemIsSyncableOrCorrupted(SecDbItemRef item); bool SecDbItemIsSyncable(SecDbItemRef item); @@ -238,6 +242,7 @@ CFTypeRef copyBlob(CFTypeRef obj); CFDataRef copySHA1(CFTypeRef obj); CFTypeRef copyNumber(CFTypeRef obj); CFDateRef copyDate(CFTypeRef obj); +CFTypeRef copyUUID(CFTypeRef obj); // MARK: cFErrorPropagate which handles errSecAuthNeeded static inline diff --git a/OSX/sec/securityd/SecDbQuery.c b/OSX/sec/securityd/SecDbQuery.c index 88959c4a..d3304a6e 100644 --- a/OSX/sec/securityd/SecDbQuery.c +++ b/OSX/sec/securityd/SecDbQuery.c @@ -1,3 +1,4 @@ + /* * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. * @@ -59,6 +60,113 @@ #define QUERY_KEY_LIMIT QUERY_KEY_LIMIT_BASE #endif + +static const uint8_t systemKeychainUUID[] = "\xF6\x23\xAE\x5C\xCC\x81\x4C\xAC\x8A\xD4\xF0\x01\x3F\x31\x35\x11"; + +CFDataRef +SecMUSRCopySystemKeychainUUID(void) +{ + return CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)systemKeychainUUID, 16, kCFAllocatorNull); +} + +CFDataRef +SecMUSRGetSystemKeychainUUID(void) +{ + static dispatch_once_t onceToken; + static CFDataRef systemKeychainData = NULL; + dispatch_once(&onceToken, ^{ + systemKeychainData = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)systemKeychainUUID, 16, kCFAllocatorNull); + }); + return systemKeychainData; +} + +CFDataRef +SecMUSRGetSingleUserKeychainUUID(void) +{ + static dispatch_once_t onceToken; + static CFDataRef singleUser = NULL; + dispatch_once(&onceToken, ^{ + singleUser = CFDataCreateWithBytesNoCopy(NULL, NULL, 0, kCFAllocatorNull); + }); + return singleUser; +} + +bool +SecMUSRIsSingleUserView(CFDataRef musr) +{ + return CFEqual(musr, SecMUSRGetSingleUserKeychainUUID()); +} + +static const uint8_t allKeychainViewsUUID[16] = "\xC8\x60\x07\xEC\x89\x62\x4D\xAF\x85\x65\x1F\xE6\x0F\x50\x5D\xB7"; + +CFDataRef +SecMUSRGetAllViews(void) +{ + static dispatch_once_t onceToken; + static CFDataRef allKeychainViewsData = NULL; + dispatch_once(&onceToken, ^{ + allKeychainViewsData = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)allKeychainViewsUUID, 16, kCFAllocatorNull); + }); + return allKeychainViewsData; +} + +bool +SecMUSRIsViewAllViews(CFDataRef musr) +{ + return CFEqual(musr, SecMUSRGetAllViews()); +} + +#if TARGET_OS_IPHONE + +CFDataRef +SecMUSRCreateActiveUserUUID(uid_t uid) +{ + uint8_t uuid[16] = "\xA7\x5A\x3A\x35\xA5\x57\x4B\x10\xBE\x2E\x83\x94\x7E\x4A\x34\x72"; + uint32_t num = htonl(uid); + memcpy(&uuid[12], &num, sizeof(num)); + return CFDataCreate(NULL, uuid, sizeof(uuid)); +} + +CFDataRef +SecMUSRCreateSyncBubbleUserUUID(uid_t uid) +{ + uint8_t uuid[16] = "\x82\x1A\xAB\x9F\xA3\xC8\x4E\x11\xAA\x90\x4C\xE8\x9E\xA6\xD7\xEC"; + uint32_t num = htonl(uid); + memcpy(&uuid[12], &num, sizeof(num)); + return CFDataCreate(NULL, uuid, sizeof(uuid)); +} + +static const uint8_t bothUserAndSystemUUID[12] = "\x36\xC4\xBE\x2E\x99\x0A\x46\x9A\xAC\x89\x09\xA4"; + + +CFDataRef +SecMUSRCreateBothUserAndSystemUUID(uid_t uid) +{ + uint8_t uuid[16]; + memcpy(uuid, bothUserAndSystemUUID, 12); + uint32_t num = htonl(uid); + memcpy(&uuid[12], &num, sizeof(num)); + return CFDataCreate(NULL, uuid, sizeof(uuid)); +} + +bool +SecMUSRGetBothUserAndSystemUUID(CFDataRef musr, uid_t *uid) +{ + if (CFDataGetLength(musr) != 16) + return false; + const uint8_t *uuid = CFDataGetBytePtr(musr); + if (memcmp(uuid, bothUserAndSystemUUID, 12) != 0) + return false; + if (uid) { + uint32_t num; + memcpy(&num, &uuid[12], sizeof(num)); + *uid = htonl(num); + } + return true; +} + +#endif + /* Inline accessors to attr and match values in a query. */ CFIndex query_attr_count(const Query *q) { @@ -171,6 +279,9 @@ void query_add_attribute_with_desc(const SecDbAttr *desc, const void *value, Que case kSecDbEncryptedDataAttr: case kSecDbUTombAttr: break; + case kSecDbUUIDAttr: + attr = copyUUID(value); + break; } if (!attr) { @@ -473,12 +584,22 @@ static void query_add_use(const void *key, const void *value, Query *q) SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not CFString"), value, key); return; } -#if defined(MULTIPLE_KEYCHAINS) - } else if (CFEqual(key, kSecUseKeychain)) { - q->q_use_keychain = value; - } else if (CFEqual(key, kSecUseKeychainList)) { - q->q_use_keychain_list = value; -#endif /* !defined(MULTIPLE_KEYCHAINS) */ +#if TARGET_OS_IPHONE + } else if (CFEqual(key, kSecUseSystemKeychain)) { +#if TARGET_OS_EMBEDDED + q->q_keybag = KEYBAG_DEVICE; +#endif + q->q_system_keychain = true; + } else if (CFEqual(key, kSecUseSyncBubbleKeychain)) { + if (isNumber(value) && CFNumberGetValue(value, kCFNumberSInt32Type, &q->q_sync_bubble) && q->q_sync_bubble > 0) { +#if TARGET_OS_EMBEDDED + q->q_keybag = KEYBAG_DEVICE; +#endif + } else { + SecError(errSecItemInvalidValue, &q->q_error, CFSTR("add_use: value %@ for key %@ is not valid uid"), value, key); + return; + } +#endif } else { SecError(errSecItemInvalidKey, &q->q_error, CFSTR("add_use: unknown key %@"), key); return; @@ -543,6 +664,11 @@ static void query_update_applier(const void *key, const void *value, return; } + if (CFEqual(key, CFSTR("musr"))) { + secnotice("item", "update_applier: refusing to update musr"); + return; + } + if (CFEqual(key, kSecValueData)) { query_set_data(value, q); } else { @@ -660,6 +786,7 @@ bool query_destroy(Query *q, CFErrorRef *error) { CFReleaseSafe(query_attr_at(q, ix).value); } CFReleaseSafe(q->q_item); + CFReleaseSafe(q->q_musrView); CFReleaseSafe(q->q_primary_key_digest); CFReleaseSafe(q->q_match_issuer); CFReleaseSafe(q->q_access_control); @@ -671,14 +798,16 @@ bool query_destroy(Query *q, CFErrorRef *error) { } bool query_notify_and_destroy(Query *q, bool ok, CFErrorRef *error) { - if (ok && !q->q_error && q->q_sync_changed) { + if (ok && !q->q_error && (q->q_sync_changed || (q->q_changed && !SecMUSRIsSingleUserView(q->q_musrView)))) { SecKeychainChanged(true); } return query_destroy(q, error) && ok; } /* Allocate and initialize a Query object for query. */ -Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, +Query *query_create(const SecDbClass *qclass, + CFDataRef musr, + CFDictionaryRef query, CFErrorRef *error) { if (!qclass) { @@ -687,6 +816,9 @@ Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, return NULL; } + if (musr == NULL) + musr = SecMUSRGetSingleUserKeychainUUID(); + /* Number of pairs we need is the number of attributes in this class plus the number of keys in the dictionary, minus one for each key in the dictionary that is a regular attribute. */ @@ -720,6 +852,7 @@ Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, return NULL; } + q->q_musrView = (CFDataRef)CFRetain(musr); q->q_keybag = KEYBAG_DEVICE; q->q_class = qclass; q->q_match_begin = q->q_match_end = key_count; @@ -748,9 +881,9 @@ bool query_update_parse(Query *q, CFDictionaryRef update, return query_parse_with_applier(q, update, query_update_applier, error); } -Query *query_create_with_limit(CFDictionaryRef query, CFIndex limit, CFErrorRef *error) { +Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error) { Query *q; - q = query_create(query_get_class(query, error), query, error); + q = query_create(query_get_class(query, error), musr, query, error); if (q) { q->q_limit = limit; if (!query_parse(q, query, error)) { diff --git a/OSX/sec/securityd/SecDbQuery.h b/OSX/sec/securityd/SecDbQuery.h index 9bad114f..2a7f8474 100644 --- a/OSX/sec/securityd/SecDbQuery.h +++ b/OSX/sec/securityd/SecDbQuery.h @@ -87,10 +87,6 @@ typedef struct Query CFArrayRef q_use_item_list; CFBooleanRef q_use_tomb; -#if defined(MULTIPLE_KEYCHAINS) - CFArrayRef q_use_keychain; - CFArrayRef q_use_keychain_list; -#endif /* !defined(MULTIPLE_KEYCHAINS) */ /* Value of kSecMatchLimit key if present. */ CFIndex q_limit; @@ -108,7 +104,10 @@ typedef struct Query /* Keybag handle to use for this item. */ keybag_handle_t q_keybag; - + + /* musr view to use when modifying the database */ + CFDataRef q_musrView; + /* ACL and credHandle passed to the query. q_cred_handle contain LA context object. */ SecAccessControlRef q_access_control; CFTypeRef q_use_cred_handle; @@ -124,14 +123,17 @@ typedef struct Query /* Caller acces groups for AKS */ CFArrayRef q_caller_access_groups; + bool q_system_keychain; + int32_t q_sync_bubble; + Pair q_pairs[]; } Query; -Query *query_create(const SecDbClass *qclass, CFDictionaryRef query, CFErrorRef *error); +Query *query_create(const SecDbClass *qclass, CFDataRef musr, CFDictionaryRef query, CFErrorRef *error); bool query_destroy(Query *q, CFErrorRef *error); bool query_error(Query *q, CFErrorRef *error); -Query *query_create_with_limit(CFDictionaryRef query, CFIndex limit, CFErrorRef *error); +Query *query_create_with_limit(CFDictionaryRef query, CFDataRef musr, CFIndex limit, CFErrorRef *error); void query_add_attribute(const void *key, const void *value, Query *q); void query_add_or_attribute(const void *key, const void *value, Query *q); void query_add_not_attribute(const void *key, const void *value, Query *q); @@ -146,6 +148,39 @@ bool query_update_parse(Query *q, CFDictionaryRef update, CFErrorRef *error); const SecDbClass *kc_class_with_name(CFStringRef name); void query_set_caller_access_groups(Query *q, CFArrayRef caller_access_groups); +CFDataRef +SecMUSRCopySystemKeychainUUID(void); + +CFDataRef +SecMUSRGetSystemKeychainUUID(void); + +CFDataRef +SecMUSRGetSingleUserKeychainUUID(void); + +bool +SecMUSRIsSingleUserView(CFDataRef uuid); + +CFDataRef +SecMUSRGetAllViews(void); + +bool +SecMUSRIsViewAllViews(CFDataRef musr); + +#if TARGET_OS_IPHONE +CFDataRef +SecMUSRCreateActiveUserUUID(uid_t uid); + +CFDataRef +SecMUSRCreateSyncBubbleUserUUID(uid_t uid); + +CFDataRef +SecMUSRCreateBothUserAndSystemUUID(uid_t uid); + +bool +SecMUSRGetBothUserAndSystemUUID(CFDataRef musr, uid_t *uid); + +#endif + __END_DECLS diff --git a/OSX/sec/securityd/SecItemDataSource.c b/OSX/sec/securityd/SecItemDataSource.c index 9eb50a70..0bdc8d8a 100644 --- a/OSX/sec/securityd/SecItemDataSource.c +++ b/OSX/sec/securityd/SecItemDataSource.c @@ -127,7 +127,7 @@ static SOSManifestRef SecItemDataSourceCopyManifestWithQueries(SecItemDataSource } static Query *SecItemDataSourceAppendQuery(CFMutableArrayRef queries, const SecDbClass *qclass, bool noTombstones, CFErrorRef *error) { - Query *q = query_create(qclass, NULL, error); + Query *q = query_create(qclass, NULL, NULL, error); if (q) { q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; q->q_limit = kSecMatchUnlimited; @@ -156,7 +156,7 @@ static Query *SecItemDataSourceAppendQueryWithClassAndViewHint(CFMutableArrayRef // default value of those attributes in the query, since old items // will all have that as their values for these new attributes. SecDbForEachAttr(qclass, attr) { - if ((attr->flags & (kSecDbPrimaryKeyFlag | kSecDbDefaultEmptyFlag | kSecDbDefault0Flag | kSecDbNotNullFlag)) == kSecDbPrimaryKeyFlag) { + if (attr == &v7tkid || attr == &v7vwht) { // attr is a primary key attribute added in schema version 7 or later if (!allowTkid || attr != &v7tkid) { if (attr == &v7vwht && viewHint) { @@ -362,7 +362,7 @@ static bool dsForEachObject(SOSDataSourceRef data_source, SOSManifestRef manifes // Setup for (size_t class_ix = 0; class_ix < array_size(dsSyncedClasses); ++class_ix) { result = (result - && (queries[class_ix] = query_create(dsSyncedClasses[class_ix], NULL, error)) + && (queries[class_ix] = query_create(dsSyncedClasses[class_ix], NULL, NULL, error)) && (sqls[class_ix] = SecDbItemCopySelectSQL(queries[class_ix], return_attr, use_attr_in_where, NULL)) && (stmts[class_ix] = SecDbCopyStmt(dbconn, sqls[class_ix], NULL, error))); } @@ -419,13 +419,6 @@ static CFDataRef copyObjectDigest(SOSObjectRef object, CFErrorRef *error) { return digest; } -static CFDataRef objectCopyPrimaryKey(SOSObjectRef object, CFErrorRef *error) { - SecDbItemRef item = (SecDbItemRef) object; - CFDataRef pk = SecDbItemGetPrimaryKey(item, error); - CFRetainSafe(pk); - return pk; -} - static CFDictionaryRef objectCopyPropertyList(SOSObjectRef object, CFErrorRef *error) { SecDbItemRef item = (SecDbItemRef) object; CFMutableDictionaryRef cryptoDataDict = SecDbItemCopyPListWithMask(item, kSecDbInCryptoDataFlag, error); @@ -472,14 +465,14 @@ static SOSMergeResult dsMergeObject(SOSTransactionRef txn, SOSObjectRef peersObj if (!mergedItem) return; if (CFEqual(mergedItem, myItem)) { // Conflict resolver choose my (local) item - secnotice("ds", "Conflict resolver choose my (local) item: %@", myItem); + secnotice("ds", "Conflict resolver chose my (local) item: %@", myItem); mr = kSOSMergeLocalObject; } else { CFRetainAssign(replacedItem, myItem); *replace = CFRetainSafe(mergedItem); if (CFEqual(mergedItem, peersItem)) { - // Conflict resolver choose peers item - secnotice("ds", "Conflict resolver choose peers item: %@", peersItem); + // Conflict resolver chose peer's item + secnotice("ds", "Conflict resolver chose peers item: %@", peersItem); mr = kSOSMergePeersObject; } else { // Conflict resolver created a new item; return it to our caller @@ -549,7 +542,7 @@ static CFDataRef dsCopyStateWithKey(SOSDataSourceRef data_source, CFStringRef ke NULL); CFReleaseSafe(dataSourceID); __block CFDataRef data = NULL; - SecDbQueryRef query = query_create(&genp_class, dict, error); + SecDbQueryRef query = query_create(&genp_class, NULL, dict, error); if (query) { if (query->q_item) CFReleaseSafe(query->q_item); query->q_item = dict; @@ -589,7 +582,7 @@ static CFDataRef dsCopyItemDataWithKeys(SOSDataSourceRef data_source, CFDictiona SecItemDataSourceRef ds = (SecItemDataSourceRef)data_source; CFMutableDictionaryRef dict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, keys); __block CFDataRef data = NULL; - SecDbQueryRef query = query_create(&genp_class, dict, error); + SecDbQueryRef query = query_create(&genp_class, NULL, dict, error); if (query) { if (query->q_item) CFReleaseSafe(query->q_item); query->q_item = dict; @@ -665,7 +658,6 @@ SOSDataSourceRef SecItemDataSourceCreate(SecDbRef db, CFStringRef name, CFErrorR // Object field accessors ds->ds.objectCopyDigest = copyObjectDigest; - ds->ds.objectCopyPrimaryKey = objectCopyPrimaryKey; // Object encode and decode. ds->ds.objectCreateWithPropertyList = objectCreateWithPropertyList; diff --git a/OSX/sec/securityd/SecItemDb.c b/OSX/sec/securityd/SecItemDb.c index b116e3aa..9a4f8667 100644 --- a/OSX/sec/securityd/SecItemDb.c +++ b/OSX/sec/securityd/SecItemDb.c @@ -62,6 +62,9 @@ const SecDbAttr *SecDbAttrWithKey(const SecDbClass *c, if (CFEqual(a->name, key)) return a; } + if (CFEqual(kSecAttrNoLegacy, key)) { + return NULL; /* results in no ops for this attribute */ + } } SecError(errSecNoSuchAttr, error, CFSTR("attribute %@ not found in class %@"), key, c->name); @@ -80,6 +83,7 @@ static CFStringRef SecDbGetKindSQL(SecDbAttrKind kind) { switch (kind) { case kSecDbBlobAttr: case kSecDbDataAttr: + case kSecDbUUIDAttr: case kSecDbSHA1Attr: case kSecDbPrimaryKeyAttr: case kSecDbEncryptedDataAttr: @@ -255,6 +259,8 @@ s3dl_query_add(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, CFErrorRef * ok = SecDbItemSetValueWithName(item, CFSTR("v_Data"), q->q_data, error); if (q->q_row_id) ok = SecDbItemSetRowId(item, q->q_row_id, error); + if (q->q_musrView) + ok = SecDbItemSetValueWithName(item, CFSTR("musr"), q->q_musrView, error); SecDbItemSetCredHandle(item, q->q_use_cred_handle); if (ok) @@ -489,11 +495,53 @@ SecDbAppendWhereAccessGroups(CFMutableStringRef sql, CFStringAppend(sql, CFSTR(")")); } +static bool +isQueryOverAllMUSRViews(CFTypeRef musrView) +{ + return SecMUSRIsViewAllViews(musrView); +} + +static bool +isQueryOverSingleUserView(CFTypeRef musrView) +{ + return isNull(musrView); +} + +#if TARGET_OS_IPHONE +static bool +isQueryOverBothUserAndSystem(CFTypeRef musrView, uid_t *uid) +{ + return SecMUSRGetBothUserAndSystemUUID(musrView, uid); +} +#endif + +static void +SecDbAppendWhereMusr(CFMutableStringRef sql, + const Query *q, + bool *needWhere) +{ + SecDbAppendWhereOrAnd(sql, needWhere); + +#if TARGET_OS_IPHONE + if (isQueryOverBothUserAndSystem(q->q_musrView, NULL)) { + CFStringAppend(sql, CFSTR("(musr = ? OR musr = ?)")); + } else +#endif + if (isQueryOverAllMUSRViews(q->q_musrView)) { + /* query over all items, regardless of view */ + } else if (isQueryOverSingleUserView(q->q_musrView)) { + CFStringAppend(sql, CFSTR("musr = ?")); + } else { + CFStringAppend(sql, CFSTR("musr = ?")); + } +} + static void SecDbAppendWhereClause(CFMutableStringRef sql, const Query *q, CFArrayRef accessGroups) { bool needWhere = true; SecDbAppendWhereROWID(sql, CFSTR("ROWID"), q->q_row_id, &needWhere); SecDbAppendWhereAttrs(sql, q, &needWhere); + SecDbAppendWhereMusr(sql, q, &needWhere); SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); } @@ -520,6 +568,7 @@ static CFStringRef s3dl_select_sql(Query *q, CFArrayRef accessGroups) { CFStringAppend(sql, CFSTR(")")); bool needWhere = true; SecDbAppendWhereAttrs(sql, q, &needWhere); + SecDbAppendWhereMusr(sql, q, &needWhere); SecDbAppendWhereAccessGroups(sql, CFSTR("agrp"), accessGroups, &needWhere); } else { CFStringAppend(sql, CFSTR("SELECT rowid, data FROM ")); @@ -531,6 +580,37 @@ static CFStringRef s3dl_select_sql(Query *q, CFArrayRef accessGroups) { return sql; } +static bool sqlBindMusr(sqlite3_stmt *stmt, const Query *q, int *pParam, CFErrorRef *error) { + int param = *pParam; + bool result = true; +#if TARGET_OS_IPHONE + uid_t uid; + + if (isQueryOverBothUserAndSystem(q->q_musrView, &uid)) { + /* network extensions are special and get to query both user and system views */ + CFDataRef systemUUID = SecMUSRGetSystemKeychainUUID(); + result = SecDbBindObject(stmt, param++, systemUUID, error); + if (result) { + CFDataRef activeUser = SecMUSRCreateActiveUserUUID(uid); + result = SecDbBindObject(stmt, param++, activeUser, error); + CFReleaseNull(activeUser); + } + } else +#endif + if (isQueryOverAllMUSRViews(q->q_musrView)) { + /* query over all items, regardless of view */ + } else if (isQueryOverSingleUserView(q->q_musrView)) { + CFDataRef singleUUID = SecMUSRGetSingleUserKeychainUUID(); + result = SecDbBindObject(stmt, param++, singleUUID, error); + } else { + result = SecDbBindObject(stmt, param++, q->q_musrView, error); + } + + *pParam = param; + return result; +} + + static bool sqlBindAccessGroups(sqlite3_stmt *stmt, CFArrayRef accessGroups, int *pParam, CFErrorRef *error) { bool result = true; @@ -558,6 +638,10 @@ static bool sqlBindWhereClause(sqlite3_stmt *stmt, const Query *q, break; } + if (result) { + result = sqlBindMusr(stmt, q, ¶m, error); + } + /* Bind the access group to the sql. */ if (result) { result = sqlBindAccessGroups(stmt, accessGroups, ¶m, error); @@ -752,7 +836,7 @@ void query_pre_add(Query *q, bool force_date) { value = CFNumberCreate(0, kCFNumberSInt32Type, &vzero); } } else if (desc->flags & kSecDbDefaultEmptyFlag) { - if (desc->kind == kSecDbDataAttr) + if (desc->kind == kSecDbDataAttr || desc->kind == kSecDbUUIDAttr) value = CFDataCreate(kCFAllocatorDefault, NULL, 0); else { value = CFSTR(""); @@ -797,7 +881,7 @@ s3dl_query_update(SecDbConnectionRef dbt, Query *q, return SecError(errSecItemIllegalQuery, error, CFSTR("attributes to update illegal; both row_id and other attributes can't be updated at the same time")); __block bool result = true; - Query *u = query_create(q->q_class, attributesToUpdate, error); + Query *u = query_create(q->q_class, NULL, attributesToUpdate, error); if (u == NULL) return false; require_action_quiet(query_update_parse(u, attributesToUpdate, error), errOut, result = false); query_pre_update(u); @@ -903,10 +987,21 @@ s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFE return ok && !needAuth; } +static bool +matchAnyString(CFStringRef needle, CFStringRef *haystack) +{ + while (*haystack) { + if (CFEqual(needle, *haystack)) + return true; + haystack++; + } + return false; +} + /* Return true iff the item in question should not be backed up, nor restored, but when restoring a backup the original version of the item should be added back to the keychain again after the restore completes. */ -static bool SecItemIsSystemBound(CFDictionaryRef item, const SecDbClass *class) { +static bool SecItemIsSystemBound(CFDictionaryRef item, const SecDbClass *cls, bool multiUser) { CFStringRef agrp = CFDictionaryGetValue(item, kSecAttrAccessGroup); if (!isString(agrp)) return false; @@ -921,17 +1016,59 @@ static bool SecItemIsSystemBound(CFDictionaryRef item, const SecDbClass *class) return true; } - if (CFEqual(agrp, CFSTR("apple")) && class == &genp_class) { + if (CFEqual(agrp, CFSTR("apple")) && cls == &genp_class) { CFStringRef service = CFDictionaryGetValue(item, kSecAttrService); CFStringRef account = CFDictionaryGetValue(item, kSecAttrAccount); - if (isString(service) && isString(account) && - CFEqual(service, CFSTR("com.apple.managedconfiguration")) && - (CFEqual(account, CFSTR("Public")) || - CFEqual(account, CFSTR("Private")))) { + + if (isString(service) && isString(account)) { + static CFStringRef mcAccounts[] = { + CFSTR("Public"), + CFSTR("Private"), + NULL, + }; + + if (CFEqual(service, CFSTR("com.apple.managedconfiguration")) + && matchAnyString(account, mcAccounts)) + { secdebug("backup", "found sys_bound item: %@", item); return true; } + } + } + + if (multiUser && CFEqual(agrp, CFSTR("com.apple.apsd"))) { + static CFStringRef pushServices[] = { + CFSTR("push.apple.com"), + CFSTR("push.apple.com,PerAppToken.v0"), + NULL + }; + CFStringRef service = CFDictionaryGetValue(item, kSecAttrService); + + if (isString(service) && matchAnyString(service, pushServices)) { + secdebug("backup", "found sys_bound item: %@", item); + return true; + } + } + + if (multiUser && CFEqual(agrp, CFSTR("apple"))) { + static CFStringRef acountServices[] = { + CFSTR("com.apple.account.AppleAccount.token"), + CFSTR("com.apple.account.AppleAccount.password"), + CFSTR("com.apple.account.AppleAccount.rpassword"), + CFSTR("com.apple.account.idms.token"), + CFSTR("com.apple.account.idms.continuation-key"), + CFSTR("com.apple.account.CloudKit.token"), + NULL + }; + CFStringRef service = CFDictionaryGetValue(item, kSecAttrService); + + if (isString(service) && matchAnyString(service, acountServices)) { + secdebug("backup", "found sys_bound item: %@", item); + return true; + } } + + secdebug("backup", "found non sys_bound item: %@", item); return false; } @@ -942,6 +1079,9 @@ static bool SecItemIsSystemBound(CFDictionaryRef item, const SecDbClass *class) will never overwrite an existing activation record. */ static bool SecServerDeleteAll(SecDbConnectionRef dbt, CFErrorRef *error) { return kc_transaction(dbt, error, ^{ + + secwarning("SecServerDeleteAll"); + bool ok = (SecDbExec(dbt, CFSTR("DELETE from genp;"), error) && SecDbExec(dbt, CFSTR("DELETE from inet;"), error) && SecDbExec(dbt, CFSTR("DELETE from cert;"), error) && @@ -950,10 +1090,55 @@ static bool SecServerDeleteAll(SecDbConnectionRef dbt, CFErrorRef *error) { }); } +#if TARGET_OS_IPHONE + +static bool DeleteAllFromTableForMUSRView(SecDbConnectionRef dbt, + CFStringRef sql, + CFDataRef musr, + CFErrorRef *error) +{ + sqlite3_stmt *stmt = NULL; + bool ok = false; + + stmt = SecDbCopyStmt(dbt, sql, NULL, error); + require(stmt, fail); + + ok = SecDbBindObject(stmt, 1, musr, error); + require(ok, fail); + + ok = SecDbStep(dbt, stmt, error, ^(bool *stop) { }); + require(ok, fail); + +fail: + if (stmt) { + ok = SecDbFinalize(stmt, error); + } + + return ok; +} + +bool SecServerDeleteAllForUser(SecDbConnectionRef dbt, CFDataRef musrView, CFErrorRef *error) { + return kc_transaction(dbt, error, ^{ + bool ok; + + secwarning("SecServerDeleteAllForUser for user: %@", musrView); + + ok = (DeleteAllFromTableForMUSRView(dbt, CFSTR("DELETE FROM genp WHERE musr = ?"), musrView, error) && + DeleteAllFromTableForMUSRView(dbt, CFSTR("DELETE FROM inet WHERE musr = ?"), musrView, error) && + DeleteAllFromTableForMUSRView(dbt, CFSTR("DELETE FROM cert WHERE musr = ?"), musrView, error) && + DeleteAllFromTableForMUSRView(dbt, CFSTR("DELETE FROM keys WHERE musr = ?"), musrView, error)); + + return ok; + }); +} +#endif + + struct s3dl_export_row_ctx { struct s3dl_query_ctx qc; keybag_handle_t dest_keybag; enum SecItemFilter filter; + bool multiUser; }; static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { @@ -976,7 +1161,7 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { /* Only export sysbound items if do_sys_bound is true, only export non sysbound items otherwise. */ bool do_sys_bound = c->filter == kSecSysBoundItemFilter; if (c->filter == kSecNoItemFilter || - SecItemIsSystemBound(item, q->q_class) == do_sys_bound) { + SecItemIsSystemBound(item, q->q_class, c->multiUser) == do_sys_bound) { /* Re-encode the item. */ secdebug("item", "export rowid %llu item: %@", rowid, item); /* The code below could be moved into handle_row. */ @@ -1036,9 +1221,13 @@ static void s3dl_export_row(sqlite3_stmt *stmt, void *context) { CFReleaseSafe(access_control); } -CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - enum SecItemFilter filter, CFErrorRef *error) { +CFDictionaryRef +SecServerCopyKeychainPlist(SecDbConnectionRef dbt, + SecurityClient *client, + keybag_handle_t src_keybag, + keybag_handle_t dest_keybag, + enum SecItemFilter filter, + CFErrorRef *error) { CFMutableDictionaryRef keychain; keychain = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -1048,12 +1237,24 @@ CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnection goto errOut; } unsigned class_ix; + bool inMultiUser = false; Query q = { .q_keybag = src_keybag }; q.q_return_type = kSecReturnDataMask | kSecReturnAttributesMask | \ kSecReturnPersistentRefMask; q.q_limit = kSecMatchUnlimited; q.q_skip_acl_items = true; +#if TARGET_OS_IPHONE + if (client && client->inMultiUser) { + q.q_musrView = SecMUSRCreateActiveUserUUID(client->uid); + inMultiUser = true; + } else +#endif + { + q.q_musrView = SecMUSRGetSingleUserKeychainUUID(); + CFRetain(q.q_musrView); + } + /* Get rid of this duplicate. */ const SecDbClass *SecDbClasses[] = { &genp_class, @@ -1068,6 +1269,7 @@ CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnection struct s3dl_export_row_ctx ctx = { .qc = { .q = &q, .dbt = dbt }, .dest_keybag = dest_keybag, .filter = filter, + .multiUser = inMultiUser, }; secnotice("item", "exporting class '%@'", q.q_class->name); @@ -1098,6 +1300,8 @@ CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnection } errOut: + CFReleaseNull(q.q_musrView); + return keychain; } @@ -1106,6 +1310,7 @@ struct SecServerImportClassState { CFErrorRef error; keybag_handle_t src_keybag; keybag_handle_t dest_keybag; + SecurityClient *client; enum SecItemFilter filter; }; @@ -1114,11 +1319,19 @@ struct SecServerImportItemState { struct SecServerImportClassState *s; }; -static void SecServerImportItem(const void *value, void *context) { - struct SecServerImportItemState *state = - (struct SecServerImportItemState *)context; +static void +SecServerImportItem(const void *value, void *context) +{ + struct SecServerImportItemState *state = (struct SecServerImportItemState *)context; + bool inMultiUser = false; +#if TARGET_OS_IPHONE + if (state->s->client->inMultiUser) + inMultiUser = true; +#endif + if (state->s->error) return; + if (!isDictionary(value)) { SecError(errSecParam, &state->s->error, CFSTR("value %@ is not a dictionary"), value); return; @@ -1132,7 +1345,7 @@ static void SecServerImportItem(const void *value, void *context) { will never have any in this case, we use the kSecSysBoundItemFilter to indicate that we don't preserve rowid's during import instead. */ if (state->s->filter == kSecBackupableItemFilter && - SecItemIsSystemBound(dict, state->class)) + SecItemIsSystemBound(dict, state->class, inMultiUser)) return; SecDbItemRef item; @@ -1148,13 +1361,69 @@ static void SecServerImportItem(const void *value, void *context) { item = SecDbItemCreateWithBackupDictionary(kCFAllocatorDefault, state->class, dict, state->s->src_keybag, state->s->dest_keybag, &state->s->error); } + /* + * + */ + if (item) { + CFDataRef musr = NULL; + CFDataRef musrBackup = CFDictionaryGetValue(dict, kSecAttrMultiUser); + CFDataRef systemKeychainUUID = SecMUSRGetSystemKeychainUUID(); + bool systemKeychain = CFEqualSafe(musrBackup, systemKeychainUUID); + +#if TARGET_OS_IPHONE + if (state->s->client && state->s->client->inMultiUser) { + if (systemKeychain) { + secwarning("system keychain not allowed in multi user mode for item: %@", item); + } else { + musr = SecMUSRCreateActiveUserUUID(state->s->client->uid); + } + } else +#endif + { + if (systemKeychain) { + musr = SecMUSRCopySystemKeychainUUID(); + } else { + musr = SecMUSRGetSingleUserKeychainUUID(); + CFRetainSafe(musr); + } + } + if (musr == NULL) { + CFReleaseNull(item); + } else { + SecDbItemSetValueWithName(item, CFSTR("musr"), musr, &state->s->error); + CFRelease(musr); + } + } + + /* + * + */ + + if (item) { + bool insertStatus; + if(state->s->filter != kSecSysBoundItemFilter) { SecDbItemExtractRowIdFromBackupDictionary(item, dict, &state->s->error); } SecDbItemInferSyncable(item, &state->s->error); - SecDbItemInsert(item, state->s->dbt, &state->s->error); - } + insertStatus = SecDbItemInsert(item, state->s->dbt, &state->s->error); + if (!insertStatus) { + /* + When running in EduMode, multiple users share the same + keychain and unfortionaly the rowid is used a + persistant reference and is part of the contraints (its + UNIQUE), so lets clear the rowid and try to insert the + entry again. + + This even happens for normal operation because of + SysBound entries, so in case of a failure, lets try + again to insert the record. + */ + SecDbItemClearRowId(item, NULL); + SecDbItemInsert(item, state->s->dbt, &state->s->error); + } + } /* Reset error if we had one, since we just skip the current item and continue importing what we can. */ @@ -1183,7 +1452,7 @@ static void SecServerImportClass(const void *key, const void *value, return; } struct SecServerImportItemState item_state = { - .class = class, .s = state + .class = class, .s = state, }; if (isArray(value)) { CFArrayRef items = (CFArrayRef)value; @@ -1195,7 +1464,7 @@ static void SecServerImportClass(const void *key, const void *value, } } -bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, +bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, SecurityClient *client, keybag_handle_t src_keybag, keybag_handle_t dest_keybag, CFDictionaryRef keychain, enum SecItemFilter filter, CFErrorRef *error) { bool ok = true; @@ -1204,18 +1473,29 @@ bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, if (filter == kSecBackupableItemFilter) { /* Grab a copy of all the items for which SecItemIsSystemBound() returns true. */ - require(sys_bound = SecServerExportKeychainPlist(dbt, KEYBAG_DEVICE, - KEYBAG_NONE, kSecSysBoundItemFilter, - error), errOut); + require(sys_bound = SecServerCopyKeychainPlist(dbt, client, KEYBAG_DEVICE, + KEYBAG_NONE, kSecSysBoundItemFilter, + error), errOut); } /* Delete everything in the keychain. */ - require(ok = SecServerDeleteAll(dbt, error), errOut); +#if TARGET_OS_IPHONE + if (client->inMultiUser) { + CFDataRef musrView = SecMUSRCreateActiveUserUUID(client->uid); + require_action(musrView, errOut, ok = false); + require_action(ok = SecServerDeleteAllForUser(dbt, musrView, error), errOut, CFReleaseNull(musrView)); + CFReleaseNull(musrView); + } else +#endif + { + require(ok = SecServerDeleteAll(dbt, error), errOut); + } struct SecServerImportClassState state = { .dbt = dbt, .src_keybag = src_keybag, .dest_keybag = dest_keybag, + .client = client, .filter = filter, }; /* Import the provided items, preserving rowids. */ @@ -1302,7 +1582,7 @@ bool s3dl_dbt_keys_current(SecDbConnectionRef dbt, uint32_t current_generation, }; for (size_t class_ix = 0; class_ix < array_size(classes); ++class_ix) { - Query *q = query_create(classes[class_ix], NULL, &localError); + Query *q = query_create(classes[class_ix], NULL, NULL, &localError); if (!q) return false; @@ -1323,7 +1603,7 @@ bool s3dl_dbt_keys_current(SecDbConnectionRef dbt, uint32_t current_generation, return true; } -bool s3dl_dbt_update_keys(SecDbConnectionRef dbt, CFErrorRef *error) { +bool s3dl_dbt_update_keys(SecDbConnectionRef dbt, SecurityClient *client, CFErrorRef *error) { return SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { __block bool ok = false; uint32_t keystore_generation_status; @@ -1335,14 +1615,14 @@ bool s3dl_dbt_update_keys(SecDbConnectionRef dbt, CFErrorRef *error) { /* take a lock assertion */ bool operated_while_unlocked = SecAKSDoWhileUserBagLocked(error, ^{ CFErrorRef localError = NULL; - CFDictionaryRef backup = SecServerExportKeychainPlist(dbt, - KEYBAG_DEVICE, KEYBAG_NONE, kSecNoItemFilter, &localError); + CFDictionaryRef backup = SecServerCopyKeychainPlist(dbt, NULL, + KEYBAG_DEVICE, KEYBAG_NONE, kSecNoItemFilter, &localError); if (backup) { if (localError) { secerror("Ignoring export error: %@ during roll export", localError); CFReleaseNull(localError); } - ok = SecServerImportKeychainInPlist(dbt, KEYBAG_NONE, + ok = SecServerImportKeychainInPlist(dbt, client, KEYBAG_NONE, KEYBAG_DEVICE, backup, kSecNoItemFilter, &localError); if (localError) { secerror("Ignoring export error: %@ during roll export", localError); diff --git a/OSX/sec/securityd/SecItemDb.h b/OSX/sec/securityd/SecItemDb.h index 0d9b52ce..86ed675e 100644 --- a/OSX/sec/securityd/SecItemDb.h +++ b/OSX/sec/securityd/SecItemDb.h @@ -29,6 +29,7 @@ #define _SECURITYD_SECITEMDB_H_ #include +#include "securityd_client.h" __BEGIN_DECLS @@ -111,12 +112,23 @@ enum SecItemFilter { kSecBackupableItemFilter, }; -CF_RETURNS_RETAINED CFDictionaryRef SecServerExportKeychainPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - enum SecItemFilter filter, CFErrorRef *error); +CFDictionaryRef SecServerCopyKeychainPlist(SecDbConnectionRef dbt, + SecurityClient *client, + keybag_handle_t src_keybag, + keybag_handle_t dest_keybag, + enum SecItemFilter filter, + CFErrorRef *error); bool SecServerImportKeychainInPlist(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, keybag_handle_t dest_keybag, - CFDictionaryRef keychain, enum SecItemFilter filter, CFErrorRef *error); + SecurityClient *client, + keybag_handle_t src_keybag, + keybag_handle_t dest_keybag, + CFDictionaryRef keychain, + enum SecItemFilter filter, + CFErrorRef *error); + +#if TARGET_OS_IPHONE +bool SecServerDeleteAllForUser(SecDbConnectionRef dbt, CFDataRef musrView, CFErrorRef *error); +#endif bool kc_transaction(SecDbConnectionRef dbt, CFErrorRef *error, bool(^perform)()); bool s3dl_copy_matching(SecDbConnectionRef dbt, Query *q, CFTypeRef *result, @@ -128,7 +140,7 @@ bool s3dl_query_delete(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups const SecDbAttr *SecDbAttrWithKey(const SecDbClass *c, CFTypeRef key, CFErrorRef *error); bool s3dl_dbt_keys_current(SecDbConnectionRef dbt, uint32_t current_generation, CFErrorRef *error); -bool s3dl_dbt_update_keys(SecDbConnectionRef dbt, CFErrorRef *error); +bool s3dl_dbt_update_keys(SecDbConnectionRef dbt, SecurityClient *client, CFErrorRef *error); __END_DECLS diff --git a/OSX/sec/securityd/SecItemSchema.c b/OSX/sec/securityd/SecItemSchema.c index 8fb94405..644091b4 100644 --- a/OSX/sec/securityd/SecItemSchema.c +++ b/OSX/sec/securityd/SecItemSchema.c @@ -36,7 +36,7 @@ #define __FLAGS(ARG, ...) SECDBFLAGS(__VA_ARGS__) #define SECDBFLAGS(ARG, ...) __FLAGS_##ARG | __FLAGS(__VA_ARGS__) -#define SecDbFlags(P,L,I,S,A,D,R,C,H,B,Z,E,N,U) (__FLAGS_##P|__FLAGS_##L|__FLAGS_##I|__FLAGS_##S|__FLAGS_##A|__FLAGS_##D|__FLAGS_##R|__FLAGS_##C|__FLAGS_##H|__FLAGS_##B|__FLAGS_##Z|__FLAGS_##E|__FLAGS_##N|__FLAGS_##U) +#define SecDbFlags(P,L,I,S,A,D,R,C,H,B,Z,E,N,U,V) (__FLAGS_##P|__FLAGS_##L|__FLAGS_##I|__FLAGS_##S|__FLAGS_##A|__FLAGS_##D|__FLAGS_##R|__FLAGS_##C|__FLAGS_##H|__FLAGS_##B|__FLAGS_##Z|__FLAGS_##E|__FLAGS_##N|__FLAGS_##U|__FLAGS_##V) #define __FLAGS_ 0 #define __FLAGS_P kSecDbPrimaryKeyFlag @@ -53,6 +53,8 @@ #define __FLAGS_E kSecDbDefaultEmptyFlag #define __FLAGS_N kSecDbNotNullFlag #define __FLAGS_U kSecDbInAuthenticatedDataFlag +#define __FLAGS_V0 kSecDbSyncPrimaryKeyV0 +#define __FLAGS_V2 (kSecDbSyncPrimaryKeyV0 | kSecDbSyncPrimaryKeyV2) // ,-------------- P : Part of primary key // / ,------------- L : Stored in local database @@ -68,88 +70,89 @@ // / / / / / / / / / / / ,--- E : Attribute has a default value of "" or empty data // / / / / / / / / / / / / ,-- N : Attribute must have a value // / / / / / / / / / / / / / ,- U : Attribute is stored in authenticated, but not necessarily encrypted data -// / / / / / / / / / / / / / / -// / / / / / / / / / / / / / / -// | | | | | | | | | | | | | | -// common to all | | | | | | | | | | | | | | -SECDB_ATTR(v6rowid, "rowid", RowId, SecDbFlags( ,L, , , , ,R, , ,B, , , , ), NULL, NULL); -SECDB_ATTR(v6cdat, "cdat", CreationDate, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), SecDbKeychainItemCopyCurrentDate, NULL); -SECDB_ATTR(v6mdat, "mdat",ModificationDate,SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), SecDbKeychainItemCopyCurrentDate, NULL); -SECDB_ATTR(v6labl, "labl", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6data, "data", EncryptedData, SecDbFlags( ,L, , , , , , , ,B, , , , ), SecDbKeychainItemCopyEncryptedData, NULL); -SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L, , ,A, , , ,H, , , ,N,U), NULL, NULL); -SECDB_ATTR(v6pdmn, "pdmn", Access, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L,I, ,A, , , ,H, ,Z, ,N,U), NULL, NULL); -SECDB_ATTR(v6tomb, "tomb", Tomb, SecDbFlags( ,L, , , , , , ,H, ,Z, ,N,U), NULL, NULL); -SECDB_ATTR(v6sha1, "sha1", SHA1, SecDbFlags( ,L,I, ,A, ,R, , , , , , , ), SecDbKeychainItemCopySHA1, NULL); -SECDB_ATTR(v6accc, "accc", AccessControl, SecDbFlags( , , , ,A, , , , , , , , , ), NULL, NULL); -SECDB_ATTR(v6v_Data, "v_Data", Data, SecDbFlags( , , , , ,D, ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6v_pk, "v_pk", PrimaryKey, SecDbFlags( , , , , , , , , , , , , , ), SecDbKeychainItemCopyPrimaryKey, NULL); -SECDB_ATTR(v7vwht, "vwht", String, SecDbFlags(P,L, , ,A, , , ,H, , , , ,U), NULL, NULL); -SECDB_ATTR(v7tkid, "tkid", String, SecDbFlags(P,L, , ,A, , , ,H, , , , ,U), NULL, NULL); -SECDB_ATTR(v7utomb, "u_Tomb", UTomb, SecDbFlags( , , , , , , , , , , , , , ), NULL, NULL); -// genp and inet and keys | | | | | | | | | | | | | | -SECDB_ATTR(v6crtr, "crtr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6alis, "alis", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , ), NULL, NULL); -// genp and inet | | | | | | | | | | | | | | -SECDB_ATTR(v6desc, "desc", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6icmt, "icmt", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6type, "type", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6invi, "invi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6nega, "nega", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6cusi, "cusi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6prot, "prot", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6scrp, "scrp", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6acct, "acct", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -// genp only | | | | | | | | | | | | | | -SECDB_ATTR(v6svce, "svce", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6gena, "gena", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , ), NULL, NULL); -// inet only | | | | | | | | | | | | | | -SECDB_ATTR(v6sdmn, "sdmn", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6srvr, "srvr", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6ptcl, "ptcl", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6atyp, "atyp", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6port, "port", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6path, "path", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -// cert only | | | | | | | | | | | | | | -SECDB_ATTR(v6ctyp, "ctyp", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6cenc, "cenc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6subj, "subj", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6issr, "issr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6slnr, "slnr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6skid, "skid", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6pkhh, "pkhh", Data, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); +// / / / / / / / / / / / / / / - S : Sync primpary key version +// / / / / / / / / / / / / / / / +// | | | | | | | | | | | | | | | +// common to all | | | | | | | | | | | | | | | +SECDB_ATTR(v6rowid, "rowid", RowId, SecDbFlags( ,L, , , , ,R, , ,B, , , , , ), NULL, NULL); +SECDB_ATTR(v6cdat, "cdat", CreationDate, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), SecDbKeychainItemCopyCurrentDate, NULL); +SECDB_ATTR(v6mdat, "mdat",ModificationDate,SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), SecDbKeychainItemCopyCurrentDate, NULL); +SECDB_ATTR(v6labl, "labl", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6data, "data", EncryptedData, SecDbFlags( ,L, , , , , , , ,B, , , , , ), SecDbKeychainItemCopyEncryptedData, NULL); +SECDB_ATTR(v6agrp, "agrp", String, SecDbFlags(P,L, , ,A, , , ,H, , , ,N,U,V0), NULL, NULL); +SECDB_ATTR(v6pdmn, "pdmn", Access, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6sync, "sync", Sync, SecDbFlags(P,L,I, ,A, , , ,H, ,Z, ,N,U,V0), NULL, NULL); +SECDB_ATTR(v6tomb, "tomb", Tomb, SecDbFlags( ,L, , , , , , ,H, ,Z, ,N,U, ), NULL, NULL); +SECDB_ATTR(v6sha1, "sha1", SHA1, SecDbFlags( ,L,I, ,A, ,R, , , , , , , , ), SecDbKeychainItemCopySHA1, NULL); +SECDB_ATTR(v6accc, "accc", AccessControl, SecDbFlags( , , , ,A, , , , , , , , , , ), NULL, NULL); +SECDB_ATTR(v6v_Data, "v_Data", Data, SecDbFlags( , , , , ,D, ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6v_pk, "v_pk", PrimaryKey, SecDbFlags( , , , , , , , , , , , , , , ), SecDbKeychainItemCopyPrimaryKey, NULL); +SECDB_ATTR(v7vwht, "vwht", String, SecDbFlags(P,L, , ,A, , , ,H, , , , ,U,V2), NULL, NULL); +SECDB_ATTR(v7tkid, "tkid", String, SecDbFlags(P,L, , ,A, , , ,H, , , , ,U,V2), NULL, NULL); +SECDB_ATTR(v7utomb, "u_Tomb", UTomb, SecDbFlags( , , , , , , , , , , , , , , ), NULL, NULL); +SECDB_ATTR(v8musr, "musr", UUID, SecDbFlags(P,L,I, , , , , , , , , ,N,U, ), NULL, NULL); +// genp and inet and keys | | | | | | | | | | | | | | | +SECDB_ATTR(v6crtr, "crtr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6alis, "alis", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ), NULL, NULL); +// genp and inet | | | | | | | | | | | | | | | +SECDB_ATTR(v6desc, "desc", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6icmt, "icmt", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6type, "type", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6invi, "invi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6nega, "nega", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6cusi, "cusi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6prot, "prot", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6scrp, "scrp", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6acct, "acct", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +// genp only | | | | | | | | | | | | | | | +SECDB_ATTR(v6svce, "svce", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6gena, "gena", Blob, SecDbFlags( ,L, ,S,A, , ,C,H, , , , , , ), NULL, NULL); +// inet only | | | | | | | | | | | | | | | +SECDB_ATTR(v6sdmn, "sdmn", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6srvr, "srvr", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6ptcl, "ptcl", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6atyp, "atyp", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6port, "port", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6path, "path", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +// cert only | | | | | | | | | | | | | | | +SECDB_ATTR(v6ctyp, "ctyp", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6cenc, "cenc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6subj, "subj", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6issr, "issr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6slnr, "slnr", Data, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6skid, "skid", Data, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6pkhh, "pkhh", Data, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); // cert attributes that share names with common ones but have different flags -SECDB_ATTR(v6certalis, "alis", Blob, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , ), NULL, NULL); -// keys only | | | | | | | | | | | | | | -SECDB_ATTR(v6kcls, "kcls", Number, SecDbFlags(P,L,I,S,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6perm, "perm", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6priv, "priv", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6modi, "modi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6klbl, "klbl", Data, SecDbFlags(P,L,I, ,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6atag, "atag", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ), NULL, NULL); -SECDB_ATTR(v6bsiz, "bsiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6esiz, "esiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6sdat, "sdat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6edat, "edat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6sens, "sens", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6asen, "asen", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6extr, "extr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6next, "next", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6encr, "encr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6decr, "decr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6drve, "drve", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6sign, "sign", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6vrfy, "vrfy", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6snrc, "snrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6vyrc, "vyrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6wrap, "wrap", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); -SECDB_ATTR(v6unwp, "unwp", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , ), NULL, NULL); +SECDB_ATTR(v6certalis, "alis", Blob, SecDbFlags( ,L,I,S,A, , ,C,H, , , , , , ), NULL, NULL); +// keys only | | | | | | | | | | | | | | | +SECDB_ATTR(v6kcls, "kcls", Number, SecDbFlags(P,L,I,S,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6perm, "perm", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6priv, "priv", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6modi, "modi", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6klbl, "klbl", Data, SecDbFlags(P,L,I, ,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6atag, "atag", Blob, SecDbFlags(P,L, ,S,A, , ,C,H, , ,E,N, ,V0), NULL, NULL); +SECDB_ATTR(v6bsiz, "bsiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6esiz, "esiz", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6sdat, "sdat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6edat, "edat", Date, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6sens, "sens", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6asen, "asen", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6extr, "extr", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6next, "next", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6encr, "encr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6decr, "decr", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6drve, "drve", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6sign, "sign", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6vrfy, "vrfy", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6snrc, "snrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6vyrc, "vyrc", Number, SecDbFlags( ,L, , ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6wrap, "wrap", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); +SECDB_ATTR(v6unwp, "unwp", Number, SecDbFlags( ,L,I, ,A, , ,C,H, , , , , , ), NULL, NULL); // keys attributes that share names with common ones but have different flags -SECDB_ATTR(v6keytype, "type", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -SECDB_ATTR(v6keycrtr, "crtr", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ), NULL, NULL); -// | | | | | | | | | | | | | | -SECDB_ATTR(v6version, "version", Number, SecDbFlags(P,L, , , , , , , , , , ,N, ), NULL, NULL); +SECDB_ATTR(v6keytype, "type", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +SECDB_ATTR(v6keycrtr, "crtr", Number, SecDbFlags(P,L, , ,A, , ,C,H, ,Z, ,N, ,V0), NULL, NULL); +// | | | | | | | | | | | | | | | +SECDB_ATTR(v6version, "version", Number, SecDbFlags(P,L, , , , , , , , , , ,N, , ), NULL, NULL); const SecDbClass genp_class = { .name = CFSTR("genp"), @@ -183,6 +186,7 @@ const SecDbClass genp_class = { &v6v_pk, &v6accc, &v7utomb, + &v8musr, 0 }, }; @@ -223,6 +227,7 @@ const SecDbClass inet_class = { &v6v_pk, &v6accc, &v7utomb, + &v8musr, 0 }, }; @@ -254,6 +259,7 @@ const SecDbClass cert_class = { &v6v_pk, &v6accc, &v7utomb, + &v8musr, 0 }, }; @@ -303,6 +309,7 @@ const SecDbClass keys_class = { &v6v_pk, &v6accc, &v7utomb, + &v8musr, 0 } }; @@ -324,8 +331,11 @@ const SecDbClass identity_class = { }, }; -const SecDbSchema v7_schema = { - 7, +/* Version 9 (iOS 9.3 and OSX 10.11.5) database schema + * Same contents as v8 tables; table names changed to force upgrade + * and correct default values in table. */ +const SecDbSchema v9_schema = { + 9, .classes = { &genp_class, &inet_class, @@ -336,6 +346,349 @@ const SecDbSchema v7_schema = { } }; +// Version 8 (Internal release iOS 9.3 and OSX 10.11.5) database schema +const SecDbClass v8genp_class = { + .name = CFSTR("genp8"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6svce, + &v6gena, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + 0 + }, +}; + +const SecDbClass v8inet_class = { + .name = CFSTR("inet8"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6sdmn, + &v6srvr, + &v6ptcl, + &v6atyp, + &v6port, + &v6path, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + 0 + }, +}; + +const SecDbClass v8cert_class = { + .name = CFSTR("cert8"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6ctyp, + &v6cenc, + &v6labl, + &v6certalis, + &v6subj, + &v6issr, + &v6slnr, + &v6skid, + &v6pkhh, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + 0 + }, +}; + +const SecDbClass v8keys_class = { + .name = CFSTR("keys8"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6kcls, + &v6labl, + &v6alis, + &v6perm, + &v6priv, + &v6modi, + &v6klbl, + &v6atag, + &v6keycrtr, + &v6keytype, + &v6bsiz, + &v6esiz, + &v6sdat, + &v6edat, + &v6sens, + &v6asen, + &v6extr, + &v6next, + &v6encr, + &v6decr, + &v6drve, + &v6sign, + &v6vrfy, + &v6snrc, + &v6vyrc, + &v6wrap, + &v6unwp, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + &v8musr, + 0 + } +}; + +const SecDbSchema v8_schema = { + 8, + .classes = { + &v8genp_class, + &v8inet_class, + &v8cert_class, + &v8keys_class, + &tversion_class, + 0 + } +}; + +// Version 7 (iOS 9 and OSX 10.11) database schema +const SecDbClass v7genp_class = { + .name = CFSTR("genp7"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6svce, + &v6gena, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + 0 + }, +}; + +const SecDbClass v7inet_class = { + .name = CFSTR("inet7"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6desc, + &v6icmt, + &v6crtr, + &v6type, + &v6scrp, + &v6labl, + &v6alis, + &v6invi, + &v6nega, + &v6cusi, + &v6prot, + &v6acct, + &v6sdmn, + &v6srvr, + &v6ptcl, + &v6atyp, + &v6port, + &v6path, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + 0 + }, +}; + +const SecDbClass v7cert_class = { + .name = CFSTR("cert7"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6ctyp, + &v6cenc, + &v6labl, + &v6certalis, + &v6subj, + &v6issr, + &v6slnr, + &v6skid, + &v6pkhh, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + 0 + }, +}; + +const SecDbClass v7keys_class = { + .name = CFSTR("keys7"), + .attrs = { + &v6rowid, + &v6cdat, + &v6mdat, + &v6kcls, + &v6labl, + &v6alis, + &v6perm, + &v6priv, + &v6modi, + &v6klbl, + &v6atag, + &v6keycrtr, + &v6keytype, + &v6bsiz, + &v6esiz, + &v6sdat, + &v6edat, + &v6sens, + &v6asen, + &v6extr, + &v6next, + &v6encr, + &v6decr, + &v6drve, + &v6sign, + &v6vrfy, + &v6snrc, + &v6vyrc, + &v6wrap, + &v6unwp, + &v6data, + &v6agrp, + &v6pdmn, + &v6sync, + &v6tomb, + &v6sha1, + &v7vwht, + &v7tkid, + &v6v_Data, + &v6v_pk, + &v6accc, + &v7utomb, + 0 + } +}; + + +const SecDbSchema v7_schema = { + 7, + .classes = { + &v7genp_class, + &v7inet_class, + &v7cert_class, + &v7keys_class, + &tversion_class, + 0 + } +}; + // Version 6 (iOS 7 and OSX 10.9) database schema static const SecDbClass v6genp_class = { @@ -633,6 +986,8 @@ static const SecDbSchema v5_schema = { }; const SecDbSchema *kc_schemas[] = { + &v9_schema, + &v8_schema, &v7_schema, &v6_schema, &v5_schema, diff --git a/OSX/sec/securityd/SecItemSchema.h b/OSX/sec/securityd/SecItemSchema.h index 523fc96f..d79fff37 100644 --- a/OSX/sec/securityd/SecItemSchema.h +++ b/OSX/sec/securityd/SecItemSchema.h @@ -55,6 +55,7 @@ extern const SecDbAttr v6svce; extern const SecDbAttr v7vwht; extern const SecDbAttr v7tkid; extern const SecDbAttr v7utomb; +extern const SecDbAttr v8musr; // TODO: Directly expose other important attributes like // kSecItemSyncAttr, kSecItemTombAttr, kSecItemCdatAttr, kSecItemMdatAttr, kSecItemDataAttr diff --git a/OSX/sec/securityd/SecItemServer.c b/OSX/sec/securityd/SecItemServer.c index 09e4287a..86448f4f 100644 --- a/OSX/sec/securityd/SecItemServer.c +++ b/OSX/sec/securityd/SecItemServer.c @@ -44,14 +44,22 @@ // TODO: Make this include work on both platforms. rdar://problem/16526848 #if TARGET_OS_EMBEDDED #include +#include #else /* defines from */ #define kSecEntitlementAssociatedDomains CFSTR("com.apple.developer.associated-domains") #define kSecEntitlementPrivateAssociatedDomains CFSTR("com.apple.private.associated-domains") #endif +#if TARGET_OS_EMBEDDED +#include +#include +#include +#endif + #include #include +#include #include #include "swcagent_client.h" @@ -98,7 +106,7 @@ static bool SecKeychainDbGetVersion(SecDbConnectionRef dbt, int *version, CFErro __block CFNumberRef versionNumber = NULL; __block CFErrorRef localError = NULL; - require_quiet(query = query_create(&tversion_class, NULL, &localError), out); + require_quiet(query = query_create(&tversion_class, NULL, NULL, &localError), out); require_quiet(SecDbItemSelect(query, dbt, &localError, ^bool(const SecDbAttr *attr) { // Bind all attributes. return true; @@ -132,14 +140,71 @@ out: return ok || CFErrorPropagate(localError, error); } +static bool +isClassD(SecDbItemRef item) +{ + CFTypeRef accessible = SecDbItemGetCachedValueWithName(item, kSecAttrAccessible); + + if (CFEqualSafe(accessible, kSecAttrAccessibleAlways) || CFEqualSafe(accessible, kSecAttrAccessibleAlwaysThisDeviceOnly)) + return true; + return false; +} + +#if TARGET_OS_EMBEDDED + +static int64_t +measureDuration(struct timeval *start) +{ + struct timeval stop; + int64_t duration; + + gettimeofday(&stop, NULL); + + duration = (stop.tv_sec-start->tv_sec) * 1000; + duration += (stop.tv_usec / 1000) - (start->tv_usec / 1000); + + return SecBucket2Significant(duration); +} + +static void +measureUpgradePhase1(struct timeval *start, bool success, int64_t itemsMigrated) +{ + int64_t duration = measureDuration(start); + + if (success) { + ADClientSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-items-success"), itemsMigrated); + ADClientSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-time-success"), duration); + } else { + ADClientSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-items-fail"), itemsMigrated); + ADClientSetValueForScalarKey(CFSTR("com.apple.keychain.phase1.migrated-time-fail"), duration); + } +} + +static void +measureUpgradePhase2(struct timeval *start, int64_t itemsMigrated) +{ + int64_t duration = measureDuration(start); + + ADClientSetValueForScalarKey(CFSTR("com.apple.keychain.phase2.migrated-items"), itemsMigrated); + ADClientSetValueForScalarKey(CFSTR("com.apple.keychain.phase2.migrated-time"), duration); +} +#endif /* TARGET_OS_EMBEDDED */ + // Goes through all tables represented by old_schema and tries to migrate all items from them into new (current version) tables. -static bool SecKeychainDbUpgradeFromSchema(SecDbConnectionRef dbt, const SecDbSchema *oldSchema, bool *inProgress, CFErrorRef *error) { +static bool UpgradeSchemaPhase1(SecDbConnectionRef dbt, const SecDbSchema *oldSchema, CFErrorRef *error) +{ __block bool ok = true; const SecDbSchema *newSchema = kc_schemas[0]; SecDbClass const *const *oldClass; SecDbClass const *const *newClass; SecDbQueryRef query = NULL; CFMutableStringRef sql = NULL; +#if TARGET_OS_EMBEDDED + __block int64_t itemsMigrated = 0; + struct timeval start; + + gettimeofday(&start, NULL); +#endif // Rename existing tables to old names, as present in old schemas. sql = CFStringCreateMutable(NULL, 0); @@ -153,6 +218,17 @@ static bool SecKeychainDbUpgradeFromSchema(SecDbConnectionRef dbt, const SecDbSc } } require_quiet(ok &= SecDbExec(dbt, sql, error), out); + CFReleaseNull(sql); + + // Drop indices that that new schemas will use + sql = CFStringCreateMutable(NULL, 0); + for (newClass = newSchema->classes; *newClass != NULL; newClass++) { + SecDbForEachAttrWithMask((*newClass), desc, kSecDbIndexFlag | kSecDbInFlag) { + CFStringAppendFormat(sql, 0, CFSTR("DROP INDEX IF EXISTS %@%@;"), (*newClass)->name, desc->name); + } + } + require_quiet(ok &= SecDbExec(dbt, sql, error), out); + CFReleaseNull(sql); // Create tables for new schema. require_quiet(ok &= SecItemDbCreateSchema(dbt, newSchema, error), out); @@ -162,10 +238,12 @@ static bool SecKeychainDbUpgradeFromSchema(SecDbConnectionRef dbt, const SecDbSc if (CFEqual((*oldClass)->name, (*newClass)->name)) continue; + secnotice("upgr", "Upgrading table %@", (*oldClass)->name); + // Prepare query to iterate through all items in cur_class. if (query != NULL) query_destroy(query, NULL); - require_quiet(query = query_create(*oldClass, NULL, error), out); + require_quiet(query = query_create(*oldClass, SecMUSRGetAllViews(), NULL, error), out); ok &= SecDbItemSelect(query, dbt, error, ^bool(const SecDbAttr *attr) { // We are interested in all attributes which are physically present in the DB. @@ -176,33 +254,22 @@ static bool SecKeychainDbUpgradeFromSchema(SecDbConnectionRef dbt, const SecDbSc }, NULL, NULL, ^(SecDbItemRef item, bool *stop) { CFErrorRef localError = NULL; +#if TARGET_OS_EMBEDDED + itemsMigrated++; +#endif // Switch item to the new class. item->class = *newClass; - // Decrypt the item. - if (SecDbItemEnsureDecrypted(item, &localError)) { + if (isClassD(item)) { + // Decrypt the item. + ok &= SecDbItemEnsureDecrypted(item, &localError); + require_quiet(ok, out); + // Delete SHA1 field from the item, so that it is newly recalculated before storing // the item into the new table. require_quiet(ok &= SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbSHA1Attr, error), - kCFNull, error), out); + kCFNull, error), out); } else { - OSStatus status = SecErrorGetOSStatus(localError); - - // Items producing errSecDecode are silently dropped - they are not decodable and lost forever. - require_quiet(status != errSecDecode, out); - - // errSecAuthNeeded means that it is an ACL-based item which requires authentication (or at least - // ACM context, which we do not have). Other errors should abort the migration completely. - require_action_quiet(status == errSecAuthNeeded || status == errSecInteractionNotAllowed, out, - ok &= CFErrorPropagate(localError, error); localError = NULL); - - // If we've hit item which could not be decoded because of locked keybag, store it into - // new tables so that accessing it fails with errSecInteractionNotAllowed instead of errSecItemNotFound. - // Next connection to the DB with opened keybag will properly decode and replace the item. - if (status == errSecInteractionNotAllowed) { - *inProgress = true; - } - // Leave item encrypted, do not ever try to decrypt it since it will fail. item->_edataState = kSecDbItemAlwaysEncrypted; } @@ -210,11 +277,31 @@ static bool SecKeychainDbUpgradeFromSchema(SecDbConnectionRef dbt, const SecDbSc // Insert new item into the new table. if (!SecDbItemInsert(item, dbt, &localError)) { secerror("item: %@ insert during upgrade: %@", item, localError); - ok &= CFErrorPropagate(localError, error); localError = NULL; + ok = false; } out: - CFReleaseSafe(localError); + if (localError) { + OSStatus status = SecErrorGetOSStatus(localError); + + switch (status) { + // continue to upgrade and don't propagate errors for insert failures + // that are typical of a single item failure + case errSecDecode: + case errSecDuplicateItem: + ok = true; + break; + case errSecInteractionNotAllowed: + case errSecAuthNeeded: + ok = true; + break; + default: + ok &= CFErrorPropagate(CFRetainSafe(localError), error); + break; + } + CFReleaseSafe(localError); + } + *stop = !ok; }); require_quiet(ok, out); @@ -231,6 +318,10 @@ static bool SecKeychainDbUpgradeFromSchema(SecDbConnectionRef dbt, const SecDbSc require_quiet(ok &= SecDbExec(dbt, sql, error), out); out: +#if TARGET_OS_EMBEDDED + measureUpgradePhase1(&start, ok, SecBucket2Significant(itemsMigrated)); +#endif + if (query != NULL) { query_destroy(query, NULL); } @@ -239,13 +330,24 @@ out: } // Goes through all tables represented by old_schema and tries to migrate all items from them into new (current version) tables. -static bool SecKeychainDbUpgradeUnlockedItems(SecDbConnectionRef dbt, bool *inProgress, CFErrorRef *error) { +static bool UpgradeItemPhase2(SecDbConnectionRef dbt, bool *inProgress, CFErrorRef *error) { __block bool ok = true; SecDbQueryRef query = NULL; +#if TARGET_OS_EMBEDDED + __block int64_t itemsMigrated = 0; + struct timeval start; + + gettimeofday(&start, NULL); +#endif // Go through all classes in new schema const SecDbSchema *newSchema = kc_schemas[0]; for (const SecDbClass *const *class = newSchema->classes; *class != NULL && !*inProgress; class++) { + if(CFEqual((*class)->name, tversion_class.name)) { + //Don't try to decrypt items in tversion table + continue; + } + const SecDbAttr *pdmn = SecDbClassAttrWithKind(*class, kSecDbAccessAttr, error); if (pdmn == nil) { continue; @@ -255,7 +357,7 @@ static bool SecKeychainDbUpgradeUnlockedItems(SecDbConnectionRef dbt, bool *inPr if (query != NULL) { query_destroy(query, NULL); } - require_action_quiet(query = query_create(*class, NULL, error), out, ok = false); + require_action_quiet(query = query_create(*class, SecMUSRGetAllViews(), NULL, error), out, ok = false); ok = SecDbItemSelect(query, dbt, error, NULL, ^bool(const SecDbAttr *attr) { // No simple per-attribute filtering. return false; @@ -270,34 +372,50 @@ static bool SecKeychainDbUpgradeUnlockedItems(SecDbConnectionRef dbt, bool *inPr }, ^(SecDbItemRef item, bool *stop) { CFErrorRef localError = NULL; +#if TARGET_OS_EMBEDDED + itemsMigrated++; +#endif + // Decrypt the item. if (SecDbItemEnsureDecrypted(item, &localError)) { + // Delete SHA1 field from the item, so that it is newly recalculated before storing // the item into the new table. require_quiet(ok = SecDbItemSetValue(item, SecDbClassAttrWithKind(item->class, kSecDbSHA1Attr, error), - kCFNull, error), out); + kCFNull, &localError), out); // Replace item with the new value in the table; this will cause the item to be decoded and recoded back, // incl. recalculation of item's hash. - ok = SecDbItemUpdate(item, item, dbt, false, error); - } else { - CFIndex status = CFErrorGetCode(localError); + ok = SecDbItemUpdate(item, item, dbt, false, &localError); + } - // Items producing errSecDecode are silently dropped - they are not decodable and lost forever. - require_action_quiet(status != errSecDecode, out, ok = SecDbItemDelete(item, dbt, false, error)); + if (localError) { + CFIndex status = CFErrorGetCode(localError); - // If we are still not able to decrypt the item because the class key is not released yet, - // remember that DB still needs phase2 migration to be run next time a connection is made. Also - // stop iterating next items, it would be just waste of time because the whole iteration will be run - // next time when this phase2 will be rerun. - if (status == errSecInteractionNotAllowed) { - *inProgress = true; - *stop = true; - } else { - // errSecAuthNeeded means that it is an ACL-based item which requires authentication (or at least - // ACM context, which we do not have). Other errors should abort the migration completely. - require_action_quiet(status == errSecAuthNeeded, out, - ok = CFErrorPropagate(CFRetainSafe(localError), error)); + switch (status) { + case errSecDecode: + // Items producing errSecDecode are silently dropped - they are not decodable and lost forever. + (void)SecDbItemDelete(item, dbt, false, error); + ok = true; + break; + case errSecInteractionNotAllowed: + // If we are still not able to decrypt the item because the class key is not released yet, + // remember that DB still needs phase2 migration to be run next time a connection is made. Also + // stop iterating next items, it would be just waste of time because the whole iteration will be run + // next time when this phase2 will be rerun. + *inProgress = true; + *stop = true; + ok = true; + break; + case errSecAuthNeeded: + // errSecAuthNeeded means that it is an ACL-based item which requires authentication (or at least + // ACM context, which we do not have). + ok = true; + break; + default: + // Other errors should abort the migration completely. + ok = CFErrorPropagate(CFRetainSafe(localError), error); + break; } } @@ -309,6 +427,10 @@ static bool SecKeychainDbUpgradeUnlockedItems(SecDbConnectionRef dbt, bool *inPr require(ok, out); } +#if TARGET_OS_EMBEDDED + measureUpgradePhase2(&start, SecBucket2Significant(itemsMigrated)); +#endif + out: if (query != NULL) query_destroy(query, NULL); @@ -316,6 +438,7 @@ out: } static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, bool *inProgress, CFErrorRef *error) { + __block bool didPhase2 = false; __block bool ok = true; // The schema we want to have is the first in the list of schemas. @@ -335,6 +458,7 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, ok &= SecDbTransaction(dbt, kSecDbExclusiveTransactionType, error, ^(bool *commit) { CFStringRef sql = NULL; + bool didPhase1 = false; // Get version again once we start a transaction, someone else might change the migration state. int version = 0; @@ -371,19 +495,41 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, ok = SecDbError(SQLITE_CORRUPT, error, CFSTR("no schema for version: %d"), oldVersion); secerror("no schema for version %d", oldVersion)); - require(ok = SecKeychainDbUpgradeFromSchema(dbt, oldSchema, inProgress, error), out); - } else { - // Just go through non-D-class items in new tables and apply decode/encode on them, because - // they were not recoded completely during some previous old-schema migration attempt (a.k.a. phase2) - require(ok = SecKeychainDbUpgradeUnlockedItems(dbt, inProgress, error), out); + secnotice("upgr", "Upgrading from version %d to %d", oldVersion, newSchema->version); + require(ok = UpgradeSchemaPhase1(dbt, oldSchema, error), out); + + didPhase1 = true; } - if (!*inProgress) { - // If either migration path we did reported that the migration was complete, signalize that - // in the version database by cleaning oldVersion (which is stored in upper halfword of the version) - oldVersion = 0; + { + CFErrorRef phase2Error = NULL; + + // Lests try to go through non-D-class items in new tables and apply decode/encode on them + // If this fails the error will be ignored after doing a phase1 since but not in the second + // time when we are doing phase2. + ok = UpgradeItemPhase2(dbt, inProgress, &phase2Error); + if (!ok) { + if (didPhase1) { + *inProgress = true; + ok = true; + } else { + SecErrorPropagate(phase2Error, error); + } + } + CFReleaseNull(phase2Error); + require(ok, out); + + if (!*inProgress) { + // If either migration path we did reported that the migration was complete, signalize that + // in the version database by cleaning oldVersion (which is stored in upper halfword of the version) + secnotice("upgr", "Done upgrading from version %d to %d", oldVersion, newSchema->version); + oldVersion = 0; + + didPhase2 = true; + } } + // Update database version table. version |= oldVersion << 16; sql = CFStringCreateWithFormat(NULL, NULL, CFSTR("UPDATE %@ SET %@ = %d"), @@ -395,10 +541,23 @@ static bool SecKeychainDbUpgradeFromVersion(SecDbConnectionRef dbt, int version, *commit = ok; }); + if (ok && didPhase2) { +#if TARGET_OS_EMBEDDED + ADClientAddValueForScalarKey(CFSTR("com.apple.keychain.migration-success"), 1); +#endif + } + out: - if (!ok) { + if (!ok || (error && *error)) { + if (ok) { + secwarning("upgrade: error has been set but status is true"); + ok = false; + } secerror("unable to complete upgrade, marking DB as corrupt: %@", error ? *error : NULL); - SecDbCorrupt(dbt); + SecDbCorrupt(dbt, error ? *error : NULL); +#if TARGET_OS_EMBEDDED + ADClientAddValueForScalarKey(CFSTR("com.apple.keychain.migration-failure"), 1); +#endif } return ok; @@ -435,11 +594,12 @@ bool itemInAccessGroup(CFDictionaryRef item, CFArrayRef accessGroups) { static CF_RETURNS_RETAINED CFDataRef SecServerExportBackupableKeychain(SecDbConnectionRef dbt, + SecurityClient *client, keybag_handle_t src_keybag, keybag_handle_t dest_keybag, CFErrorRef *error) { CFDataRef data_out = NULL; /* Export everything except the items for which SecItemIsSystemBound() returns true. */ - CFDictionaryRef keychain = SecServerExportKeychainPlist(dbt, + CFDictionaryRef keychain = SecServerCopyKeychainPlist(dbt, client, src_keybag, dest_keybag, kSecBackupableItemFilter, error); if (keychain) { @@ -453,8 +613,12 @@ static CF_RETURNS_RETAINED CFDataRef SecServerExportBackupableKeychain(SecDbConn } static bool SecServerImportBackupableKeychain(SecDbConnectionRef dbt, - keybag_handle_t src_keybag, - keybag_handle_t dest_keybag, CFDataRef data, CFErrorRef *error) { + SecurityClient *client, + keybag_handle_t src_keybag, + keybag_handle_t dest_keybag, + CFDataRef data, + CFErrorRef *error) +{ return kc_transaction(dbt, error, ^{ bool ok = false; CFDictionaryRef keychain; @@ -463,8 +627,11 @@ static bool SecServerImportBackupableKeychain(SecDbConnectionRef dbt, error); if (keychain) { if (isDictionary(keychain)) { - ok = SecServerImportKeychainInPlist(dbt, src_keybag, - dest_keybag, keychain, + ok = SecServerImportKeychainInPlist(dbt, + client, + src_keybag, + dest_keybag, + keychain, kSecBackupableItemFilter, error); } else { @@ -476,13 +643,13 @@ static bool SecServerImportBackupableKeychain(SecDbConnectionRef dbt, }); } -static CF_RETURNS_RETAINED CFDataRef SecServerKeychainBackup(SecDbConnectionRef dbt, CFDataRef keybag, +static CFDataRef SecServerKeychainCreateBackup(SecDbConnectionRef dbt, SecurityClient *client, CFDataRef keybag, CFDataRef password, CFErrorRef *error) { CFDataRef backup = NULL; keybag_handle_t backup_keybag; if (ks_open_keybag(keybag, password, &backup_keybag, error)) { /* Export from system keybag to backup keybag. */ - backup = SecServerExportBackupableKeychain(dbt, KEYBAG_DEVICE, backup_keybag, error); + backup = SecServerExportBackupableKeychain(dbt, client, KEYBAG_DEVICE, backup_keybag, error); if (!ks_close_keybag(backup_keybag, error)) { CFReleaseNull(backup); } @@ -490,14 +657,19 @@ static CF_RETURNS_RETAINED CFDataRef SecServerKeychainBackup(SecDbConnectionRef return backup; } -static bool SecServerKeychainRestore(SecDbConnectionRef dbt, CFDataRef backup, - CFDataRef keybag, CFDataRef password, CFErrorRef *error) { +static bool SecServerKeychainRestore(SecDbConnectionRef dbt, + SecurityClient *client, + CFDataRef backup, + CFDataRef keybag, + CFDataRef password, + CFErrorRef *error) +{ keybag_handle_t backup_keybag; if (!ks_open_keybag(keybag, password, &backup_keybag, error)) return false; /* Import from backup keybag to system keybag. */ - bool ok = SecServerImportBackupableKeychain(dbt, backup_keybag, KEYBAG_DEVICE, + bool ok = SecServerImportBackupableKeychain(dbt, client, backup_keybag, KEYBAG_DEVICE, backup, error); ok &= ks_close_keybag(backup_keybag, error); @@ -584,17 +756,19 @@ static SecDbRef kc_dbhandle(void) { } /* For whitebox testing only */ -void kc_dbhandle_reset(void); -void kc_dbhandle_reset(void) +void SecKeychainDbReset(dispatch_block_t inbetween) { - __block bool done = false; - dispatch_once(&_kc_dbhandle_once, ^{ - kc_dbhandle_init(); - done = true; - }); - // TODO: Not thread safe at all! - FOR DEBUGGING ONLY - if (!done) - kc_dbhandle_init(); + CFStringRef dbPath = __SecKeychainCopyPath(); + if (dbPath == NULL) + abort(); + + CFReleaseNull(_kc_dbhandle); + + if (inbetween) + inbetween(); + + _kc_dbhandle = SecKeychainDbCreate(dbPath); + CFRelease(dbPath); } static SecDbConnectionRef kc_aquire_dbt(bool writeAndRead, CFErrorRef *error) { @@ -625,7 +799,7 @@ static bool kc_with_dbt(bool writeAndRead, CFErrorRef *error, bool (^perform)(Se } static bool -items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, +items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, CFDataRef musrView, CFDataRef issuer, CFArrayRef issuers, int recurse) { Query *q; @@ -636,6 +810,7 @@ items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, if (CFArrayContainsValue(issuers, CFRangeMake(0, CFArrayGetCount(issuers)), issuer)) return true; + /* XXX make musr supported */ const void *keys[] = { kSecClass, kSecReturnRef, kSecAttrSubject }; const void *vals[] = { kSecClassCertificate, kCFBooleanTrue, issuer }; CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, array_size(keys), NULL, NULL); @@ -644,7 +819,7 @@ items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, return false; CFErrorRef localError = NULL; - q = query_create_with_limit(query, kSecMatchUnlimited, &localError); + q = query_create_with_limit(query, musrView, kSecMatchUnlimited, &localError); CFRelease(query); if (q) { s3dl_copy_matching(dbt, q, (CFTypeRef*)&results, accessGroups, &localError); @@ -663,7 +838,7 @@ items_matching_issuer_parent(SecDbConnectionRef dbt, CFArrayRef accessGroups, if (CFEqual(cert_issuer, issuer)) continue; if (recurse-- > 0) - found = items_matching_issuer_parent(dbt, accessGroups, cert_issuer, issuers, recurse); + found = items_matching_issuer_parent(dbt, accessGroups, musrView, cert_issuer, issuers, recurse); } CFReleaseSafe(results); @@ -674,7 +849,7 @@ bool match_item(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFDic { if (q->q_match_issuer) { CFDataRef issuer = CFDictionaryGetValue(item, kSecAttrIssuer); - if (!items_matching_issuer_parent(dbt, accessGroups, issuer, q->q_match_issuer, 10 /*max depth*/)) + if (!items_matching_issuer_parent(dbt, accessGroups, q->q_musrView, issuer, q->q_match_issuer, 10 /*max depth*/)) return false; } @@ -687,30 +862,6 @@ bool match_item(SecDbConnectionRef dbt, Query *q, CFArrayRef accessGroups, CFDic **************** Beginning of Externally Callable Interface **************** ****************************************************************************/ -#if 0 -// TODO Use as a safety wrapper -static bool SecErrorWith(CFErrorRef *in_error, bool (^perform)(CFErrorRef *error)) { - CFErrorRef error = in_error ? *in_error : NULL; - bool ok; - if ((ok = perform(&error))) { - assert(error == NULL); - if (error) - secerror("error + success: %@", error); - } else { - assert(error); - OSStatus status = SecErrorGetOSStatus(error); - if (status != errSecItemNotFound) // Occurs in normal operation, so exclude - secerror("error:[%" PRIdOSStatus "] %@", status, error); - if (in_error) { - *in_error = error; - } else { - CFReleaseNull(error); - } - } - return ok; -} -#endif - void (*SecTaskDiagnoseEntitlements)(CFArrayRef accessGroups) = NULL; /* AUDIT[securityd](done): @@ -718,8 +869,10 @@ void (*SecTaskDiagnoseEntitlements)(CFArrayRef accessGroups) = NULL; */ static bool SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, - CFArrayRef accessGroups, CFErrorRef *error) + SecurityClient *client, CFErrorRef *error) { + CFArrayRef accessGroups = client->accessGroups; + CFIndex ag_count; if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { if (SecTaskDiagnoseEntitlements) @@ -734,7 +887,7 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, } bool ok = false; - Query *q = query_create_with_limit(query, 1, error); + Query *q = query_create_with_limit(query, client->musr, 1, error); if (q) { CFStringRef agrp = CFDictionaryGetValue(q->q_item, kSecAttrAccessGroup); if (agrp && accessGroupsAllows(accessGroups, agrp)) { @@ -745,15 +898,32 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, CFRetainSafe(accessGroups); } +#if TARGET_OS_IPHONE + if (q->q_sync_bubble && client->inMultiUser) { + CFReleaseNull(q->q_musrView); + q->q_musrView = SecMUSRCreateSyncBubbleUserUUID(q->q_sync_bubble); + } else if (client->inMultiUser && client->isNetworkExtension) { + CFReleaseNull(q->q_musrView); + q->q_musrView = SecMUSRCreateBothUserAndSystemUUID(client->uid); + } else if (q->q_system_keychain && client->inMultiUser) { + CFReleaseNull(q->q_musrView); + q->q_musrView = SecMUSRCopySystemKeychainUUID(); + } else { + q->q_system_keychain = false; + } +#endif + query_set_caller_access_groups(q, accessGroups); /* Sanity check the query. */ - if (q->q_use_item_list) { + if (q->q_system_keychain && !client->allowSystemKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); + } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); + } else if (q->q_system_keychain && q->q_sync_bubble) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("can't do both system and syncbubble keychain")); + } else if (q->q_use_item_list) { ok = SecError(errSecUseItemListUnsupported, error, CFSTR("use item list unsupported")); -#if defined(MULTIPLE_KEYCHAINS) - } else if (q->q_use_keychain) { - ok = SecError(errSecUseKeychainUnsupported, error, CFSTR("use keychain list unsupported")); -#endif } else if (q->q_match_issuer && ((q->q_class != &cert_class) && (q->q_class != &identity_class))) { ok = SecError(errSecUnsupportedOperation, error, CFSTR("unsupported match attribute")); @@ -774,18 +944,38 @@ SecItemServerCopyMatching(CFDictionaryRef query, CFTypeRef *result, } bool -_SecItemCopyMatching(CFDictionaryRef query, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error) { - return SecItemServerCopyMatching(query, result, accessGroups, error); +_SecItemCopyMatching(CFDictionaryRef query, SecurityClient *client, CFTypeRef *result, CFErrorRef *error) { + return SecItemServerCopyMatching(query, result, client, error); +} + +#if TARGET_OS_IPHONE +static bool +SecItemSynchronizable(CFDictionaryRef query) +{ + bool result = false; + CFTypeRef value = CFDictionaryGetValue(query, kSecAttrSynchronizable); + if (isBoolean(value)) + return CFBooleanGetValue(value); + else if (isNumber(value)) { + SInt32 number = 0; + (void)CFNumberGetValue(value, kCFNumberSInt32Type, &number); + result = !!number; + } + + return result; } +#endif + /* AUDIT[securityd](done): attributes (ok) is a caller provided dictionary, only its cf type has been checked. */ bool -_SecItemAdd(CFDictionaryRef attributes, CFArrayRef accessGroups, - CFTypeRef *result, CFErrorRef *error) +_SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *result, CFErrorRef *error) { + CFArrayRef accessGroups = client->accessGroups; + bool ok = true; CFIndex ag_count; if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { @@ -795,13 +985,12 @@ _SecItemAdd(CFDictionaryRef attributes, CFArrayRef accessGroups, CFSTR("client has neither application-identifier nor keychain-access-groups entitlements")); } - Query *q = query_create_with_limit(attributes, 0, error); + Query *q = query_create_with_limit(attributes, client->musr, 0, error); if (q) { /* Access group sanity checking. */ CFStringRef agrp = (CFStringRef)CFDictionaryGetValue(attributes, kSecAttrAccessGroup); - CFArrayRef ag = accessGroups; /* Having the special accessGroup "*" allows access to all accessGroups. */ if (CFArrayContainsValue(accessGroups, CFRangeMake(0, ag_count), CFSTR("*"))) accessGroups = NULL; @@ -811,23 +1000,36 @@ _SecItemAdd(CFDictionaryRef attributes, CFArrayRef accessGroups, if (!accessGroupsAllows(accessGroups, agrp)) ok = SecError(errSecNoAccessForItem, error, CFSTR("NoAccessForItem")); } else { - agrp = (CFStringRef)CFArrayGetValueAtIndex(ag, 0); + agrp = (CFStringRef)CFArrayGetValueAtIndex(client->accessGroups, 0); /* We are using an implicit access group, add it as if the user specified it as an attribute. */ query_add_attribute(kSecAttrAccessGroup, agrp, q); } +#if TARGET_OS_IPHONE + if (q->q_system_keychain && client->inMultiUser) { + CFReleaseNull(q->q_musrView); + q->q_musrView = SecMUSRCopySystemKeychainUUID(); + } else { + q->q_system_keychain = false; + } + query_add_attribute_with_desc(&v8musr, q->q_musrView, q); +#endif if (ok) { query_ensure_access_control(q, agrp); - if (q->q_row_id) + if (q->q_system_keychain && !client->allowSystemKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); + } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); +#if TARGET_OS_IPHONE + } else if (q->q_system_keychain && SecItemSynchronizable(attributes) && !client->inMultiUser) { + ok = SecError(errSecInvalidKey, error, CFSTR("Can't store system keychain and synchronizable")); +#endif + } else if (q->q_row_id) { ok = SecError(errSecValuePersistentRefUnsupported, error, CFSTR("q_row_id")); // TODO: better error string - #if defined(MULTIPLE_KEYCHAINS) - else if (q->q_use_keychain_list) - ok = SecError(errSecUseKeychainListUnsupported, error, CFSTR("q_use_keychain_list")); // TODO: better error string; - #endif - else if (!q->q_error) { + } else if (!q->q_error) { ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt){ return kc_transaction(dbt, error, ^{ query_pre_add(q, true); @@ -849,8 +1051,10 @@ _SecItemAdd(CFDictionaryRef attributes, CFArrayRef accessGroups, */ bool _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, - CFArrayRef accessGroups, CFErrorRef *error) + SecurityClient *client, CFErrorRef *error) { + CFArrayRef accessGroups = client->accessGroups; + CFIndex ag_count; if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { if (SecTaskDiagnoseEntitlements) @@ -865,14 +1069,31 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, } bool ok = true; - Query *q = query_create_with_limit(query, kSecMatchUnlimited, error); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); if (!q) { ok = false; } if (ok) { +#if TARGET_OS_IPHONE + if (q->q_system_keychain && client->inMultiUser) { + CFReleaseNull(q->q_musrView); + q->q_musrView = SecMUSRCopySystemKeychainUUID(); + } else { + q->q_system_keychain = false; + } +#endif + /* Sanity check the query. */ query_set_caller_access_groups(q, accessGroups); - if (q->q_use_item_list) { + if (q->q_system_keychain && !client->allowSystemKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); + } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); +#if TARGET_OS_IPHONE + } else if (q->q_system_keychain && SecItemSynchronizable(attributesToUpdate) && !client->inMultiUser) { + ok = SecError(errSecInvalidKey, error, CFSTR("Can't update an system keychain item with synchronizable")); +#endif + } else if (q->q_use_item_list) { ok = SecError(errSecUseItemListUnsupported, error, CFSTR("use item list not supported")); } else if (q->q_return_type & kSecReturnDataMask) { /* Update doesn't return anything so don't ask for it. */ @@ -912,8 +1133,10 @@ _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, query (ok) is a caller provided dictionary, only its cf type has been checked. */ bool -_SecItemDelete(CFDictionaryRef query, CFArrayRef accessGroups, CFErrorRef *error) +_SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error) { + CFArrayRef accessGroups = client->accessGroups; + CFIndex ag_count; if (!accessGroups || 0 == (ag_count = CFArrayGetCount(accessGroups))) { if (SecTaskDiagnoseEntitlements) @@ -927,20 +1150,33 @@ _SecItemDelete(CFDictionaryRef query, CFArrayRef accessGroups, CFErrorRef *error accessGroups = NULL; } - Query *q = query_create_with_limit(query, kSecMatchUnlimited, error); + Query *q = query_create_with_limit(query, client->musr, kSecMatchUnlimited, error); bool ok; if (q) { +#if TARGET_OS_IPHONE + if (q->q_system_keychain && client->inMultiUser) { + CFReleaseNull(q->q_musrView); + q->q_musrView = SecMUSRCopySystemKeychainUUID(); + } else { + q->q_system_keychain = false; + } +#endif + query_set_caller_access_groups(q, accessGroups); /* Sanity check the query. */ - if (q->q_limit != kSecMatchUnlimited) + if (q->q_system_keychain && !client->allowSystemKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for system keychain")); + } else if (q->q_sync_bubble && !client->allowSyncBubbleKeychain) { + ok = SecError(errSecMissingEntitlement, error, CFSTR("client doesn't have entitlement for syncbubble keychain")); + } else if (q->q_limit != kSecMatchUnlimited) { ok = SecError(errSecMatchLimitUnsupported, error, CFSTR("match limit not supported by delete")); - else if (query_match_count(q) != 0) + } else if (query_match_count(q) != 0) { ok = SecError(errSecItemMatchUnsupported, error, CFSTR("match not supported by delete")); - else if (q->q_ref) + } else if (q->q_ref) { ok = SecError(errSecValueRefUnsupported, error, CFSTR("value ref not supported by delete")); - else if (q->q_row_id && query_attr_count(q)) + } else if (q->q_row_id && query_attr_count(q)) { ok = SecError(errSecItemIllegalQuery, error, CFSTR("rowid and other attributes are mutually exclusive")); - else { + } else { ok = kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { return s3dl_query_delete(dbt, q, accessGroups, error); }); @@ -1141,7 +1377,13 @@ _SecAddNegativeWebCredential(CFStringRef fqdn, CFStringRef appID, bool forSafari CFErrorRef error = NULL; CFStringRef accessGroup = CFSTR("*"); - CFArrayRef accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + SecurityClient client = { + .task = NULL, + .accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks), + .allowSystemKeychain = false, + .allowSyncBubbleKeychain = false, + .isNetworkExtension = false, + }; CFDictionaryAddValue(attrs, kSecClass, kSecClassInternetPassword); CFDictionaryAddValue(attrs, kSecAttrAccessGroup, kSecSafariAccessGroup); @@ -1150,7 +1392,7 @@ _SecAddNegativeWebCredential(CFStringRef fqdn, CFStringRef appID, bool forSafari CFDictionaryAddValue(attrs, kSecAttrServer, fqdn); CFDictionaryAddValue(attrs, kSecAttrSynchronizable, kCFBooleanTrue); - (void)_SecItemDelete(attrs, accessGroups, &error); + (void)_SecItemDelete(attrs, &client, &error); CFReleaseNull(error); CFDictionaryAddValue(attrs, kSecAttrAccount, kSecSafariPasswordsNotSaved); @@ -1171,12 +1413,12 @@ _SecAddNegativeWebCredential(CFStringRef fqdn, CFStringRef appID, bool forSafari } CFTypeRef addResult = NULL; - result = _SecItemAdd(attrs, accessGroups, &addResult, &error); + result = _SecItemAdd(attrs, &client, &addResult, &error); CFReleaseSafe(addResult); CFReleaseSafe(error); CFReleaseSafe(attrs); - CFReleaseSafe(accessGroups); + CFReleaseSafe(client.accessGroups); return result; } @@ -1190,6 +1432,8 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, CFTypeRef *result, CFErrorRef *error) { + SecurityClient client = {}; + CFStringRef fqdn = CFRetainSafe(CFDictionaryGetValue(attributes, kSecAttrServer)); CFStringRef account = CFRetainSafe(CFDictionaryGetValue(attributes, kSecAttrAccount)); #if TARGET_OS_IPHONE && !TARGET_OS_WATCH @@ -1198,7 +1442,6 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, CFStringRef password = CFRetainSafe(CFDictionaryGetValue(attributes, CFSTR("spwd"))); #endif CFStringRef accessGroup = CFSTR("*"); - CFArrayRef accessGroups = NULL; CFMutableDictionaryRef query = NULL, attrs = NULL; SInt32 port = -1; bool ok = false, update = false; @@ -1273,7 +1516,12 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, #endif // give ourselves access to see matching items for kSecSafariAccessGroup - accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + client.task = NULL; + client.accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + client.allowSystemKeychain = false; + client.allowSyncBubbleKeychain = false; + client.isNetworkExtension = false; + // create lookup query query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); @@ -1289,7 +1537,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, // check for presence of Safari's negative entry ('passwords not saved') CFDictionarySetValue(query, kSecAttrAccount, kSecSafariPasswordsNotSaved); - ok = _SecItemCopyMatching(query, accessGroups, result, error); + ok = _SecItemCopyMatching(query, &client, result, error); if(result) CFReleaseNull(*result); CFReleaseNull(*error); if (ok) { @@ -1307,7 +1555,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, } // look up existing password - if (_SecItemCopyMatching(query, accessGroups, result, error)) { + if (_SecItemCopyMatching(query, &client, result, error)) { // found it, so this becomes either an "update password" or "delete password" operation if(result) CFReleaseNull(*result); CFReleaseNull(*error); @@ -1324,7 +1572,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, ok = /*approved ||*/ swca_confirm_operation(swca_update_request_id, clientAuditToken, query, error, ^void (CFStringRef fqdn) { _SecAddNegativeWebCredential(fqdn, appID, false); }); if (ok) { - ok = _SecItemUpdate(query, attrs, accessGroups, error); + ok = _SecItemUpdate(query, attrs, &client, error); } } else { @@ -1333,7 +1581,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, ok = /*approved ||*/ swca_confirm_operation(swca_delete_request_id, clientAuditToken, query, error, ^void (CFStringRef fqdn) { _SecAddNegativeWebCredential(fqdn, appID, false); }); if (ok) { - ok = _SecItemDelete(query, accessGroups, error); + ok = _SecItemDelete(query, &client, error); } } if (ok) { @@ -1364,8 +1612,8 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, CFReleaseSafe(credential); CFDictionarySetValue(query, kSecAttrComment, kSecSafariDefaultComment); - CFReleaseSafe(accessGroups); - accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecSafariAccessGroup, 1, &kCFTypeArrayCallBacks); + CFReleaseSafe(client.accessGroups); + client.accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&kSecSafariAccessGroup, 1, &kCFTypeArrayCallBacks); // mark the item as created by this function const int32_t creator_value = 'swca'; @@ -1383,7 +1631,7 @@ _SecAddSharedWebCredential(CFDictionaryRef attributes, } } if (ok) { - ok = _SecItemAdd(query, accessGroups, result, error); + ok = _SecItemAdd(query, &client, result, error); } cleanup: @@ -1398,7 +1646,7 @@ cleanup: #endif CFReleaseSafe(attrs); CFReleaseSafe(query); - CFReleaseSafe(accessGroups); + CFReleaseSafe(client.accessGroups); CFReleaseSafe(fqdn); CFReleaseSafe(account); CFReleaseSafe(password); @@ -1417,7 +1665,6 @@ _SecCopySharedWebCredential(CFDictionaryRef query, CFMutableArrayRef credentials = NULL; CFMutableArrayRef foundItems = NULL; CFMutableArrayRef fqdns = NULL; - CFArrayRef accessGroups = NULL; CFStringRef fqdn = NULL; CFStringRef account = NULL; CFIndex idx, count; @@ -1431,7 +1678,13 @@ _SecCopySharedWebCredential(CFDictionaryRef query, // give ourselves access to see matching items for kSecSafariAccessGroup CFStringRef accessGroup = CFSTR("*"); - accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks); + SecurityClient client = { + .task = NULL, + .accessGroups = CFArrayCreate(kCFAllocatorDefault, (const void **)&accessGroup, 1, &kCFTypeArrayCallBacks), + .allowSystemKeychain = false, + .allowSyncBubbleKeychain = false, + .isNetworkExtension = false, + }; // On input, the query dictionary contains optional fqdn and account entries. fqdn = CFDictionaryGetValue(query, kSecAttrServer); @@ -1546,7 +1799,7 @@ _SecCopySharedWebCredential(CFDictionaryRef query, CFDictionaryAddValue(attrs, kSecReturnAttributes, kCFBooleanTrue); CFDictionaryAddValue(attrs, kSecReturnData, kCFBooleanTrue); - ok = _SecItemCopyMatching(attrs, accessGroups, (CFTypeRef*)&items, error); + ok = _SecItemCopyMatching(attrs, &client, (CFTypeRef*)&items, error); if (count > 1) { // ignore interim error since we have multiple domains to search CFReleaseNull(*error); @@ -1722,7 +1975,7 @@ cleanup: } CFReleaseSafe(foundItems); *result = credentials; - CFReleaseSafe(accessGroups); + CFReleaseSafe(client.accessGroups); CFReleaseSafe(fqdns); #if 0 /* debugging */ secerror("result=%s, copied items %@, error=%@", (ok) ? "true" : "false", *result, *error); @@ -1734,7 +1987,7 @@ cleanup: // MARK: Keychain backup CF_RETURNS_RETAINED CFDataRef -_SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { +_SecServerKeychainCreateBackup(SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { CFDataRef backup; SecDbConnectionRef dbt = SecDbConnectionAquire(kc_dbhandle(), false, error); @@ -1743,13 +1996,14 @@ _SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error if (keybag == NULL && passcode == NULL) { #if USE_KEYSTORE - backup = SecServerExportBackupableKeychain(dbt, KEYBAG_DEVICE, backup_keybag_handle, error); + backup = SecServerExportBackupableKeychain(dbt, client, KEYBAG_DEVICE, backup_keybag_handle, error); #else /* !USE_KEYSTORE */ + (void)client; SecError(errSecParam, error, CFSTR("Why are you doing this?")); backup = NULL; #endif /* USE_KEYSTORE */ } else { - backup = SecServerKeychainBackup(dbt, keybag, passcode, error); + backup = SecServerKeychainCreateBackup(dbt, client, keybag, passcode, error); } SecDbConnectionRelease(dbt); @@ -1758,13 +2012,13 @@ _SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error } bool -_SecServerKeychainRestore(CFDataRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { +_SecServerKeychainRestore(CFDataRef backup, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error) { if (backup == NULL || keybag == NULL) return SecError(errSecParam, error, CFSTR("backup or keybag missing")); __block bool ok = true; ok &= SecDbPerformWrite(kc_dbhandle(), error, ^(SecDbConnectionRef dbconn) { - ok = SecServerKeychainRestore(dbconn, backup, keybag, passcode, error); + ok = SecServerKeychainRestore(dbconn, client, backup, keybag, passcode, error); }); if (ok) { @@ -1969,6 +2223,7 @@ _SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef pa require_action_quiet(isData(keybag), errOut, ok = SecError(errSecParam, error, CFSTR("keybag %@ not a data"), keybag)); require_action_quiet(isDictionary(backup), errOut, ok = SecError(errSecParam, error, CFSTR("backup %@ not a dictionary"), backup)); if (password) { + require_action_quiet(isData(password), errOut, ok = SecError(errSecParam, error, CFSTR("password not a data"))); } @@ -1978,7 +2233,12 @@ errOut: return ok; } -bool _SecServerRollKeys(bool force, CFErrorRef *error) { +bool _SecServerRollKeysGlue(bool force, CFErrorRef *error) { + return _SecServerRollKeys(force, NULL, error); +} + + +bool _SecServerRollKeys(bool force, SecurityClient *client, CFErrorRef *error) { #if USE_KEYSTORE uint32_t keystore_generation_status = 0; if (aks_generation(KEYBAG_DEVICE, generation_noop, &keystore_generation_status)) @@ -1989,7 +2249,7 @@ bool _SecServerRollKeys(bool force, CFErrorRef *error) { bool up_to_date = s3dl_dbt_keys_current(dbt, current_generation, NULL); if (force && !up_to_date) { - up_to_date = s3dl_dbt_update_keys(dbt, error); + up_to_date = s3dl_dbt_update_keys(dbt, client, error); if (up_to_date) { secerror("Completed roll keys."); up_to_date = s3dl_dbt_keys_current(dbt, current_generation, NULL); @@ -2004,6 +2264,438 @@ bool _SecServerRollKeys(bool force, CFErrorRef *error) { #endif } +#if TARGET_OS_IOS + +/* + * Sync bubble migration code + */ + +struct SyncBubbleRule { + CFStringRef attribute; + CFTypeRef value; +}; + +static bool +TransmogrifyItemsToSyncBubble(SecurityClient *client, uid_t uid, + bool onlyDelete, + bool copyToo, + const SecDbClass *qclass, + struct SyncBubbleRule *items, CFIndex nItems, + CFErrorRef *error) +{ + CFMutableDictionaryRef updateAttributes = NULL; + CFDataRef syncBubbleView = NULL; + CFDataRef activeUserView = NULL; + bool res = false; + Query *q = NULL; + CFIndex n; + + syncBubbleView = SecMUSRCreateSyncBubbleUserUUID(uid); + require(syncBubbleView, fail); + + activeUserView = SecMUSRCreateActiveUserUUID(uid); + require(activeUserView, fail); + + + if ((onlyDelete && !copyToo) || !onlyDelete) { + + /* + * Clean out items first + */ + + secnotice("syncbubble", "cleaning out old items"); + + q = query_create(qclass, NULL, NULL, error); + require(q, fail); + + q->q_limit = kSecMatchUnlimited; + q->q_keybag = device_keybag_handle; + + for (n = 0; n < nItems; n++) { + query_add_attribute(items[n].attribute, items[n].value, q); + } + q->q_musrView = CFRetain(syncBubbleView); + require(q->q_musrView, fail); + + kc_with_dbt(false, error, ^(SecDbConnectionRef dbt) { + return kc_transaction(dbt, error, ^{ + return s3dl_query_delete(dbt, q, NULL, error); + }); + }); + + query_destroy(q, NULL); + q = NULL; + } + + + if (onlyDelete || !copyToo) { + secnotice("syncbubble", "skip migration of items"); + } else { + /* + * Copy over items from EMCS to sync bubble + */ + + secnotice("syncbubble", "migrating sync bubble items"); + + q = query_create(qclass, NULL, NULL, error); + require(q, fail); + + q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; + q->q_limit = kSecMatchUnlimited; + q->q_keybag = device_keybag_handle; /* XXX change to session key bag when it exists */ + + for (n = 0; n < nItems; n++) { + query_add_or_attribute(items[n].attribute, items[n].value, q); + } + query_add_or_attribute(CFSTR("musr"), activeUserView, q); + q->q_musrView = CFRetain(activeUserView); + + updateAttributes = CFDictionaryCreateMutableForCFTypes(NULL); + require(updateAttributes, fail); + + CFDictionarySetValue(updateAttributes, CFSTR("musr"), syncBubbleView); /* XXX should use kSecAttrMultiUser */ + + + kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { + return kc_transaction(dbt, error, ^{ + CFErrorRef error2 = NULL; + + SecDbItemSelect(q, dbt, &error2, NULL, ^bool(const SecDbAttr *attr) { + return CFDictionaryGetValue(q->q_item, attr->name); + }, NULL, NULL, ^(SecDbItemRef item, bool *stop) { + CFErrorRef error3 = NULL; + secinfo("syncbubble", "migrating item"); + + SecDbItemRef new_item = SecDbItemCopyWithUpdates(item, updateAttributes, NULL); + if (new_item == NULL) + return; + + SecDbItemClearRowId(new_item, NULL); + + if (!SecDbItemSetKeybag(new_item, device_keybag_handle, NULL)) { + CFRelease(new_item); + return; + } + + if (!SecDbItemInsert(new_item, dbt, &error3)) { + secnotice("syncbubble", "migration failed with %@ for item %@", error3, new_item); + } + CFRelease(new_item); + CFReleaseNull(error3); + }); + CFReleaseNull(error2); + + return (bool)true; + }); + }); + } + res = true; + +fail: + CFReleaseNull(syncBubbleView); + CFReleaseNull(activeUserView); + CFReleaseNull(updateAttributes); + if (q) + query_destroy(q, NULL); + + return res; +} + +static struct SyncBubbleRule PCSItems[] = { + { + .attribute = CFSTR("agrp"), + .value = CFSTR("com.apple.ProtectedCloudStorage"), + } +}; +static struct SyncBubbleRule NSURLSesssiond[] = { + { + .attribute = CFSTR("agrp"), + .value = CFSTR("com.apple.nsurlsessiond"), + } +}; +static struct SyncBubbleRule AccountsdItems[] = { + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.AppleAccount.token"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.AppleAccount.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.AppleAccount.rpassword"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.idms.token"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.idms.continuation-key"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.CloudKit.token"), + }, +}; + +static struct SyncBubbleRule MobileMailItems[] = { + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.IMAP.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.SMTP.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Exchange.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Hotmail.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Google.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Google.oauth-token"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Google.oath-refresh-token"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Yahoo.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Yahoo.oauth-token"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Yahoo.oauth-token-nosync"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.Yahoo.oath-refresh-token"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.IMAPNotes.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.IMAPMail.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.126.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.163.password"), + }, + { + .attribute = CFSTR("svce"), + .value = CFSTR("com.apple.account.aol.password"), + }, +}; + +static bool +ArrayContains(CFArrayRef array, CFStringRef service) +{ + return CFArrayContainsValue(array, CFRangeMake(0, CFArrayGetCount(array)), service); +} + +bool +_SecServerTransmogrifyToSyncBubble(CFArrayRef services, uid_t uid, SecurityClient *client, CFErrorRef *error) +{ + bool copyCloudAuthToken = false; + bool copyMobileMail = false; + bool res = true; + bool copyPCS = false; + bool onlyDelete = false; + bool copyNSURLSesssion = false; + + if (!client->inMultiUser) + return false; + + secnotice("syncbubble", "migration for uid %d uid for services %@", (int)uid, services); + +#if TARGET_OS_SIMULATOR + // no delete in sim +#elif TARGET_OS_IOS + if (uid != (uid_t)client->activeUser) + onlyDelete = true; +#else +#error "no sync bubble on other platforms" +#endif + + /* + * First select that services to copy/delete + */ + + if (ArrayContains(services, CFSTR("com.apple.bird.usermanager.sync")) + || ArrayContains(services, CFSTR("com.apple.cloudphotod.sync")) + || ArrayContains(services, CFSTR("com.apple.cloudphotod.syncstakeholder")) + || ArrayContains(services, CFSTR("com.apple.cloudd.usermanager.sync"))) + { + copyCloudAuthToken = true; + copyPCS = true; + } + + if (ArrayContains(services, CFSTR("com.apple.nsurlsessiond.usermanager.sync"))) + { + copyCloudAuthToken = true; + copyNSURLSesssion = true; + } + + if (ArrayContains(services, CFSTR("com.apple.syncdefaultsd.usermanager.sync"))) { + copyCloudAuthToken = true; + } + if (ArrayContains(services, CFSTR("com.apple.mailq.sync")) || ArrayContains(services, CFSTR("com.apple.mailq.sync.xpc"))) { + copyCloudAuthToken = true; + copyMobileMail = true; + copyPCS = true; + } + + /* + * The actually copy/delete the items selected + */ + + res = TransmogrifyItemsToSyncBubble(client, uid, onlyDelete, copyPCS, &inet_class, PCSItems, sizeof(PCSItems)/sizeof(PCSItems[0]), error); + require(res, fail); + res = TransmogrifyItemsToSyncBubble(client, uid, onlyDelete, copyPCS, &genp_class, PCSItems, sizeof(PCSItems)/sizeof(PCSItems[0]), error); + require(res, fail); + + /* mail */ + res = TransmogrifyItemsToSyncBubble(client, uid, onlyDelete, copyMobileMail, &genp_class, MobileMailItems, sizeof(MobileMailItems)/sizeof(MobileMailItems[0]), error); + require(res, fail); + + /* accountsd */ + res = TransmogrifyItemsToSyncBubble(client, uid, onlyDelete, copyCloudAuthToken, &genp_class, AccountsdItems, sizeof(AccountsdItems)/sizeof(AccountsdItems[0]), error); + require(res, fail); + + /* nsurlsessiond */ + res = TransmogrifyItemsToSyncBubble(client, uid, onlyDelete, copyNSURLSesssion, &inet_class, NSURLSesssiond, sizeof(NSURLSesssiond)/sizeof(NSURLSesssiond[0]), error); + require(res, fail); + +fail: + return res; +} + +/* + * Migrate from user keychain to system keychain when switching to edu mode + */ + +bool +_SecServerTransmogrifyToSystemKeychain(SecurityClient *client, CFErrorRef *error) +{ + __block bool ok = true; + + /* + * we are not in multi user yet, about to switch, otherwise we would + * check that for client->inMultiuser here + */ + + kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { + return kc_transaction(dbt, error, ^{ + CFDataRef systemUUID = SecMUSRGetSystemKeychainUUID(); + + const SecDbSchema *newSchema = kc_schemas[0]; + SecDbClass const *const *kcClass; + + for (kcClass = newSchema->classes; *kcClass != NULL; kcClass++) { + CFErrorRef localError = NULL; + Query *q = NULL; + + if (*kcClass == &tversion_class || *kcClass == &identity_class) + continue; + + q = query_create(*kcClass, SecMUSRGetSingleUserKeychainUUID(), NULL, error); + if (q == NULL) + continue; + + ok &= SecDbItemSelect(q, dbt, error, ^bool(const SecDbAttr *attr) { + return (attr->flags & kSecDbInFlag) != 0; + }, ^bool(const SecDbAttr *attr) { + // No filtering please. + return false; + }, ^bool(CFMutableStringRef sql, bool *needWhere) { + SecDbAppendWhereOrAnd(sql, needWhere); + CFStringAppendFormat(sql, NULL, CFSTR("musr = ?")); + return true; + }, ^bool(sqlite3_stmt *stmt, int col) { + return SecDbBindObject(stmt, col++, SecMUSRGetSingleUserKeychainUUID(), error); + }, ^(SecDbItemRef item, bool *stop) { + CFErrorRef localError = NULL; + + if (!SecDbItemSetValueWithName(item, kSecAttrMultiUser, systemUUID, &localError)) { + secerror("item: %@ update musr to system failed: %@", item, localError); + ok = false; + goto out; + } + + if (!SecDbItemDoUpdate(item, item, dbt, &localError, ^bool (const SecDbAttr *attr) { + return attr->kind == kSecDbRowIdAttr; + })) { + secerror("item: %@ insert during UPDATE: %@", item, localError); + ok = false; + goto out; + } + + out: + SecErrorPropagate(localError, error); + CFReleaseSafe(localError); + }); + + if (q) + query_destroy(q, &localError); + + } + return (bool)true; + }); + }); + + return ok; +} + +/* + * Migrate from user keychain to system keychain when switching to edu mode + */ + +bool +_SecServerDeleteMUSERViews(SecurityClient *client, uid_t uid, CFErrorRef *error) +{ + return kc_with_dbt(true, error, ^(SecDbConnectionRef dbt) { + CFDataRef musrView = NULL, syncBubbleView = NULL; + bool ok = false; + + syncBubbleView = SecMUSRCreateSyncBubbleUserUUID(uid); + require(syncBubbleView, fail); + + musrView = SecMUSRCreateActiveUserUUID(uid); + require(musrView, fail); + + require(ok = SecServerDeleteAllForUser(dbt, syncBubbleView, error), fail); + require(ok = SecServerDeleteAllForUser(dbt, musrView, error), fail); + + fail: + CFReleaseNull(syncBubbleView); + CFReleaseNull(musrView); + return ok; + }); +} + + +#endif /* TARGET_OS_IOS */ + bool _SecServerGetKeyStats(const SecDbClass *qclass, struct _SecServerKeyStats *stats) @@ -2011,7 +2703,7 @@ _SecServerGetKeyStats(const SecDbClass *qclass, __block CFErrorRef error = NULL; bool res = false; - Query *q = query_create(qclass, NULL, &error); + Query *q = query_create(qclass, NULL, NULL, &error); require(q, fail); q->q_return_type = kSecReturnDataMask | kSecReturnAttributesMask; diff --git a/OSX/sec/securityd/SecItemServer.h b/OSX/sec/securityd/SecItemServer.h index de9f4a19..4bc57b94 100644 --- a/OSX/sec/securityd/SecItemServer.h +++ b/OSX/sec/securityd/SecItemServer.h @@ -34,18 +34,21 @@ #include #include #include +#include +#include "securityd_client.h" + __BEGIN_DECLS -bool _SecItemAdd(CFDictionaryRef attributes, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); -bool _SecItemCopyMatching(CFDictionaryRef query, CFArrayRef accessGroups, CFTypeRef *result, CFErrorRef *error); -bool _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, CFArrayRef accessGroups, CFErrorRef *error); -bool _SecItemDelete(CFDictionaryRef query, CFArrayRef accessGroups, CFErrorRef *error); +bool _SecItemAdd(CFDictionaryRef attributes, SecurityClient *client, CFTypeRef *result, CFErrorRef *error); +bool _SecItemCopyMatching(CFDictionaryRef query, SecurityClient *client, CFTypeRef *result, CFErrorRef *error); +bool _SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate, SecurityClient *client, CFErrorRef *error); +bool _SecItemDelete(CFDictionaryRef query, SecurityClient *client, CFErrorRef *error); bool _SecItemDeleteAll(CFErrorRef *error); bool _SecServerRestoreKeychain(CFErrorRef *error); bool _SecServerMigrateKeychain(int32_t handle_in, CFDataRef data_in, int32_t *handle_out, CFDataRef *data_out, CFErrorRef *error); -CF_RETURNS_RETAINED CFDataRef _SecServerKeychainBackup(CFDataRef keybag, CFDataRef passcode, CFErrorRef *error); -bool _SecServerKeychainRestore(CFDataRef backup, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error); +CFDataRef _SecServerKeychainCreateBackup(SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error); +bool _SecServerKeychainRestore(CFDataRef backup, SecurityClient *client, CFDataRef keybag, CFDataRef passcode, CFErrorRef *error); CF_RETURNS_RETAINED CFArrayRef _SecServerKeychainSyncUpdateMessage(CFDictionaryRef updates, CFErrorRef *error); bool _SecServerKeychainSyncUpdateIDSMessage(CFDictionaryRef updates, CFErrorRef *error); @@ -55,6 +58,12 @@ int SecServerKeychainTakeOverBackupFD(CFStringRef backupName, CFErrorRef *error) bool _SecServerRestoreSyncable(CFDictionaryRef backup, CFDataRef keybag, CFDataRef password, CFErrorRef *error); +#if TARGET_OS_IOS +bool _SecServerTransmogrifyToSystemKeychain(SecurityClient *client, CFErrorRef *error); +bool _SecServerTransmogrifyToSyncBubble(CFArrayRef services, uid_t uid, SecurityClient *client, CFErrorRef *error); +bool _SecServerDeleteMUSERViews(SecurityClient *client, uid_t uid, CFErrorRef *error); +#endif + bool _SecAddSharedWebCredential(CFDictionaryRef attributes, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error); bool _SecCopySharedWebCredential(CFDictionaryRef query, const audit_token_t *clientAuditToken, CFStringRef appID, CFArrayRef domains, CFTypeRef *result, CFErrorRef *error); @@ -63,6 +72,11 @@ void SecItemServerAppendItemDescription(CFMutableStringRef desc, CFDictionaryRef SecDbRef SecKeychainDbCreate(CFStringRef path); + +/* For whitebox testing only */ +void SecKeychainDbReset(dispatch_block_t inbetween); + + SOSDataSourceFactoryRef SecItemDataSourceFactoryGetDefault(void); /* FIXME: there is a specific type for keybag handle (keybag_handle_t) @@ -74,7 +88,8 @@ void SecItemServerSetKeychainChangedNotification(const char *notification_name); CFStringRef __SecKeychainCopyPath(void); -bool _SecServerRollKeys(bool force, CFErrorRef *error); +bool _SecServerRollKeys(bool force, SecurityClient *client, CFErrorRef *error); +bool _SecServerRollKeysGlue(bool force, CFErrorRef *error); struct _SecServerKeyStats { unsigned long items; diff --git a/OSX/sec/securityd/SecKeybagSupport.c b/OSX/sec/securityd/SecKeybagSupport.c index 6a48f4ac..e22897b7 100644 --- a/OSX/sec/securityd/SecKeybagSupport.c +++ b/OSX/sec/securityd/SecKeybagSupport.c @@ -43,6 +43,9 @@ #endif #endif /* USE_KEYSTORE */ +#include +#include + /* g_keychain_handle is the keybag handle used for encrypting item in the keychain. For testing purposes, it can be set to something other than the default, with SecItemServerSetKeychainKeybag */ @@ -469,3 +472,4 @@ bool ks_close_keybag(keybag_handle_t keybag, CFErrorRef *error) { #endif /* USE_KEYSTORE */ return true; } + diff --git a/OSX/sec/securityd/SecPolicyServer.c b/OSX/sec/securityd/SecPolicyServer.c index cfcc825d..46257024 100644 --- a/OSX/sec/securityd/SecPolicyServer.c +++ b/OSX/sec/securityd/SecPolicyServer.c @@ -1083,6 +1083,8 @@ static void SecPolicyCheckAnchorApple(SecPVCRef pvc, if (isDictionary(value)) { if (CFDictionaryGetValue(value, kSecPolicyAppleAnchorIncludeTestRoots)) flags |= kSecAppleTrustAnchorFlagsIncludeTestAnchors; + if (CFDictionaryGetValue(value, kSecPolicyAppleAnchorAllowTestRootsOnProduction)) + flags |= kSecAppleTrustAnchorFlagsAllowNonProduction; } bool foundMatch = SecIsAppleTrustAnchor(cert, flags); @@ -1616,6 +1618,11 @@ static void SecPolicyCheckBasicCertificateProcessing(SecPVCRef pvc, if (!SecPVCSetResult(pvc, fail_key, n - i, kCFBooleanFalse)) return; } + if (SecCertificateIsWeak(cert)) { + CFStringRef fail_key = i == n ? kSecPolicyCheckWeakLeaf : kSecPolicyCheckWeakIntermediates; + if (!SecPVCSetResult(pvc, fail_key, n - i, kCFBooleanFalse)) + return; + } #endif #if 0 /* Check revocation status if the certificate asks for it. */ @@ -2320,7 +2327,7 @@ static void SecPolicyCheckCT(SecPVCRef pvc, CFStringRef key) require(operatorsValidatingExternalScts, out); if(trustedLogs) { // Don't bother trying to validate SCTs if we don't have any trusted logs. - if(embeddedScts) { + if(embeddedScts && precertEntry) { // Don't bother if we could not get the precert. CFArrayForEach(embeddedScts, ^(const void *value){ bool validLogAtVerifyTime = false; CFStringRef operator = get_valid_sct_operator(value, 1, precertEntry, pvc->verifyTime, SecCertificateNotValidBefore(leafCert), trustedLogs, &validLogAtVerifyTime); @@ -2329,7 +2336,7 @@ static void SecPolicyCheckCT(SecPVCRef pvc, CFStringRef key) }); } - if(builderScts) { + if(builderScts && x509Entry) { // Don't bother if we could not get the cert. CFArrayForEach(builderScts, ^(const void *value){ bool validLogAtVerifyTime = false; CFStringRef operator = get_valid_sct_operator(value, 0, x509Entry, pvc->verifyTime, SecCertificateNotValidBefore(leafCert), trustedLogs, &validLogAtVerifyTime); @@ -2338,7 +2345,7 @@ static void SecPolicyCheckCT(SecPVCRef pvc, CFStringRef key) }); } - if(ocspScts) { + if(ocspScts && x509Entry) { CFArrayForEach(ocspScts, ^(const void *value){ bool validLogAtVerifyTime = false; CFStringRef operator = get_valid_sct_operator(value, 0, x509Entry, pvc->verifyTime, SecCertificateNotValidBefore(leafCert), trustedLogs, &validLogAtVerifyTime); @@ -2445,6 +2452,41 @@ static void SecPolicyCheckNoNetworkAccess(SecPVCRef pvc, SecPathBuilderSetCanAccessNetwork(pvc->builder, false); } +static void SecPolicyCheckWeakIntermediates(SecPVCRef pvc, + CFStringRef key) { + CFIndex ix, count = SecPVCGetCertificateCount(pvc); + for (ix = 1; ix < count - 1; ++ix) { + SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); + if (cert && SecCertificateIsWeak(cert)) { + /* Intermediate certificate has a weak key. */ + if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse)) + return; + } + } +} + +static void SecPolicyCheckWeakLeaf(SecPVCRef pvc, + CFStringRef key) { + SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0); + if (cert && SecCertificateIsWeak(cert)) { + /* Leaf certificate has a weak key. */ + if (!SecPVCSetResult(pvc, key, 0, kCFBooleanFalse)) + return; + } +} + +static void SecPolicyCheckWeakRoot(SecPVCRef pvc, + CFStringRef key) { + CFIndex ix, count = SecPVCGetCertificateCount(pvc); + ix = count - 1; + SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix); + if (cert && SecCertificateIsWeak(cert)) { + /* Root certificate has a weak key. */ + if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse)) + return; + } +} + // MARK: - // MARK: SecRVCRef /******************************************************** @@ -2882,11 +2924,12 @@ static bool SecPVCCheckRevocation(SecPVCRef pvc) { secdebug("ocsp", "Checking cached responses for cert %ld", certIX); SecRVCConsumeOCSPResponse(rvc, SecOCSPCacheCopyMatching(rvc->ocspRequest, NULL), NULL_TIME, false); - /* Unless we successfully checked the revocation status of this cert - based on the cache or stapled responses, attempt to fire off an async http request - for this cert's revocation status. */ + /* If the cert is EV or if revocation checking was explicitly enabled, attempt to fire off an + async http request for this cert's revocation status, unless we already successfully checked + the revocation status of this cert based on the cache or stapled responses, */ + bool allow_fetch = SecPathBuilderCanAccessNetwork(pvc->builder) && (pvc->is_ev || pvc->check_revocation); bool fetch_done = true; - if (rvc->done || !SecPathBuilderCanAccessNetwork(pvc->builder) || + if (rvc->done || !allow_fetch || (fetch_done = SecRVCFetchNext(rvc))) { /* We got a cache hit or we aren't allowed to access the network, or the async http post failed. */ @@ -3015,6 +3058,15 @@ void SecPolicyServerInitalize(void) { CFDictionaryAddValue(gSecPolicyLeafCallbacks, kSecPolicyCheckCertificatePolicy, SecPolicyCheckCertificatePolicyOid); + CFDictionaryAddValue(gSecPolicyPathCallbacks, + kSecPolicyCheckWeakIntermediates, + SecPolicyCheckWeakIntermediates); + CFDictionaryAddValue(gSecPolicyLeafCallbacks, + kSecPolicyCheckWeakLeaf, + SecPolicyCheckWeakLeaf); + CFDictionaryAddValue(gSecPolicyPathCallbacks, + kSecPolicyCheckWeakRoot, + SecPolicyCheckWeakRoot); } /* AUDIT[securityd](done): @@ -3287,6 +3339,13 @@ bool SecPVCParentCertificateChecks(SecPVCRef pvc, CFIndex ix) { goto errOut; } + if (SecCertificateIsWeak(cert)) { + /* Certificate uses weak key. */ + if (!SecPVCSetResult(pvc, is_anchor ? kSecPolicyCheckWeakRoot + : kSecPolicyCheckWeakIntermediates, ix, kCFBooleanFalse)) + goto errOut; + } + if (is_anchor) { /* Perform anchor specific checks. */ /* Don't think we have any of these. */ @@ -3423,10 +3482,10 @@ bool SecPVCPathChecks(SecPVCRef pvc) { as a non EV one, if it was valid as such. */ pvc->result = pre_ev_check_result; } - /* Check revocation only if the chain is valid so far. Then only check - revocation if the client asked for it explicitly or is_ev is - true. */ - if (pvc->result && (pvc->is_ev || pvc->check_revocation)) { + /* Check revocation only if the chain is valid so far. The revocation will + only fetch OCSP response over the network if the client asked for revocation + check explicitly or is_ev is true. */ + if (pvc->result) { completed = SecPVCCheckRevocation(pvc); } diff --git a/OSX/sec/securityd/SecTrustServer.c b/OSX/sec/securityd/SecTrustServer.c index 5a135130..e3e17cb6 100644 --- a/OSX/sec/securityd/SecTrustServer.c +++ b/OSX/sec/securityd/SecTrustServer.c @@ -277,9 +277,17 @@ static bool SecItemCertificateSourceCopyParents( CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 4, NULL, NULL); CFTypeRef results = NULL; + SecurityClient client = { + .task = NULL, + .accessGroups = msource->accessGroups, + .allowSystemKeychain = true, + .allowSyncBubbleKeychain = false, + .isNetworkExtension = false, + }; + /* We can make this async or run this on a queue now easily. */ CFErrorRef localError = NULL; - if (!_SecItemCopyMatching(query, msource->accessGroups, &results, &localError)) { + if (!_SecItemCopyMatching(query, &client, &results, &localError)) { if (CFErrorGetCode(localError) != errSecItemNotFound) { secdebug("trust", "_SecItemCopyMatching: %@", localError); } @@ -317,11 +325,18 @@ static bool SecItemCertificateSourceContains(SecCertificateSourceRef source, normalizedSubject, serialNumber }; + SecurityClient client = { + .task = NULL, + .accessGroups = msource->accessGroups, + .allowSystemKeychain = true, + .allowSyncBubbleKeychain = false, + .isNetworkExtension = false, + }; CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 5, NULL, NULL); CFErrorRef localError = NULL; CFTypeRef results = NULL; - bool ok = _SecItemCopyMatching(query, msource->accessGroups, &results, &localError); + bool ok = _SecItemCopyMatching(query, &client, &results, &localError); CFRelease(query); CFRelease(serialNumber); CFReleaseSafe(results); diff --git a/OSX/sec/securityd/entitlements.plist b/OSX/sec/securityd/entitlements.plist index 5b29ab98..a88a3458 100644 --- a/OSX/sec/securityd/entitlements.plist +++ b/OSX/sec/securityd/entitlements.plist @@ -18,5 +18,7 @@ com.apple.private.network.socket-delegate + com.apple.mkb.usersession.info + diff --git a/OSX/sec/securityd/iCloudTrace.c b/OSX/sec/securityd/iCloudTrace.c index 363aaff3..8a19f191 100644 --- a/OSX/sec/securityd/iCloudTrace.c +++ b/OSX/sec/securityd/iCloudTrace.c @@ -34,64 +34,15 @@ #include #endif #include +#include -/* -------------------------------------------------------------------------- - Function: Bucket - - Description: In order to preserve annominity of a user, take an - absolute value and return back the most significant - value in base 10 - -------------------------------------------------------------------------- */ -static int64_t Bucket(int64_t value) -{ - if (value < 10) - { - return value; - } - - if (value < 100) - { - return (value / 10) * 10; - } - - if (value < 1000) - { - return (value / 100) * 100; - } - - if (value < 10000) - { - return (value / 1000) * 1000; - } - - if (value < 100000) - { - return (value / 10000) * 10000; - } - - if (value < 1000000) - { - return (value / 100000) * 10000; - } - - return value; -} - -static int64_t -Bucket2Significant(int64_t value) -{ - if (value < 100) - return value; - return 10 * Bucket2Significant(value / 10); -} - static void TraceKeyClassItem(void *token, CFStringRef keyclass, CFStringRef name, int64_t num) { CFStringRef key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@.%@"), keyclass, name); if (key) { - num = Bucket2Significant(num); + num = SecBucket2Significant(num); AddKeyValuePairToKeychainLoggingTransaction(token, key, num); CFReleaseNull(key); } @@ -119,7 +70,7 @@ void CloudKeychainTrace(CFIndex num_peers, size_t num_items, { void *token = BeginCloudKeychainLoggingTransaction(); AddKeyValuePairToKeychainLoggingTransaction(token, kNumberOfiCloudKeychainPeers, (int64_t)num_peers); - AddKeyValuePairToKeychainLoggingTransaction(token, kNumberOfiCloudKeychainItemsBeingSynced, Bucket((int64_t)num_items)); + AddKeyValuePairToKeychainLoggingTransaction(token, kNumberOfiCloudKeychainItemsBeingSynced, SecBucket1Significant((int64_t)num_items)); TraceKeyClass(token, CFSTR("genp"), genpStats); TraceKeyClass(token, CFSTR("inet"), inetStats); TraceKeyClass(token, CFSTR("keys"), keysStats); diff --git a/OSX/sec/securityd/spi.c b/OSX/sec/securityd/spi.c index 25abfd70..4acf2b6e 100644 --- a/OSX/sec/securityd/spi.c +++ b/OSX/sec/securityd/spi.c @@ -54,7 +54,7 @@ static struct securityd spi = { .sec_truststore_remove_all = _SecTrustStoreRemoveAll, .sec_item_delete_all = _SecItemDeleteAll, .sec_trust_evaluate = SecTrustServerEvaluate, - .sec_keychain_backup = _SecServerKeychainBackup, + .sec_keychain_backup = _SecServerKeychainCreateBackup, .sec_keychain_restore = _SecServerKeychainRestore, .sec_keychain_backup_syncable = _SecServerBackupSyncable, .sec_keychain_restore_syncable = _SecServerRestoreSyncable, @@ -105,7 +105,7 @@ static struct securityd spi = { .sec_ota_pki_get_new_asset = SecOTAPKISignalNewAsset, .soscc_ProcessSyncWithAllPeers = SOSCCProcessSyncWithAllPeers_Server, .soscc_EnsurePeerRegistration = SOSCCProcessEnsurePeerRegistration_Server, - .sec_roll_keys = _SecServerRollKeys, + .sec_roll_keys = _SecServerRollKeysGlue, .soscc_CopyDeviceID = SOSCCCopyDeviceID_Server, .soscc_SetDeviceID = SOSCCSetDeviceID_Server, .soscc_CheckIDSRegistration = SOSCCIDSServiceRegistrationTest_Server, @@ -126,7 +126,11 @@ static struct securityd spi = { .soscc_SetEscrowRecords = SOSCCSetEscrowRecord_Server, .soscc_CopyEscrowRecords = SOSCCCopyEscrowRecord_Server, .soscc_PeerAvailability = SOSCCCheckPeerAvailability_Server, - + .sosbskb_WrapToBackupSliceKeyBagForView = SOSWrapToBackupSliceKeyBagForView_Server, + .soscc_CopyAccountState = SOSCCCopyAccountState_Server, + .soscc_DeleteAccountState = SOSCCDeleteAccountState_Server, + .soscc_CopyEngineData = SOSCCCopyEngineData_Server, + .soscc_DeleteEngineState = SOSCCDeleteEngineState_Server, }; void securityd_init_server(void) { diff --git a/OSX/sectests/SecurityTests-Entitlements.plist b/OSX/sectests/SecurityTests-Entitlements.plist index 753bee02..dd8eb5fb 100644 --- a/OSX/sectests/SecurityTests-Entitlements.plist +++ b/OSX/sectests/SecurityTests-Entitlements.plist @@ -12,6 +12,8 @@ migrate-keychain + com.apple.private.system-keychain + modify-anchor-certificates com.apple.springboard.wipedevice diff --git a/OSX/sectests/testlist.h b/OSX/sectests/testlist.h index 26ae9f35..2561235f 100644 --- a/OSX/sectests/testlist.h +++ b/OSX/sectests/testlist.h @@ -3,5 +3,6 @@ #include #include #include +#include diff --git a/OSX/security2/sub_commands.h b/OSX/security2/sub_commands.h index e018521e..36fbe7b5 100644 --- a/OSX/security2/sub_commands.h +++ b/OSX/security2/sub_commands.h @@ -25,4 +25,5 @@ // This file can't be once, it gets included multiple times to get definitions and declarations. #include "Security/Tool/SecurityCommands.h" -#include "SOSCircle/Tool/SOSCommands.h" +#include "SOSCircle/Tool/keychain_sync.h" +#include "SOSCircle/Tool/keychain_log.h" diff --git a/OSX/utilities/Regressions/su-41-secdb-stress.c b/OSX/utilities/Regressions/su-41-secdb-stress.c index 27f409fb..a31995e0 100644 --- a/OSX/utilities/Regressions/su-41-secdb-stress.c +++ b/OSX/utilities/Regressions/su-41-secdb-stress.c @@ -205,7 +205,9 @@ static void tests(void) dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_semaphore_t sema = dispatch_semaphore_create(50); // use semaphore so we dont end all threads an deadlock for (size_t job=0; job < 1000; ++job) { + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_group_async(group, queue, ^{ CFIndex cur_idle = SecDbIdleConnectionCount(db); dispatch_sync(count_queue, ^{ if (max_idle < cur_idle) max_idle = cur_idle; }); @@ -225,6 +227,7 @@ static void tests(void) }), "read %@", performError); } CFReleaseNull(performError); + dispatch_semaphore_signal(sema); }); } dispatch_group_wait(group, DISPATCH_TIME_FOREVER); diff --git a/OSX/utilities/SecurityTool/security_tool_commands.h b/OSX/utilities/SecurityTool/security_tool_commands.h index 7e01dfc6..78ad8e3a 100644 --- a/OSX/utilities/SecurityTool/security_tool_commands.h +++ b/OSX/utilities/SecurityTool/security_tool_commands.h @@ -34,7 +34,7 @@ #define SECURITY_COMMAND_IOS(name, function, parameters, description) extern int command_not_on_this_platform(int argc, char * const *argv); #endif -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) +#if !TARGET_OS_IPHONE #define SECURITY_COMMAND_MAC(name, function, parameters, description) int function(int argc, char * const *argv); #else #define SECURITY_COMMAND_MAC(name, function, parameters, description) extern int command_not_on_this_platform(int argc, char * const *argv); diff --git a/OSX/utilities/src/SecAKSWrappers.c b/OSX/utilities/src/SecAKSWrappers.c index 83bed63d..77d2ea91 100644 --- a/OSX/utilities/src/SecAKSWrappers.c +++ b/OSX/utilities/src/SecAKSWrappers.c @@ -42,36 +42,34 @@ # error "unsupported target platform" #endif +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && TARGET_HAS_KEYSTORE + // OS X +const keybag_handle_t keybagHandle = session_keybag_handle; +#elif TARGET_HAS_KEYSTORE // iOS, but not simulator +const keybag_handle_t keybagHandle = device_keybag_handle; +#endif + +#if TARGET_HAS_KEYSTORE +const AKSAssertionType_t lockAssertType = kAKSAssertTypeOther; +#endif + +CFGiblisGetSingleton(dispatch_queue_t, GetKeybagAssertionQueue, sUserKeyBagAssertionLockQueue, ^{ + *sUserKeyBagAssertionLockQueue = dispatch_queue_create("AKS Lock Assertion Queue", NULL); +}) + +#if TARGET_HAS_KEYSTORE +static uint32_t count = 0; +#endif const char * const kUserKeybagStateChangeNotification = change_notification; -bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action) -{ +bool SecAKSLockUserKeybag(uint64_t timeout, CFErrorRef *error){ #if !TARGET_HAS_KEYSTORE - action(); return true; #else - // Acquire lock assertion, ref count? - __block kern_return_t status = kIOReturnSuccess; - static dispatch_once_t queue_once; - static dispatch_queue_t assertion_queue; - -#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED // OS X - keybag_handle_t keybagHandle = session_keybag_handle; -#else // iOS, but not simulator - keybag_handle_t keybagHandle = device_keybag_handle; -#endif - AKSAssertionType_t lockAssertType = kAKSAssertTypeOther; - dispatch_once(&queue_once, ^{ - assertion_queue = dispatch_queue_create("AKS Lock Assertion Queue", NULL); - }); - - static uint32_t count = 0; - - dispatch_sync(assertion_queue, ^{ + dispatch_sync(GetKeybagAssertionQueue(), ^{ if (count == 0) { - uint64_t timeout = 60ull; secnotice("lockassertions", "Requesting lock assertion for %lld seconds", timeout); status = aks_assert_hold(keybagHandle, lockAssertType, timeout); } @@ -79,17 +77,43 @@ bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action) if (status == kIOReturnSuccess) ++count; }); + return SecKernError(status, error, CFSTR("Kern return error")); +#endif /* !TARGET_HAS_KEYSTORE */ +} + +bool SecAKSUnLockUserKeybag(CFErrorRef *error){ +#if !TARGET_HAS_KEYSTORE + return true; +#else + __block kern_return_t status = kIOReturnSuccess; + + dispatch_sync(GetKeybagAssertionQueue(), ^{ + if (count && (--count == 0)) { + secnotice("lockassertions", "Dropping lock assertion"); + status = aks_assert_drop(keybagHandle, lockAssertType); + } + }); - if (status == kIOReturnSuccess) { + return SecKernError(status, error, CFSTR("Kern return error")); +#endif /* !TARGET_HAS_KEYSTORE */ +} + + +bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action) +{ +#if !TARGET_HAS_KEYSTORE + action(); + return true; +#else + // Acquire lock assertion, ref count? + + bool status = false; + uint64_t timeout = 60ull; + if (SecAKSLockUserKeybag(timeout, error)) { action(); - dispatch_sync(assertion_queue, ^{ - if (count && (--count == 0)) { - secnotice("lockassertions", "Dropping lock assertion"); - status = aks_assert_drop(keybagHandle, lockAssertType); - } - }); + status = SecAKSUnLockUserKeybag(error); } - return SecKernError(status, error, CFSTR("Kern return error")); + return status; #endif /* !TARGET_HAS_KEYSTORE */ } diff --git a/OSX/utilities/src/SecAKSWrappers.h b/OSX/utilities/src/SecAKSWrappers.h index fd855ce3..b4a7ad23 100644 --- a/OSX/utilities/src/SecAKSWrappers.h +++ b/OSX/utilities/src/SecAKSWrappers.h @@ -128,6 +128,14 @@ static inline bool SecAKSGetHasBeenUnlocked(bool* hasBeenUnlocked, CFErrorRef* e bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action); +// +// if you can't use the block version above, use these. +// !!!!!Remember to balance them!!!!!! +// +bool SecAKSUnLockUserKeybag(CFErrorRef *error); +bool SecAKSLockUserKeybag(uint64_t timeout, CFErrorRef *error); + + CFDataRef SecAKSCopyBackupBagWithSecret(size_t size, uint8_t *secret, CFErrorRef *error); #endif diff --git a/OSX/utilities/src/SecAppleAnchor.c b/OSX/utilities/src/SecAppleAnchor.c index 1a83d100..6384e9fd 100644 --- a/OSX/utilities/src/SecAppleAnchor.c +++ b/OSX/utilities/src/SecAppleAnchor.c @@ -16,7 +16,7 @@ bool SecIsAppleTrustAnchorData(CFDataRef cert, SecAppleTrustAnchorFlags flags) { - CFDictionaryRef anchors; + CFDictionaryRef anchors = NULL; CFTypeRef value = NULL; bool res = false; @@ -24,11 +24,12 @@ SecIsAppleTrustAnchorData(CFDataRef cert, require(anchors, fail); value = CFDictionaryGetValue(anchors, cert); - require(value, fail); + require_quiet(value, fail); require(isBoolean(value), fail); - if (SecIsInternalRelease() && (flags & kSecAppleTrustAnchorFlagsIncludeTestAnchors)) { + if ((SecIsInternalRelease() || flags & kSecAppleTrustAnchorFlagsAllowNonProduction) + && flags & kSecAppleTrustAnchorFlagsIncludeTestAnchors) { res = true; } else { res = CFBooleanGetValue(value); diff --git a/OSX/utilities/src/SecAppleAnchorPriv.h b/OSX/utilities/src/SecAppleAnchorPriv.h index e87fa0bc..f8c5a4ad 100644 --- a/OSX/utilities/src/SecAppleAnchorPriv.h +++ b/OSX/utilities/src/SecAppleAnchorPriv.h @@ -15,6 +15,7 @@ __BEGIN_DECLS typedef CF_OPTIONS(uint32_t, SecAppleTrustAnchorFlags) { kSecAppleTrustAnchorFlagsIncludeTestAnchors = 1 << 0, + kSecAppleTrustAnchorFlagsAllowNonProduction = 1 << 1, }; /* diff --git a/OSX/utilities/src/SecDb.c b/OSX/utilities/src/SecDb.c index 76d6369a..8ea52f9d 100644 --- a/OSX/utilities/src/SecDb.c +++ b/OSX/utilities/src/SecDb.c @@ -70,6 +70,7 @@ struct __OpaqueSecDbConnection { bool inTransaction; SecDbTransactionSource source; bool isCorrupted; + CFErrorRef corruptionError; sqlite3 *handle; // Pending deletions and additions for the current transaction // Entires are either: @@ -325,9 +326,10 @@ static bool SecDbDidCreateFirstConnection(SecDbConnectionRef dbconn, bool didCre return ok; } -void SecDbCorrupt(SecDbConnectionRef dbconn) +void SecDbCorrupt(SecDbConnectionRef dbconn, CFErrorRef error) { dbconn->isCorrupted = true; + CFAssignRetained(dbconn->corruptionError, error); } @@ -689,7 +691,7 @@ static bool SecDbTruncate(SecDbConnectionRef dbconn, CFErrorRef *error) static bool SecDbHandleCorrupt(SecDbConnectionRef dbconn, int rc, CFErrorRef *error) { - CFStringRef reason = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SQL DB %@ is corrupted, trying to recover (rc=%d)"), dbconn->db->db_path, rc); + CFStringRef reason = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("SQL DB %@ is corrupted, trying to recover (rc=%d) %@"), dbconn->db->db_path, rc, dbconn->corruptionError); __security_simulatecrash(reason, __sec_exception_code_CorruptDb(knownDbPathIndex(dbconn), rc)); CFReleaseSafe(reason); @@ -858,6 +860,11 @@ SecDbConnectionCreate(SecDbRef db, bool readOnly, CFErrorRef *error) dbconn->db = db; dbconn->readOnly = readOnly; + dbconn->inTransaction = false; + dbconn->source = NULL; + dbconn->isCorrupted = false; + dbconn->corruptionError = NULL; + dbconn->handle = NULL; dbconn->changes = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault); done: @@ -1020,6 +1027,8 @@ SecDbConnectionDestroy(CFTypeRef value) } dbconn->db = NULL; CFReleaseNull(dbconn->changes); + CFReleaseNull(dbconn->corruptionError); + } diff --git a/OSX/utilities/src/SecDb.h b/OSX/utilities/src/SecDb.h index fa6b78e8..cefa055d 100644 --- a/OSX/utilities/src/SecDb.h +++ b/OSX/utilities/src/SecDb.h @@ -160,7 +160,7 @@ bool SecDbWithSQL(SecDbConnectionRef dbconn, CFStringRef sql, CFErrorRef *error, bool SecDbForEach(sqlite3_stmt *stmt, CFErrorRef *error, bool(^row)(int row_index)); // Mark the database as corrupted. -void SecDbCorrupt(SecDbConnectionRef dbconn); +void SecDbCorrupt(SecDbConnectionRef dbconn, CFErrorRef error); __END_DECLS diff --git a/OSX/utilities/src/SecTrace.c b/OSX/utilities/src/SecTrace.c new file mode 100644 index 00000000..0acd1e3d --- /dev/null +++ b/OSX/utilities/src/SecTrace.c @@ -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@ + */ + +#include "SecTrace.h" + + +static int64_t +SecBucketNSignificant(int64_t value, int64_t n) +{ + uint64_t factor = 1; + while (value > n) { + value /= 10; + factor *= 10; + } + return factor * value; +} + +int64_t +SecBucket1Significant(int64_t value) +{ + return SecBucketNSignificant(value, 10); +} + +int64_t +SecBucket2Significant(int64_t value) +{ + return SecBucketNSignificant(value, 100); +} + diff --git a/OSX/utilities/src/SecTrace.h b/OSX/utilities/src/SecTrace.h new file mode 100644 index 00000000..de8e368f --- /dev/null +++ b/OSX/utilities/src/SecTrace.h @@ -0,0 +1,38 @@ +/* + * 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 SecTrace_h +#define SecTrace_h + +#include +#include + +__BEGIN_DECLS + +int64_t SecBucket1Significant(int64_t); +int64_t SecBucket2Significant(int64_t); + +__END_DECLS + + +#endif /* SecTrace_h */ diff --git a/OSX/utilities/src/debugging.c b/OSX/utilities/src/debugging.c index e27d6c60..e7302d03 100644 --- a/OSX/utilities/src/debugging.c +++ b/OSX/utilities/src/debugging.c @@ -414,7 +414,7 @@ static void setup_environment_scopes() { ApplyScopeListForIDC(cur_scope, kScopeIDEnvironment); } -#define XPCSCOPESTRWANT "api,account,accountChange,circle,circleChange,circleCreat,flush,fresh,keygen,signing,talkwithkvs" +#define XPCSCOPESTRWANT "api,account,accountChange,circle,circleChange,circleCreat,flush,fresh,keygen,signing,talkwithkvs,syncbubble" #define XPCSCOPESTRDONTWANT "-event,http,item,keytrace,lockassertions,otr_keysetup,securityd,server,serverxpc,session,sync,titc,transport,trust,updates,xpc" static void setup_xpcdefault_scopes() { diff --git a/OSX/utilities/src/der_plist.h b/OSX/utilities/src/der_plist.h index 579a0e06..36629478 100644 --- a/OSX/utilities/src/der_plist.h +++ b/OSX/utilities/src/der_plist.h @@ -27,6 +27,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + // // Error Codes for PropertyList <-> DER // @@ -59,4 +63,8 @@ CFDataRef CFPropertyListCreateDERData(CFAllocatorRef allocator, CFPropertyListRe CFPropertyListRef CFPropertyListCreateWithDERData(CFAllocatorRef allocator, CFDataRef data, CFOptionFlags options, CFPropertyListFormat *format, CFErrorRef *error); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/OSX/utilities/utilities.xcodeproj/project.pbxproj b/OSX/utilities/utilities.xcodeproj/project.pbxproj index e0ec9aff..a069e601 100644 --- a/OSX/utilities/utilities.xcodeproj/project.pbxproj +++ b/OSX/utilities/utilities.xcodeproj/project.pbxproj @@ -76,6 +76,8 @@ E7B183661AAE3FA3006C3392 /* su-08-secbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = E7B183651AAE3FA3006C3392 /* su-08-secbuffer.c */; }; E7CC89D51909E0A2005FFA08 /* su-07-debugging.c in Sources */ = {isa = PBXBuildFile; fileRef = E7CC89D41909E0A2005FFA08 /* su-07-debugging.c */; }; E7E0D909158FD9CD002CA176 /* su-10-cfstring-der.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */; }; + EB0BC8F31C3C6E8E00785842 /* SecTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = EB0BC8F11C3C6E8E00785842 /* SecTrace.c */; }; + EB0BC8F41C3C6E8E00785842 /* SecTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = EB0BC8F21C3C6E8E00785842 /* SecTrace.h */; }; EB7193901B0258890066F5E2 /* SecAppleAnchor.c in Sources */ = {isa = PBXBuildFile; fileRef = EB71938E1B0258890066F5E2 /* SecAppleAnchor.c */; }; EB7193911B0258890066F5E2 /* SecAppleAnchorPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = EB71938F1B0258890066F5E2 /* SecAppleAnchorPriv.h */; }; EB7193941B02606A0066F5E2 /* SecInternalRelease.c in Sources */ = {isa = PBXBuildFile; fileRef = EB7193921B02606A0066F5E2 /* SecInternalRelease.c */; }; @@ -163,6 +165,8 @@ E7E0D8F9158FA9A3002CA176 /* libutilitiesRegressions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libutilitiesRegressions.a; sourceTree = BUILT_PRODUCTS_DIR; }; E7E0D908158FD9CD002CA176 /* su-10-cfstring-der.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "su-10-cfstring-der.c"; sourceTree = ""; }; E7FC081B161A3038008E0760 /* SecIOFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIOFormat.h; sourceTree = ""; }; + EB0BC8F11C3C6E8E00785842 /* SecTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTrace.c; sourceTree = ""; }; + EB0BC8F21C3C6E8E00785842 /* SecTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrace.h; sourceTree = ""; }; EB71938E1B0258890066F5E2 /* SecAppleAnchor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAppleAnchor.c; sourceTree = ""; }; EB71938F1B0258890066F5E2 /* SecAppleAnchorPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecAppleAnchorPriv.h; sourceTree = ""; }; EB7193921B02606A0066F5E2 /* SecInternalRelease.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecInternalRelease.c; sourceTree = ""; }; @@ -211,6 +215,8 @@ E777C71F15B74024004044A8 /* SecCFError.h */, E7B01B961664031B000485F1 /* SecDispatchRelease.h */, E7FC081B161A3038008E0760 /* SecIOFormat.h */, + EB0BC8F11C3C6E8E00785842 /* SecTrace.c */, + EB0BC8F21C3C6E8E00785842 /* SecTrace.h */, 4C6882C115ABADBC00028C8F /* array_size.h */, 4C6882C215ABADBC00028C8F /* comparison.c */, 4C6882C315ABADBC00028C8F /* comparison.h */, @@ -247,12 +253,12 @@ 52E2E4941738371400E78313 /* SecXPCError.h */, 52E2E4961738394C00E78313 /* SecXPCError.c */, E706B78918FC822B00797907 /* simulate_crash.c */, + 0C95CCC91A609D5F006E176C /* SecSCTUtils.h */, 0C95CCC81A609D5F006E176C /* SecSCTUtils.c */, EB71938E1B0258890066F5E2 /* SecAppleAnchor.c */, EB71938F1B0258890066F5E2 /* SecAppleAnchorPriv.h */, EB7193921B02606A0066F5E2 /* SecInternalRelease.c */, EB7193931B02606A0066F5E2 /* SecInternalReleasePriv.h */, - 0C95CCC91A609D5F006E176C /* SecSCTUtils.h */, ); path = src; sourceTree = ""; @@ -350,6 +356,7 @@ 4C6882E415ABADBC00028C8F /* der_plist.h in Headers */, BEA22A371811E4CF00BE7682 /* SecCertificateTrace.h in Headers */, 4C6882E615ABADBC00028C8F /* der_plist_internal.h in Headers */, + EB0BC8F41C3C6E8E00785842 /* SecTrace.h in Headers */, 4C6882E915ABADBC00028C8F /* fileIo.h in Headers */, 0C95CCCB1A609D5F006E176C /* SecSCTUtils.h in Headers */, E7188DF91AAA819400B46156 /* SecBuffer.h in Headers */, @@ -447,6 +454,7 @@ 4C6882DF15ABADBC00028C8F /* der_data.c in Sources */, 4C6882E015ABADBC00028C8F /* der_date.c in Sources */, E73EB7991B229F3C0095E255 /* SecCoreCrypto.c in Sources */, + EB0BC8F31C3C6E8E00785842 /* SecTrace.c in Sources */, E706B78A18FC822B00797907 /* simulate_crash.c in Sources */, E72D462D175FC35500F70B9B /* SecAKSWrappers.c in Sources */, 4C6882E115ABADBC00028C8F /* der_dictionary.c in Sources */, diff --git a/OTAPKIAssetTool/OTAServiceApp.m b/OTAPKIAssetTool/OTAServiceApp.m index 62d645ea..eee3ecff 100644 --- a/OTAPKIAssetTool/OTAServiceApp.m +++ b/OTAPKIAssetTool/OTAServiceApp.m @@ -82,7 +82,7 @@ static void OTAPKI_LOG(const char* sz, ...) kkManifestFileName - The file name of the manifest file for the OTA PKI trust asset - kAllowListFileName - The file name of the asset file that contains + kAllowListFileName - The file name of the asset file that contains hashes of the allowed leaf certificates whose trust store root has been removed @@ -110,6 +110,10 @@ static void OTAPKI_LOG(const char* sz, ...) certificates. This file sets which certs will be considered to be EV. + kCTLogsFileName - The file name of the asset file that contains + the list of Certificate Transparency logs and + their public keys. + kCertsIndexFileName - The file name of the asset file that contains a hash table of offsets into the cert table file. This is used to look up anchor certs. @@ -145,6 +149,7 @@ static const NSString* kAppleESCertificatesName = @"AppleESCertificates.plist"; static const NSString* kBlockKeyFileName = @"Blocked.plist"; static const NSString* kGrayListedKeysFileName = @"GrayListedKeys.plist"; static const NSString* kEVRootsFileName = @"EVRoots.plist"; +static const NSString* kCTLogsFileName = @"TrustedCTLogs.plist"; static const NSString* kCertsIndexFileName = @"certsIndex.data"; static const NSString* kCertsTableFileName = @"certsTable.data"; static const NSString* kVersionNumberKey = @"VersionNumber"; @@ -499,7 +504,7 @@ out: _file_list = [NSArray arrayWithObjects:kBlockKeyFileName, kGrayListedKeysFileName, kEVRootsFileName, kCertsIndexFileName, kCertsTableFileName, kManifestFileName, kAssetVersionFileName, kAppleESCertificatesName, - kAllowListFileName, nil]; + kAllowListFileName, kCTLogsFileName, nil]; _current_asset_version = nil; _next_asset_version = nil; diff --git a/RegressionTests/Security.plist b/RegressionTests/Security.plist new file mode 100644 index 00000000..b2eb369f --- /dev/null +++ b/RegressionTests/Security.plist @@ -0,0 +1,61 @@ + + + + + Project + Security + TestSpecificLogs + + /var/log/system.log + /var/log/module/com.apple.securityd/.* + /var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/.*security.log.* + + Tests + + + TestName + BackupNegativeTest + Command + + /AppleInternal/CoreOS/tests/Security/secbackupntest + + + + TestName + BackupTest + Command + + /AppleInternal/CoreOS/tests/Security/secbackuptest + + + + TestName + EduModeTest + Command + + /AppleInternal/CoreOS/tests/Security/secedumodetest + + + + TestName + secd_02_upgrade_while_locked + Command + + /usr/local/bin/secdtests + -1 + secd_02_upgrade_while_locked + + + + TestName + secd_35_keychain_migrate_inet + Command + + /usr/local/bin/secdtests + -1 + secd_35_keychain_migrate_inet + + + + + diff --git a/RegressionTests/Security_edumode.plist b/RegressionTests/Security_edumode.plist new file mode 100644 index 00000000..32e19d80 --- /dev/null +++ b/RegressionTests/Security_edumode.plist @@ -0,0 +1,35 @@ + + + + + Project + Security + TestSpecificLogs + + /var/log/system.log + /var/log/module/com.apple.securityd/.* + /var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/.*security.log.* + + Tests + + + TestName + BackupNegativeTest + Command + + /AppleInternal/CoreOS/tests/Security/secbackupntest + + + + TestName + si_13_item_system + Command + + /AppleInternal/Applications/SecurityTests.app/SecurityTests + -1 + si_13_item_system + + + + + diff --git a/RegressionTests/secbackupntest/secbackupntest.m b/RegressionTests/secbackupntest/secbackupntest.m new file mode 100644 index 00000000..1fc5ecc7 --- /dev/null +++ b/RegressionTests/secbackupntest/secbackupntest.m @@ -0,0 +1,64 @@ +// +// Copyright 2015 Apple. All rights reserved. +// + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + +#include +#include + +#include + +#include +#include + +#if !TARGET_OS_SIMULATOR +#include + +static NSData * +BagMe(void) +{ + keybag_handle_t handle; + kern_return_t result; + void *data = NULL; + int length; + + result = aks_create_bag("foo", 3, kAppleKeyStoreAsymmetricBackupBag, &handle); + if (result) + errx(1, "aks_create_bag: %08x", result); + + result = aks_save_bag(handle, &data, &length); + if (result) + errx(1, "aks_save_bag"); + + return [NSData dataWithBytes:data length:length]; +} +#endif /* TARGET_OS_SIMULATOR */ + +int main (int argc, const char * argv[]) +{ + @autoreleasepool { + NSData *bag = NULL, *password = NULL; + +#if !TARGET_OS_SIMULATOR + bag = BagMe(); + password = [NSData dataWithBytes:"foo" length:3]; +#endif + + NSLog(@"backup bag: %@", bag); + + NSData *backup = (__bridge NSData *)_SecKeychainCopyBackup((__bridge CFDataRef)bag, (__bridge CFDataRef)password); + if (backup != NULL) { + NSLog(@"backup data: %@", backup); + errx(1, "got backup"); + } + return 0; + } +} + + diff --git a/RegressionTests/secbackuptest/secbackuptest.entitlements b/RegressionTests/secbackuptest/secbackuptest.entitlements new file mode 100644 index 00000000..3776f055 --- /dev/null +++ b/RegressionTests/secbackuptest/secbackuptest.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.private.security.no-sandbox + + restore-keychain + + migrate-keychain + + application-identifier + com.apple.security.secbackuptest + + diff --git a/RegressionTests/secbackuptest/secbackuptest.m b/RegressionTests/secbackuptest/secbackuptest.m new file mode 100644 index 00000000..962cb283 --- /dev/null +++ b/RegressionTests/secbackuptest/secbackuptest.m @@ -0,0 +1,107 @@ +// +// Copyright 2015 - 2016 Apple. All rights reserved. +// + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + +#include +#include + +#include + +#include +#include +#include + +#if TARGET_OS_SIMULATOR +int +main(void) +{ + return 0; +} +#else + +#include + +static NSData * +BagMe(void) +{ + keybag_handle_t handle; + kern_return_t result; + void *data = NULL; + int length; + + result = aks_create_bag("foo", 3, kAppleKeyStoreAsymmetricBackupBag, &handle); + if (result) + errx(1, "aks_create_bag: %08x", result); + + result = aks_save_bag(handle, &data, &length); + if (result) + errx(1, "aks_save_bag"); + + return [NSData dataWithBytes:data length:length]; +} + +int main (int argc, const char * argv[]) +{ + @autoreleasepool { + NSData *bag = NULL, *password = NULL; + CFErrorRef error = NULL; + + bag = BagMe(); + password = [NSData dataWithBytes:"foo" length:3]; + + NSData *backup = CFBridgingRelease(_SecKeychainCopyBackup((__bridge CFDataRef)bag, (__bridge CFDataRef)password)); + if (backup == NULL) { + errx(1, "backup failed"); + } + + char path[] = "/tmp/secbackuptestXXXXXXX"; + int fd = mkstemp(path); + + bool status = _SecKeychainWriteBackupToFileDescriptor((__bridge CFDataRef)bag, (__bridge CFDataRef)password, fd, &error); + if (!status) { + NSLog(@"backup failed: %@", error); + errx(1, "failed backup 2"); + } + + struct stat sb; + fstat(fd, &sb); + + if (sb.st_size != (off_t)[backup length]) + warn("backup different "); + + if (abs((int)(sb.st_size - (off_t)[backup length])) > 1000) + errx(1, "backup different enough to fail"); + + + status = _SecKeychainRestoreBackupFromFileDescriptor(fd, (__bridge CFDataRef)bag, (__bridge CFDataRef)password, &error); + if (!status) { + NSLog(@"restore failed: %@", error); + errx(1, "restore failed"); + } + + close(fd); + unlink(path); + + NSData *backup2 = CFBridgingRelease(_SecKeychainCopyBackup((__bridge CFDataRef)bag, (__bridge CFDataRef)password)); + if (backup2 == NULL) { + errx(1, "backup 3 failed"); + } + + if (abs((int)(sb.st_size - (off_t)[backup2 length])) > 1000) + errx(1, "backup different enough to fail (mem vs backup2): %d vs %d", (int)sb.st_size, (int)[backup2 length]); + if (abs((int)([backup length] - [backup2 length])) > 1000) + errx(1, "backup different enough to fail (backup1 vs backup2: %d vs %d", (int)[backup length], (int)[backup2 length]); + + return 0; + } +} + +#endif /* TARGET_OS_SIMULATOR */ + diff --git a/RegressionTests/secedumodetest/secedumodetest.entitlements b/RegressionTests/secedumodetest/secedumodetest.entitlements new file mode 100644 index 00000000..f2060450 --- /dev/null +++ b/RegressionTests/secedumodetest/secedumodetest.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.developer.networking.networkextension + + com.apple.private.system-keychain + + keychain-access-groups + + com.apple.vpn-test + + + diff --git a/RegressionTests/secedumodetest/secedumodetest.m b/RegressionTests/secedumodetest/secedumodetest.m new file mode 100644 index 00000000..617a88de --- /dev/null +++ b/RegressionTests/secedumodetest/secedumodetest.m @@ -0,0 +1,65 @@ +// +// Copyright 2016 Apple. All rights reserved. +// + +/* + * This is to fool os services to not provide the Keychain manager + * interface tht doens't work since we don't have unified headers + * between iOS and OS X. rdar://23405418/ + */ +#define __KEYCHAINCORE__ 1 + +#include +#include +#include +#include +#include + + +int main (int argc, const char * argv[]) +{ + @autoreleasepool { + + NSDictionary *addItem = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"vpn-test-label", + (id)kSecAttrAccount : @"vpn-test-account", + (id)kSecValueData : @"password", + (id)kSecUseSystemKeychain : @YES, + }; + + NSDictionary *querySystemItem = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"vpn-test-label", + (id)kSecAttrAccount : @"vpn-test-account", + (id)kSecUseSystemKeychain : @YES, + }; + + NSDictionary *queryItem = @{ + (id)kSecClass : (id)kSecClassGenericPassword, + (id)kSecAttrLabel : @"vpn-test-label", + (id)kSecAttrAccount : @"vpn-test-account", + }; + + (void)SecItemDelete((__bridge CFDictionaryRef)querySystemItem); + + + if (!SecItemAdd((__bridge CFDictionaryRef)addItem, NULL)) + errx(1, "failed to add"); + + + if (!SecItemCopyMatching((__bridge CFDictionaryRef)queryItem, NULL)) + errx(1, "failed to find in user + system"); + + if (!SecItemCopyMatching((__bridge CFDictionaryRef)querySystemItem, NULL)) + errx(1, "failed to find in system"); + + + if (!SecItemDelete((__bridge CFDictionaryRef)querySystemItem)) + errx(1, "failed to clean up"); + + return 0; + } +} + + diff --git a/Security.xcodeproj/project.pbxproj b/Security.xcodeproj/project.pbxproj index 3f766e4f..c1edcc99 100644 --- a/Security.xcodeproj/project.pbxproj +++ b/Security.xcodeproj/project.pbxproj @@ -39,6 +39,7 @@ 05EF68CA1949167B007958C3 /* PBXTargetDependency */, 05EF68C81949166E007958C3 /* PBXTargetDependency */, 05EF68C0194915B6007958C3 /* PBXTargetDependency */, + EB93052B1BE1B43700978606 /* PBXTargetDependency */, ); name = Security_executables; productName = Security_executables; @@ -105,6 +106,7 @@ BE4AC9B418B8020400B84964 /* PBXTargetDependency */, 5346481B17331ED800FE9172 /* PBXTargetDependency */, F94E7AE21ACC8E7700F23132 /* PBXTargetDependency */, + EB9C1DB71BDFD51800F89272 /* PBXTargetDependency */, ); name = phase2; productName = phase2; @@ -132,6 +134,21 @@ name = world; productName = world; }; + EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */ = { + isa = PBXAggregateTarget; + buildConfigurationList = EB9C1DAF1BDFD4DF00F89272 /* Build configuration list for PBXAggregateTarget "SecurityBatsTests" */; + buildPhases = ( + EB9C1DB41BDFD4F200F89272 /* install BATS plist */, + EB9305021BE1B35D00978606 /* Chown BATS plist */, + ); + dependencies = ( + EB9B37AF1C6470B20027E2F9 /* PBXTargetDependency */, + EB0BC8411C3C079100785842 /* PBXTargetDependency */, + EB3A8E011BEEC6F3001A89AA /* PBXTargetDependency */, + ); + name = SecurityBatsTests; + productName = SecurityBatsTests; + }; F93C49021AB8FCE00047E01A /* ckcdiagnose.sh */ = { isa = PBXAggregateTarget; buildConfigurationList = F93C49031AB8FCE00047E01A /* Build configuration list for PBXAggregateTarget "ckcdiagnose.sh" */; @@ -1508,10 +1525,29 @@ E7FEEEFA1332B8210025EB06 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CF730310EF9CDE300E17471 /* CFNetwork.framework */; }; E7FEEEFB1332B8300025EB06 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CBCE5A90BE7F69100FF81F5 /* IOKit.framework */; }; E7FEFB94169E378500E18152 /* libSOSCommands.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FEFB8F169E36B000E18152 /* libSOSCommands.a */; }; + EB0BC8111C3C064400785842 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + EB0BC83F1C3C076400785842 /* secedumodetest.m in Sources */ = {isa = PBXBuildFile; fileRef = EB0BC83D1C3C06CA00785842 /* secedumodetest.m */; }; + EB3409B01C1D627400D77661 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + EB3A8DFF1BEEC66F001A89AA /* Security_edumode.plist in install BATS plist */ = {isa = PBXBuildFile; fileRef = EB3A8DD71BEEC4D6001A89AA /* Security_edumode.plist */; }; EB5D73101B0CB09E009CAA47 /* SOSTypes.h in Old SOS header location */ = {isa = PBXBuildFile; fileRef = 52F8DE4D1AF2EB8F00A2C271 /* SOSTypes.h */; }; EB5D73111B0CB0BE009CAA47 /* SOSPeerInfo.h in Old SOS header location */ = {isa = PBXBuildFile; fileRef = E7450BAD16D42B17009C07B8 /* SOSPeerInfo.h */; }; + EB69AB301BF4348000913AF1 /* SecEMCSPriv.h in Headers */ = {isa = PBXBuildFile; fileRef = EB69AB091BF4347700913AF1 /* SecEMCSPriv.h */; settings = {ATTRIBUTES = (Private, ); }; }; + EB9B37A91C64705F0027E2F9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + EB9B37B01C6476F10027E2F9 /* secbackuptest.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9B37A31C646F070027E2F9 /* secbackuptest.m */; }; + EB9C1D7B1BDFD0E000F89272 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; + EB9C1D7E1BDFD0E100F89272 /* secbackupntest.m in Sources */ = {isa = PBXBuildFile; fileRef = EB9C1D7D1BDFD0E100F89272 /* secbackupntest.m */; }; + EB9C1DB51BDFD50100F89272 /* Security.plist in install BATS plist */ = {isa = PBXBuildFile; fileRef = EB9C1DAD1BDFD49400F89272 /* Security.plist */; }; + EBC1B8E11BE96FE600E6ACA6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; EBD8495B1B24BEA000C5FD1E /* print_cert.c in Sources */ = {isa = PBXBuildFile; fileRef = EBD8495A1B24BEA000C5FD1E /* print_cert.c */; }; EBE54D761BE32F6F000C4856 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE901721C2283F7007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE901991C2284EE007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE9019A1C22852C007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE9019B1C2285D4007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE9019C1C2285DB007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE9019D1C228603007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBE9019E1C228610007308C6 /* AggregateDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72B368BD179891FC004C37CE /* AggregateDictionary.framework */; }; + EBF2D73C1C1E2B47006AB6FF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7FCBE431314471B000DE34E /* Foundation.framework */; }; F93C493B1AB8FF530047E01A /* ckcdiagnose.sh in CopyFiles */ = {isa = PBXBuildFile; fileRef = F93C493A1AB8FF530047E01A /* ckcdiagnose.sh */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; /* End PBXBuildFile section */ @@ -2608,6 +2644,41 @@ remoteGlobalIDString = E7FEFB82169E363300E18152; remoteInfo = libSOSCommands; }; + EB0BC8401C3C079100785842 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB0BC80D1C3C064400785842; + remoteInfo = secedumodetest; + }; + EB3A8E001BEEC6F3001A89AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB9C1D791BDFD0E000F89272; + remoteInfo = secbackupntest; + }; + EB93052A1BE1B43700978606 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272; + remoteInfo = SecurityBatsTests; + }; + EB9B37AE1C6470B20027E2F9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB9B37A51C64705F0027E2F9; + remoteInfo = secbackuptest; + }; + EB9C1DB61BDFD51800F89272 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4C35DB69094F906D002917C4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EB9C1DAE1BDFD4DE00F89272; + remoteInfo = SecurityBatsTests; + }; EBD849351B242C8900C5FD1E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 4C35DB69094F906D002917C4 /* Project object */; @@ -3867,6 +3938,18 @@ name = "Old SOS header location"; runOnlyForDeploymentPostprocessing = 1; }; + EB9C1DB41BDFD4F200F89272 /* install BATS plist */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /AppleInternal/CoreOS/BATS/unit_tests; + dstSubfolderSpec = 0; + files = ( + EB9C1DB51BDFD50100F89272 /* Security.plist in install BATS plist */, + EB3A8DFF1BEEC66F001A89AA /* Security_edumode.plist in install BATS plist */, + ); + name = "install BATS plist"; + runOnlyForDeploymentPostprocessing = 1; + }; F93C49061AB8FCE50047E01A /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; @@ -4652,6 +4735,17 @@ E7FCBE431314471B000DE34E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; E7FCBE451314471B000DE34E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; E7FEFB80169E26E200E18152 /* sub_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sub_commands.h; sourceTree = ""; }; + EB0BC8151C3C064400785842 /* secedumodetest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secedumodetest; sourceTree = BUILT_PRODUCTS_DIR; }; + EB0BC83D1C3C06CA00785842 /* secedumodetest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = secedumodetest.m; path = secedumodetest/secedumodetest.m; sourceTree = ""; }; + EB0BC83E1C3C072C00785842 /* secedumodetest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = secedumodetest.entitlements; path = secedumodetest/secedumodetest.entitlements; sourceTree = ""; }; + EB3A8DD71BEEC4D6001A89AA /* Security_edumode.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Security_edumode.plist; sourceTree = ""; }; + EB69AB091BF4347700913AF1 /* SecEMCSPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEMCSPriv.h; sourceTree = ""; }; + EB9B37A31C646F070027E2F9 /* secbackuptest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = secbackuptest.m; path = secbackuptest/secbackuptest.m; sourceTree = ""; }; + EB9B37A41C646F5F0027E2F9 /* secbackuptest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = secbackuptest.entitlements; path = secbackuptest/secbackuptest.entitlements; sourceTree = ""; }; + EB9B37AD1C64705F0027E2F9 /* secbackuptest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secbackuptest; sourceTree = BUILT_PRODUCTS_DIR; }; + EB9C1D7A1BDFD0E000F89272 /* secbackupntest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = secbackupntest; sourceTree = BUILT_PRODUCTS_DIR; }; + EB9C1D7D1BDFD0E100F89272 /* secbackupntest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = secbackupntest.m; sourceTree = ""; }; + EB9C1DAD1BDFD49400F89272 /* Security.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Security.plist; sourceTree = ""; }; EBD8495A1B24BEA000C5FD1E /* print_cert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = print_cert.c; path = OSX/sec/SecurityTool/print_cert.c; sourceTree = SOURCE_ROOT; }; EBE54D771BE33227000C4856 /* libmis.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmis.dylib; path = usr/lib/libmis.dylib; sourceTree = SDKROOT; }; F93C493A1AB8FF530047E01A /* ckcdiagnose.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ckcdiagnose.sh; sourceTree = ""; }; @@ -4662,9 +4756,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE901721C2283F7007308C6 /* AggregateDictionary.framework in Frameworks */, 0C0BDB901756A80100BC1A7E /* libsecipc_client.a in Frameworks */, 0C0BDB8C1756A5F500BC1A7E /* libregressions.a in Frameworks */, 438168C51B4ED43B00C54D58 /* CoreFoundation.framework in Frameworks */, + EB3409B01C1D627400D77661 /* Foundation.framework in Frameworks */, 0C0BDB8B1756A5D900BC1A7E /* libASN1.a in Frameworks */, 0C0BDB8A1756A5D500BC1A7E /* libDER.a in Frameworks */, 0C0BDB851756A4B900BC1A7E /* libsecdRegressions.a in Frameworks */, @@ -4701,7 +4797,6 @@ 5296CB4E1655B8F5009912AF /* libMobileGestalt.dylib in Frameworks */, 0C78F1D016A5E3EB00654E08 /* libbsm.dylib in Frameworks */, 0C15009B161D020000181E9D /* libASN1.a in Frameworks */, - 438166ED1B4ECF9400C54D58 /* CoreFoundation.framework in Frameworks */, 0C15009A161D01F400181E9D /* libCMS.a in Frameworks */, 44A655831AA4B4BB0059D185 /* libctkclient.a in Frameworks */, 0C150099161D01D700181E9D /* libDER.a in Frameworks */, @@ -4712,6 +4807,7 @@ 4C2FEC5215755D8C0008BE39 /* libutilities.a in Frameworks */, 4432AF8B1A014664000958DC /* libcoreauthd_client.a in Frameworks */, 4432AF8D1A01472C000958DC /* libaks_acl.a in Frameworks */, + 438166ED1B4ECF9400C54D58 /* CoreFoundation.framework in Frameworks */, 4CAF67AC0F3A70220064A534 /* IOKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4720,10 +4816,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 43DB54551BB1F8920083C3F1 /* ProtectedCloudStorage.framework in Frameworks */, 4C8A38C917B93DF10001B4C0 /* CloudServices.framework in Frameworks */, 4C7913251799A5CC00A9633E /* MobileCoreServices.framework in Frameworks */, 4381603B1B4DCEFF00C54D58 /* AggregateDictionary.framework in Frameworks */, - 43DB54551BB1F8920083C3F1 /* ProtectedCloudStorage.framework in Frameworks */, 4C3DD6BD179760280093F9D8 /* libMobileGestalt.dylib in Frameworks */, 533B5D4F177CD63100995334 /* SpringBoardServices.framework in Frameworks */, 7200D76F177B9999009BB396 /* ManagedConfiguration.framework in Frameworks */, @@ -4741,6 +4837,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE9019C1C2285DB007308C6 /* AggregateDictionary.framework in Frameworks */, E7D690A11652E07B0079537A /* libMobileGestalt.dylib in Frameworks */, 0CCA418715C89FBB002AEC4C /* libsecurity_ssl_regressions.a in Frameworks */, 18F7F67814D77F0600F88A12 /* libsecurityd.a in Frameworks */, @@ -4784,6 +4881,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE9019A1C22852C007308C6 /* AggregateDictionary.framework in Frameworks */, 438168BB1B4ED42300C54D58 /* CoreFoundation.framework in Frameworks */, E7FEFB94169E378500E18152 /* libSOSCommands.a in Frameworks */, E7104A07169E03CE00DB0045 /* libSecurityTool.a in Frameworks */, @@ -4794,6 +4892,7 @@ 4C32C1A60A497A21002891BD /* Security.framework in Frameworks */, 4CAE95DC0F3D6E020075278E /* CFNetwork.framework in Frameworks */, 4C0CC642174C580200CC799A /* SystemConfiguration.framework in Frameworks */, + EBC1B8E11BE96FE600E6ACA6 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4823,6 +4922,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE9019D1C228603007308C6 /* AggregateDictionary.framework in Frameworks */, 5233636418CA9B8900333A5C /* SystemConfiguration.framework in Frameworks */, 5233636318CA9B3C00333A5C /* libSecureObjectSync.a in Frameworks */, 5233635818CA9B2600333A5C /* libsecurityd.a in Frameworks */, @@ -4865,6 +4965,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE901991C2284EE007308C6 /* AggregateDictionary.framework in Frameworks */, + EBF2D73C1C1E2B47006AB6FF /* Foundation.framework in Frameworks */, 5E43C49F1B00D63100E5ECB2 /* libutilities.a in Frameworks */, 5E43C49D1B00D55C00E5ECB2 /* libsecurityd.a in Frameworks */, 5E43C49B1B00D50F00E5ECB2 /* libSecureObjectSync.a in Frameworks */, @@ -4999,6 +5101,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE9019B1C2285D4007308C6 /* AggregateDictionary.framework in Frameworks */, + E7A011AE14E1B78800765C29 /* Foundation.framework in Frameworks */, E7D690921652E06A0079537A /* libMobileGestalt.dylib in Frameworks */, 0CCA418815C89FC4002AEC4C /* libsecurity_ssl_regressions.a in Frameworks */, 18F7F67514D77EF400F88A12 /* libsecurityd.a in Frameworks */, @@ -5018,7 +5122,6 @@ E7FEEEF81332B7F70025EB06 /* libsqlite3.dylib in Frameworks */, E7FEEEFA1332B8210025EB06 /* CFNetwork.framework in Frameworks */, E7FEEEFB1332B8300025EB06 /* IOKit.framework in Frameworks */, - E7A011AE14E1B78800765C29 /* Foundation.framework in Frameworks */, 7930B06A134A4864007062F8 /* Security.framework in Frameworks */, E71F3E4116EA6A5100FAF9B4 /* SystemConfiguration.framework in Frameworks */, ); @@ -5028,6 +5131,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + EBE9019E1C228610007308C6 /* AggregateDictionary.framework in Frameworks */, 52222CD0167BDAEC00EDD09C /* SpringBoardServices.framework in Frameworks */, E7B01BD2166594AB000485F1 /* CFNetwork.framework in Frameworks */, E7B01BD3166594AB000485F1 /* IOKit.framework in Frameworks */, @@ -5048,6 +5152,30 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + EB0BC8101C3C064400785842 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EB0BC8111C3C064400785842 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB9B37A81C64705F0027E2F9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EB9B37A91C64705F0027E2F9 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB9C1D771BDFD0E000F89272 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EB9C1D7B1BDFD0E000F89272 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -5295,6 +5423,7 @@ 5E10992719A5E55800A60E2B /* ISACLProtectedItems */, 5EBE247B1B00CCAE0007DB0E /* secacltests */, 4381690E1B4EDCBD00C54D58 /* SOSCCAuthPlugin */, + EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */, E7FCBE401314471B000DE34E /* Frameworks */, 4C35DC36094F9120002917C4 /* Products */, 4C8BC620097DBC1B00C781D5 /* Libraries */, @@ -5333,6 +5462,9 @@ CD276C271A83F60C003226BC /* IDSKeychainSyncingProxy.bundle */, 5EBE247A1B00CCAE0007DB0E /* secacltests */, 4381690C1B4EDCBD00C54D58 /* SOSCCAuthPlugin.bundle */, + EB9C1D7A1BDFD0E000F89272 /* secbackupntest */, + EB0BC8151C3C064400785842 /* secedumodetest */, + EB9B37AD1C64705F0027E2F9 /* secbackuptest */, ); name = Products; sourceTree = ""; @@ -5839,6 +5971,7 @@ 4AF7FFF715AFB73800B9D400 /* SecOTRMath.h */, 4AF7FFF915AFB73800B9D400 /* SecOTRPacketData.h */, 4AF7FFFA15AFB73800B9D400 /* SecOTRPackets.h */, + EB69AB091BF4347700913AF1 /* SecEMCSPriv.h */, 4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */, 4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */, CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */, @@ -6403,6 +6536,44 @@ name = Frameworks; sourceTree = ""; }; + EB0BC83C1C3C069500785842 /* secedumodetest */ = { + isa = PBXGroup; + children = ( + EB0BC83D1C3C06CA00785842 /* secedumodetest.m */, + EB0BC83E1C3C072C00785842 /* secedumodetest.entitlements */, + ); + name = secedumodetest; + sourceTree = ""; + }; + EB9B377C1C646ED10027E2F9 /* secbackuptest */ = { + isa = PBXGroup; + children = ( + EB9B37A31C646F070027E2F9 /* secbackuptest.m */, + EB9B37A41C646F5F0027E2F9 /* secbackuptest.entitlements */, + ); + name = secbackuptest; + sourceTree = ""; + }; + EB9C1D7C1BDFD0E100F89272 /* secbackupntest */ = { + isa = PBXGroup; + children = ( + EB9C1D7D1BDFD0E100F89272 /* secbackupntest.m */, + ); + path = secbackupntest; + sourceTree = ""; + }; + EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = { + isa = PBXGroup; + children = ( + EB9C1DAD1BDFD49400F89272 /* Security.plist */, + EB3A8DD71BEEC4D6001A89AA /* Security_edumode.plist */, + EB9C1D7C1BDFD0E100F89272 /* secbackupntest */, + EB9B377C1C646ED10027E2F9 /* secbackuptest */, + EB0BC83C1C3C069500785842 /* secedumodetest */, + ); + path = RegressionTests; + sourceTree = ""; + }; F93C49391AB8FF530047E01A /* ckcdiagnose */ = { isa = PBXGroup; children = ( @@ -6488,6 +6659,7 @@ 0C5D2EED167FEEC90077501D /* secasn1t.h in Headers */, 0C5D2EEF167FF0560077501D /* SecAsn1Templates.h in Headers */, D45D1A471B3A293E00C63E16 /* oids.h in Headers */, + EB69AB301BF4348000913AF1 /* SecEMCSPriv.h in Headers */, 8E02FA6B1107BE460043545E /* pbkdf2.h in Headers */, 8ED6F6CA110904E300D2B368 /* SecPBKDF.h in Headers */, 7901791812D51F7200CA4D44 /* SecCmsBase.h in Headers */, @@ -6988,6 +7160,54 @@ productReference = E7B01BF2166594AB000485F1 /* SyncDevTest2.app */; productType = "com.apple.product-type.application"; }; + EB0BC80D1C3C064400785842 /* secedumodetest */ = { + isa = PBXNativeTarget; + buildConfigurationList = EB0BC8121C3C064400785842 /* Build configuration list for PBXNativeTarget "secedumodetest" */; + buildPhases = ( + EB0BC80E1C3C064400785842 /* Sources */, + EB0BC8101C3C064400785842 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = secedumodetest; + productName = secbackupntest; + productReference = EB0BC8151C3C064400785842 /* secedumodetest */; + productType = "com.apple.product-type.tool"; + }; + EB9B37A51C64705F0027E2F9 /* secbackuptest */ = { + isa = PBXNativeTarget; + buildConfigurationList = EB9B37AA1C64705F0027E2F9 /* Build configuration list for PBXNativeTarget "secbackuptest" */; + buildPhases = ( + EB9B37A61C64705F0027E2F9 /* Sources */, + EB9B37A81C64705F0027E2F9 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = secbackuptest; + productName = secbackupntest; + productReference = EB9B37AD1C64705F0027E2F9 /* secbackuptest */; + productType = "com.apple.product-type.tool"; + }; + EB9C1D791BDFD0E000F89272 /* secbackupntest */ = { + isa = PBXNativeTarget; + buildConfigurationList = EB9C1DA91BDFD0E100F89272 /* Build configuration list for PBXNativeTarget "secbackupntest" */; + buildPhases = ( + EB9C1D761BDFD0E000F89272 /* Sources */, + EB9C1D771BDFD0E000F89272 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = secbackupntest; + productName = secbackupntest; + productReference = EB9C1D7A1BDFD0E000F89272 /* secbackupntest */; + productType = "com.apple.product-type.tool"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -7005,6 +7225,12 @@ CD276C261A83F60C003226BC = { CreatedOnToolsVersion = 7.0; }; + EB9C1D791BDFD0E000F89272 = { + CreatedOnToolsVersion = 7.1; + }; + EB9C1DAE1BDFD4DE00F89272 = { + CreatedOnToolsVersion = 7.1; + }; F93C49021AB8FCE00047E01A = { CreatedOnToolsVersion = 6.3; }; @@ -7105,6 +7331,10 @@ F93C49021AB8FCE00047E01A /* ckcdiagnose.sh */, 5EBE24791B00CCAE0007DB0E /* secacltests */, 4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */, + EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */, + EB9C1D791BDFD0E000F89272 /* secbackupntest */, + EB0BC80D1C3C064400785842 /* secedumodetest */, + EB9B37A51C64705F0027E2F9 /* secbackuptest */, ); }; /* End PBXProject section */ @@ -7663,6 +7893,21 @@ shellPath = /bin/sh; shellScript = "install_name_tool -change /System/Library/Frameworks/CFNetwork.framework/CFNetwork /System/Library/Frameworks/CoreServices.framework/CoreServices \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}\""; }; + EB9305021BE1B35D00978606 /* Chown BATS plist */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 8; + files = ( + ); + inputPaths = ( + ); + name = "Chown BATS plist"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "chown root:wheel ${DSTROOT}/AppleInternal/CoreOS/BATS/unit_tests/*.plist"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -7909,6 +8154,30 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + EB0BC80E1C3C064400785842 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB0BC83F1C3C076400785842 /* secedumodetest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB9B37A61C64705F0027E2F9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB9B37B01C6476F10027E2F9 /* secbackuptest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EB9C1D761BDFD0E000F89272 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EB9C1D7E1BDFD0E100F89272 /* secbackupntest.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -8392,6 +8661,31 @@ name = libSOSCommands; targetProxy = E7FEFB92169E377900E18152 /* PBXContainerItemProxy */; }; + EB0BC8411C3C079100785842 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB0BC80D1C3C064400785842 /* secedumodetest */; + targetProxy = EB0BC8401C3C079100785842 /* PBXContainerItemProxy */; + }; + EB3A8E011BEEC6F3001A89AA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB9C1D791BDFD0E000F89272 /* secbackupntest */; + targetProxy = EB3A8E001BEEC6F3001A89AA /* PBXContainerItemProxy */; + }; + EB93052B1BE1B43700978606 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; + targetProxy = EB93052A1BE1B43700978606 /* PBXContainerItemProxy */; + }; + EB9B37AF1C6470B20027E2F9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB9B37A51C64705F0027E2F9 /* secbackuptest */; + targetProxy = EB9B37AE1C6470B20027E2F9 /* PBXContainerItemProxy */; + }; + EB9C1DB71BDFD51800F89272 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */; + targetProxy = EB9C1DB61BDFD51800F89272 /* PBXContainerItemProxy */; + }; EBD849361B242C8900C5FD1E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4CE5A54C09C796E100D27A3F /* sslViewer */; @@ -8965,6 +9259,10 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = NO; @@ -9025,6 +9323,10 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_TREAT_WARNINGS_AS_ERRORS = YES; @@ -9205,6 +9507,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = "secacltests/secacltests-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "$(inherited)", @@ -9221,6 +9527,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = "secacltests/secacltests-entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); INSTALL_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/bin"; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "$(inherited)", @@ -10122,6 +10432,10 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_PRECOMPILE_PREFIX_HEADER = NO; @@ -10178,6 +10492,10 @@ CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = "Keychain/Keychain-Entitlements.plist"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PRECOMPILE_PREFIX_HEADER = NO; HEADER_SEARCH_PATHS = ( @@ -10218,6 +10536,348 @@ }; name = Release; }; + EB0BC8131C3C064400785842 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + 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 = RegressionTests/secedumodetest/secedumodetest.entitlements; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "-framework", + Security, + ); + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + }; + name = Debug; + }; + EB0BC8141C3C064400785842 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + 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 = RegressionTests/secedumodetest/secedumodetest.entitlements; + 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_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-framework", + Security, + ); + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + EB9B37AB1C64705F0027E2F9 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + 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 = RegressionTests/secbackuptest/secbackuptest.entitlements; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "-framework", + Security, + ); + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + }; + name = Debug; + }; + EB9B37AC1C64705F0027E2F9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + 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 = RegressionTests/secbackuptest/secbackuptest.entitlements; + 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_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-framework", + Security, + ); + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + EB9C1D811BDFD0E100F89272 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + 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; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ( + "-framework", + Security, + ); + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + }; + name = Debug; + }; + EB9C1D821BDFD0E100F89272 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + 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; + 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_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + INSTALL_PATH = /AppleInternal/CoreOS/tests/Security; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_LDFLAGS = ( + "-framework", + Security, + ); + "OTHER_LDFLAGS[sdk=iphoneos*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-laks", + "-framework", + Security, + "-framework", + IOKit, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx.internal; + SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + EB9C1DB01BDFD4DF00F89272 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + EB9C1DB11BDFD4DF00F89272 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; F93C49041AB8FCE00047E01A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -10532,6 +11192,42 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + EB0BC8121C3C064400785842 /* Build configuration list for PBXNativeTarget "secedumodetest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB0BC8131C3C064400785842 /* Debug */, + EB0BC8141C3C064400785842 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EB9B37AA1C64705F0027E2F9 /* Build configuration list for PBXNativeTarget "secbackuptest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB9B37AB1C64705F0027E2F9 /* Debug */, + EB9B37AC1C64705F0027E2F9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EB9C1DA91BDFD0E100F89272 /* Build configuration list for PBXNativeTarget "secbackupntest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB9C1D811BDFD0E100F89272 /* Debug */, + EB9C1D821BDFD0E100F89272 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EB9C1DAF1BDFD4DF00F89272 /* Build configuration list for PBXAggregateTarget "SecurityBatsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EB9C1DB01BDFD4DF00F89272 /* Debug */, + EB9C1DB11BDFD4DF00F89272 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; F93C49031AB8FCE00047E01A /* Build configuration list for PBXAggregateTarget "ckcdiagnose.sh" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Security.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme index c32b0529..dc2d7b05 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme @@ -11,7 +11,8 @@ buildForRunning = "YES" buildForProfiling = "YES" buildForArchiving = "YES" - buildForAnalyzing = "YES"> + buildForAnalyzing = "YES" + hideIssues = "NO"> + buildForAnalyzing = "YES" + hideIssues = "NO"> + + @@ -200,6 +206,10 @@ argument = "si_16_ec_certificate" isEnabled = "NO"> + + @@ -298,7 +308,7 @@ + isEnabled = "YES"> + + + + + + @@ -692,10 +714,6 @@ argument = "otr_packetdata" isEnabled = "NO"> - - + + @@ -426,6 +430,14 @@ argument = "si_88_sectrust_vpnprofile" isEnabled = "NO"> + + + + diff --git a/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme b/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme index acbfe3f0..280d9d48 100644 --- a/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme +++ b/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme @@ -99,6 +99,14 @@ argument = "secd_05_corrupted_items" isEnabled = "NO"> + + + + @@ -231,6 +239,10 @@ argument = "sc_140_hsa2" isEnabled = "NO"> + + diff --git a/SecurityTests/SecurityTests-Entitlements.plist b/SecurityTests/SecurityTests-Entitlements.plist index c966c010..3363c039 100644 --- a/SecurityTests/SecurityTests-Entitlements.plist +++ b/SecurityTests/SecurityTests-Entitlements.plist @@ -20,6 +20,8 @@ com.apple.springboard.wipedevice + com.apple.private.system-keychain + application-identifier com.apple.security.regressions keychain-access-groups diff --git a/SecurityTool/SecurityTool.xcodeproj/project.pbxproj b/SecurityTool/SecurityTool.xcodeproj/project.pbxproj index 544cdf0b..5d97e419 100644 --- a/SecurityTool/SecurityTool.xcodeproj/project.pbxproj +++ b/SecurityTool/SecurityTool.xcodeproj/project.pbxproj @@ -476,6 +476,9 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18A25BEB14752959004F59F8 /* project.xcconfig */; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + HEADER_SEARCH_PATHS = "${CONFIGURATION_BUILD_DIR}/usr/local/include"; + USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; }; @@ -483,6 +486,10 @@ isa = XCBuildConfiguration; baseConfigurationReference = 18A25BEB14752959004F59F8 /* project.xcconfig */; buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + HEADER_SEARCH_PATHS = "${CONFIGURATION_BUILD_DIR}/usr/local/include"; + "HEADER_SEARCH_PATHS[arch=*]" = ""; + USER_HEADER_SEARCH_PATHS = ""; }; name = Release; }; diff --git a/SecurityTool/entitlements.plist b/SecurityTool/entitlements.plist index 4d4bad7a..ac3d1b60 100644 --- a/SecurityTool/entitlements.plist +++ b/SecurityTool/entitlements.plist @@ -13,6 +13,10 @@ restore-keychain + com.apple.private.syncbubble-keychain + + com.apple.private.system-keychain + application-identifier com.apple.security diff --git a/SecurityTool/keychain_find.c b/SecurityTool/keychain_find.c index 23f56859..da00ab89 100644 --- a/SecurityTool/keychain_find.c +++ b/SecurityTool/keychain_find.c @@ -34,7 +34,11 @@ #include #include #include +#include +#include +#include #include +#include #include #include #include @@ -1185,6 +1189,353 @@ cleanup: return result; } +// Declare here to use later. +int keychain_set_partition_list(SecKeychainRef kc, CFDictionaryRef query, CFStringRef password, CFStringRef partitionlist); +int keychain_parse_args_and_set_partition_list(int argc, char * const *argv, CFDictionaryRef query, CFStringRef partitionidsinput, CFStringRef password); + +int keychain_set_internet_password_partition_list(int argc, char * const *argv) { + /* + * " -a Match \"account\" string\n" + * " -c Match \"creator\" (four-character code)\n" + * " -C Match \"type\" (four-character code)\n" + * " -d Match \"securityDomain\" string\n" + * " -D Match \"kind\" string\n" + * " -j Match \"comment\" string\n" + * " -l Match \"label\" string\n" + * " -p Match \"path\" string\n" + * " -P Match port number\n" + * " -r Match \"protocol\" (four-character code)\n" + * " -s Match \"server\" string\n" + * " -t Match \"authenticationType\" (four-character code)\n" + * " -S Comma-separated list of allowed partition IDs" + * " -k password for keychain" + */ + + CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(query, kSecClass, kSecClassInternetPassword); + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); + + CFStringRef partitionidsinput = NULL; + CFStringRef password = NULL; + + int ch, result = 0; + while ((ch = getopt(argc, argv, "a:c:C:d:D:j:l:p:P:r:s:S:t:k:")) != -1) + { + switch (ch) + { + case 'a': + CFDictionarySetValue(query, kSecAttrAccount, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'c': + CFDictionarySetValue(query, kSecAttrCreator, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'C': + CFDictionarySetValue(query, kSecAttrType, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'd': + CFDictionarySetValue(query, kSecAttrSecurityDomain, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'D': + CFDictionarySetValue(query, kSecAttrDescription, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'j': + CFDictionarySetValue(query, kSecAttrComment, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'l': + CFDictionarySetValue(query, kSecAttrLabel, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'p': + CFDictionarySetValue(query, kSecAttrPath, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'P': + CFDictionarySetValue(query, kSecAttrPort, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'r': + CFDictionarySetValue(query, kSecAttrProtocol, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 's': + CFDictionarySetValue(query, kSecAttrService, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 't': + CFDictionarySetValue(query, kSecAttrAuthenticationType, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'S': + partitionidsinput = CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull); + break; + case 'k': + password = CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull); + break; + case '?': + default: + result = 2; + goto cleanup; + } + } + + argc -= optind; + argv += optind; + + result = keychain_parse_args_and_set_partition_list(argc, argv, query, partitionidsinput, password); + +cleanup: + safe_CFRelease(&password); + safe_CFRelease(&partitionidsinput); + safe_CFRelease(&query); + return result; +} + +int +keychain_set_generic_password_partition_list(int argc, char * const *argv) { + CFMutableDictionaryRef query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + // -a Match \"account\" string + // -c Match \"creator\" (four-character code) + // -C Match \"type\" (four-character code) + // -D Match \"kind\" string + // -G Match \"value\" string (generic attribute) + // -j Match \"comment\" string + // -l Match \"label\" string + // -s Match \"service\" string + // -S Comma-separated list of allowed partition IDs + // -k password for keychain + + CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword); + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); + + CFStringRef partitionidsinput = NULL; + CFStringRef password = NULL; + + int ch, result = 0; + while ((ch = getopt(argc, argv, "a:c:C:D:G:j:l:s:S:k:")) != -1) + { + switch (ch) + { + case 'a': + CFDictionarySetValue(query, kSecAttrAccount, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'c': + CFDictionarySetValue(query, kSecAttrCreator, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'C': + CFDictionarySetValue(query, kSecAttrType, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'D': + CFDictionarySetValue(query, kSecAttrDescription, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'G': + CFDictionarySetValue(query, kSecAttrGeneric, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'j': + CFDictionarySetValue(query, kSecAttrComment, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'l': + CFDictionarySetValue(query, kSecAttrLabel, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 's': + CFDictionarySetValue(query, kSecAttrService, CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull)); + break; + case 'S': + partitionidsinput = CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull); + break; + case 'k': + password = CFStringCreateWithCStringNoCopy(NULL, optarg, kCFStringEncodingUTF8, kCFAllocatorNull); + break; + case '?': + default: + result = 2; + goto cleanup; + } + } + + argc -= optind; + argv += optind; + + result = keychain_parse_args_and_set_partition_list(argc, argv, query, partitionidsinput, password); + +cleanup: + safe_CFRelease(&password); + safe_CFRelease(&partitionidsinput); + safe_CFRelease(&query); + return result; +} + + +int keychain_parse_args_and_set_partition_list(int argc, char * const *argv, CFDictionaryRef query, CFStringRef partitionidsinput, CFStringRef password) { + int result = 0; + const char *keychainName = NULL; + SecKeychainRef kc = NULL; + + // if we were given a keychain, use it + if (argc == 1) + { + keychainName = argv[0]; + if (*keychainName == '\0') + { + result = 2; + goto cleanup; + } + + kc = keychain_open(keychainName); + if(!kc) { + sec_error("couldn't open \"%s\"", keychainName); + result = 1; + goto cleanup; + } + + CFMutableArrayRef searchList = (CFMutableArrayRef) CFArrayCreateMutable(kCFAllocatorDefault, 1, &kCFTypeArrayCallBacks); + CFArrayAppendValue((CFMutableArrayRef)searchList, kc); + CFDictionarySetValue(query, kSecMatchSearchList, searchList); + } else if (argc != 0) { + result = 2; + goto cleanup; + } + + if(!password) { + char* cpassword = prompt_password(keychainName); + if (!cpassword) { + result = -1; + goto cleanup; + } + password = CFStringCreateWithCString(NULL, cpassword, kCFStringEncodingUTF8); + free(cpassword); + } + + if(!partitionidsinput || !password) { + result = 2; + goto cleanup; + } + + result = keychain_set_partition_list(kc, query, password, partitionidsinput); + +cleanup: + return result; +} + + +int keychain_set_partition_list(SecKeychainRef kc, CFDictionaryRef query, CFStringRef password, CFStringRef partitionlist) { + int result = 0; + + char *passwordBuf = NULL; + size_t passwordLen; + GetCStringFromCFString(password, &passwordBuf, &passwordLen); + + OSStatus status; + + // Unlock the keychain with the given password, since we'll be fetching ACLs + status = SecKeychainUnlock(kc, (UInt32) passwordLen, passwordBuf, true); + if(status) { + sec_perror("SecKeychainUnlock", status); + result = 1; + goto cleanup; + } + + CFTypeRef results = NULL; + status = SecItemCopyMatching(query, &results); + if(status) { + sec_perror("SecItemCopyMatching", status); + result = 1; + goto cleanup; + } + + if(!results) { + result = 0; + goto cleanup; + } + + if (CFGetTypeID(results) == CFArrayGetTypeID()) { + for(int i = 0; i < CFArrayGetCount(results); i++) { + SecKeychainItemRef item = (SecKeychainItemRef) CFArrayGetValueAtIndex(results, i); + SecAccessRef access = NULL; + + do_password_item_printing(item, false, false); + + status = SecKeychainItemCopyAccess(item, &access); + if (status == errSecNoAccessForItem) { + continue; + } + if(status) { + sec_perror("SecKeychainItemCopyAccess", status); + result = 1; + goto cleanup; + } + + CFArrayRef aclList = NULL; + status = SecAccessCopyACLList(access, &aclList); + if (status) + { + sec_perror("SecAccessCopyACLList", status); + result = 1; + goto cleanup; + } + + CFIndex size = CFArrayGetCount(aclList); + for(CFIndex i = 0; i < size; i++) { + SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(aclList, i); + CSSM_ACL_AUTHORIZATION_TAG tags[64]; // Pick some upper limit + uint32 tagix, tagCount = sizeof(tags) / sizeof(*tags); + status = SecACLGetAuthorizations(acl, tags, &tagCount); + + if (status) + { + sec_perror("SecACLGetAuthorizations", status); + result = 1; + goto cleanup; + } + + CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector = {}; + + for (tagix = 0; tagix < tagCount; ++tagix) + { + CSSM_ACL_AUTHORIZATION_TAG tag = tags[tagix]; + if(tag == CSSM_ACL_AUTHORIZATION_PARTITION_ID) { + + CFArrayRef applicationList; + CFStringRef promptDescription; + + status = SecACLCopySimpleContents(acl, &applicationList, &promptDescription, &promptSelector); + if(status) { + sec_perror("SecACLCopySimpleContents", status); + result = 1; + goto cleanup; + } + + CFArrayRef partitionIDs = CFStringCreateArrayBySeparatingStrings(kCFAllocatorDefault, partitionlist, CFSTR(",")); + CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionarySetValue(dict, CFSTR("Partitions"), partitionIDs); + CFDataRef xml = CFPropertyListCreateXMLData(NULL, dict); + CFStringRef xmlstr = cfToHex(xml); + + SecACLSetSimpleContents(acl, applicationList, xmlstr, &promptSelector); + + safe_CFRelease(&xmlstr); + safe_CFRelease(&xml); + safe_CFRelease(&dict); + safe_CFRelease(&partitionIDs); + } + } + } + + status = SecKeychainItemSetAccessWithPassword(item, access, (UInt32) passwordLen, passwordBuf); + if(status) { + sec_perror("SecKeychainItemSetAccessWithPassword", status); + result = 1; + goto cleanup; + } + } + } + + result = 0; + +cleanup: + if(passwordBuf) { + free(passwordBuf); + } + safe_CFRelease(&results); + + return result; +} + + int keychain_find_certificate(int argc, char * const *argv) diff --git a/SecurityTool/keychain_find.h b/SecurityTool/keychain_find.h index db6b6848..53e64259 100644 --- a/SecurityTool/keychain_find.h +++ b/SecurityTool/keychain_find.h @@ -72,6 +72,10 @@ extern int keychain_find_generic_password(int argc, char * const *argv); extern int keychain_delete_generic_password(int argc, char * const *argv); +extern int keychain_set_generic_password_partition_list(int argc, char * const *argv); + +extern int keychain_set_internet_password_partition_list(int argc, char * const *argv); + extern int keychain_find_certificate(int argc, char * const *argv); extern int keychain_dump(int argc, char * const *argv); diff --git a/SecurityTool/keychain_unlock.c b/SecurityTool/keychain_unlock.c index eda34585..eb89a7f7 100644 --- a/SecurityTool/keychain_unlock.c +++ b/SecurityTool/keychain_unlock.c @@ -105,12 +105,7 @@ keychain_unlock(int argc, char * const *argv) if (!password && use_password) { - const char *fmt = "password to unlock %s: "; - const char *name = keychainName ? keychainName : "default"; - char *prompt = malloc(strlen(fmt) + strlen(name)); - sprintf(prompt, fmt, name); - password = getpass(prompt); - free(prompt); + password = prompt_password(keychainName); if (!password) { result = -1; diff --git a/SecurityTool/keychain_utilities.c b/SecurityTool/keychain_utilities.c index ae9fcc20..4d1bf2ef 100644 --- a/SecurityTool/keychain_utilities.c +++ b/SecurityTool/keychain_utilities.c @@ -199,6 +199,24 @@ loser: return result; } +int +print_keychain_version(FILE* stream, SecKeychainRef keychain) +{ + int result = 0; + UInt32 version; + OSStatus status = SecKeychainGetKeychainVersion(keychain, &version); + if(status) { + sec_perror("SecKeychainGetKeychainVersion", status); + result = 1; + goto loser; + } + + fprintf(stream, "%d", version); + +loser: + return result; +} + static void print_cfdata(FILE *stream, CFDataRef data) { @@ -208,7 +226,7 @@ print_cfdata(FILE *stream, CFDataRef data) fprintf(stream, ""); } -static void +void print_cfstring(FILE *stream, CFStringRef string) { if (!string) @@ -277,6 +295,7 @@ print_access(FILE *stream, SecAccessRef access, Boolean interactive) fprintf(stream, " entry %lu:\n authorizations (%lu):", aclix, (unsigned long)tagCount); + bool printPartitionIDList = false; for (tagix = 0; tagix < tagCount; ++tagix) { CSSM_ACL_AUTHORIZATION_TAG tag = tags[tagix]; @@ -345,6 +364,13 @@ print_access(FILE *stream, SecAccessRef access, Boolean interactive) case CSSM_ACL_AUTHORIZATION_CHANGE_OWNER: fputs(" change_owner", stream); break; + case CSSM_ACL_AUTHORIZATION_INTEGRITY: + fputs(" integrity", stream); + break; + case CSSM_ACL_AUTHORIZATION_PARTITION_ID: + fputs(" partition_id", stream); + printPartitionIDList = true; + break; default: fprintf(stream, " tag=%lu", (unsigned long)tag); break; @@ -365,7 +391,12 @@ print_access(FILE *stream, SecAccessRef access, Boolean interactive) fputs(" don't-require-password\n", stream); fputs(" description: ", stream); - print_cfstring(stream, description); + // special case for Partition IDs + if(printPartitionIDList) { + print_partition_id_list(stream, description); + } else { + print_cfstring(stream, description); + } fputc('\n', stream); if (applicationList) @@ -467,6 +498,11 @@ print_keychain_item_attributes(FILE *stream, SecKeychainItemRef item, Boolean sh fputc('\n', stream); if (result) goto loser; + fputs("version: ", stream); + result = print_keychain_version(stream, keychain); + fputc('\n', stream); + if (result) + goto loser; /* First find out the item class. */ status = SecKeychainItemCopyAttributesAndData(item, NULL, &itemClass, NULL, NULL, NULL); @@ -812,6 +848,48 @@ fromHex(const char *hexDigits, CSSM_DATA *data) } } +CFDataRef +cfFromHex(CFStringRef hex) { + // behavior is undefined if you pass in a non-hex string. Don't do that. + char* chex; + size_t len; + + GetCStringFromCFString(hex, &chex, &len); + if(len == 0) { + return NULL; + } + + size_t bytes = len/2; + CFMutableDataRef bin = CFDataCreateMutable(kCFAllocatorDefault, bytes); + CFDataIncreaseLength(bin, bytes); + + if(!bin || CFDataGetLength(bin) != bytes) { + safe_CFRelease(bin); + return NULL; + } + + UInt8* data = CFDataGetMutableBytePtr(bin); + for(size_t i = 0; i < bytes; i++) { + data[i] = (uint8)(hexValue(chex[2*i]) << 4 | hexValue(chex[2*i+1])); + } + + return bin; +} + +CFStringRef cfToHex(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; +} + void safe_CFRelease(void *cfTypeRefPtr) { @@ -822,6 +900,79 @@ safe_CFRelease(void *cfTypeRefPtr) } } + +void +GetCStringFromCFString(CFStringRef cfstring, char** cstr, size_t* len) { + CFIndex strLen = CFStringGetLength(cfstring); + CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(strLen, kCFStringEncodingUTF8); + *cstr = (char *)malloc(bufLen); + if (!CFStringGetCString(cfstring, *cstr, bufLen-1, kCFStringEncodingUTF8)) { + (*cstr)[0]=0; + } + // Handle non-8-bit characters. + *len = strnlen(*cstr, strLen); +} + +CFDictionaryRef makeCFDictionaryFromData(CFDataRef data) +{ + if (data) { + CFPropertyListRef plist = CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL); + if (plist && CFGetTypeID(plist) != CFDictionaryGetTypeID()) { + safe_CFRelease(&plist); + return NULL; + } + return (CFDictionaryRef) plist; + } else { + return NULL; + } +} + +void print_partition_id_list(FILE* stream, CFStringRef description) { + CFDataRef binary = NULL; + CFDictionaryRef partitionList = NULL; + CFArrayRef partitionIDs = NULL; + + if(!description) { + goto error; + } + binary = cfFromHex(description); + if(!binary) { + goto error; + } + partitionList = makeCFDictionaryFromData(binary); + if(!partitionList) { + goto error; + } + + partitionIDs = CFDictionaryGetValue(partitionList, CFSTR("Partitions")); + if(!partitionIDs) { + goto error; + } + + for(size_t i = 0; i < CFArrayGetCount(partitionIDs); i++) { + CFStringRef s = CFArrayGetValueAtIndex(partitionIDs, i); + if(!s) { + goto error; + } + + if(i != 0) { + fprintf(stream, ", "); + } + print_cfstring(stream, s); + } + + goto cleanup; +error: + fprintf(stream, "invalid partition ID: "); + print_cfstring(stream, description); +cleanup: + // don't release partitionIDs; it's an element of partitionList + safe_CFRelease(&binary); + safe_CFRelease(&partitionList); + + return; +} + /* * map a 6-bit binary value to a printable character. */ @@ -959,3 +1110,14 @@ print_buffer_pem(FILE *stream, const char *headerString, UInt32 length, const vo if (headerString) fprintf(stream, "-----END %s-----\n", headerString); } + +char* +prompt_password(const char* keychainName) { + const char *fmt = "password to unlock %s: "; + const char *name = keychainName ? keychainName : "default"; + char *prompt = malloc(strlen(fmt) + strlen(name)); + sprintf(prompt, fmt, name); + char *password = getpass(prompt); + free(prompt); + return password; +} diff --git a/SecurityTool/keychain_utilities.h b/SecurityTool/keychain_utilities.h index f291bb4f..09da8a82 100644 --- a/SecurityTool/keychain_utilities.h +++ b/SecurityTool/keychain_utilities.h @@ -29,6 +29,8 @@ #include #include +#include +#include #ifdef __cplusplus extern "C" { @@ -46,20 +48,34 @@ extern int print_keychain_name(FILE *stream, SecKeychainRef keychain); extern int print_keychain_item_attributes(FILE *stream, SecKeychainItemRef item, Boolean show_data, Boolean show_raw_data, Boolean show_acl, Boolean interactive); +extern void print_cfstring(FILE *stream, CFStringRef string); + extern void print_buffer(FILE *stream, UInt32 length, const void *data); extern void print_buffer_pem(FILE *stream, const char *headerString, UInt32 length, const void *data); extern void print_uint32(FILE* stream, uint32 n); - + extern unsigned char hexValue(char c); extern void fromHex(const char *hexDigits, CSSM_DATA *data); - + +extern CFDataRef cfFromHex(CFStringRef hex); + +extern CFStringRef cfToHex(CFDataRef bin); + +extern CFDictionaryRef makeCFDictionaryFromData(CFDataRef data); + +extern void GetCStringFromCFString(CFStringRef cfstring, char** cstr, size_t* len); + +extern void print_partition_id_list(FILE *stream, CFStringRef description); + extern void safe_CFRelease(void *cfTypeRefPtr); extern void check_obsolete_keychain(const char *kcName); +extern char* prompt_password(const char* keychainName); + #ifdef __cplusplus } #endif diff --git a/SecurityTool/security.c b/SecurityTool/security.c index c1e9f0d9..15b8bacd 100644 --- a/SecurityTool/security.c +++ b/SecurityTool/security.c @@ -271,7 +271,7 @@ const command commands[] = "Find a generic password item."}, { "delete-generic-password", keychain_delete_generic_password, - "[-a account] [-s service] [options...] keychain...]\n" + "[-a account] [-s service] [options...] [keychain...]\n" " -a Match \"account\" string\n" " -c Match \"creator\" (four-character code)\n" " -C Match \"type\" (four-character code)\n" @@ -283,6 +283,21 @@ const command commands[] = "If no keychains are specified to search, the default search list is used.", "Delete a generic password item."}, + { "set-generic-password-partition-list", keychain_set_generic_password_partition_list, + "[-a account] [-s service] [-S partition-list] [-k keychain password] [options...] [keychain]\n" + " -a Match \"account\" string\n" + " -c Match \"creator\" (four-character code)\n" + " -C Match \"type\" (four-character code)\n" + " -D Match \"kind\" string\n" + " -G Match \"value\" string (generic attribute)\n" + " -j Match \"comment\" string\n" + " -l Match \"label\" string\n" + " -s Match \"service\" string\n" + " -S Comma-separated list of allowed partition IDs\n" + " -k The password for the keychain (required)\n" + "If no keychains are specified to search, the default search list is used.", + "Set the partition ID list of a generic password item."}, + { "find-internet-password", keychain_find_internet_password, "[-a account] [-s server] [options...] [-g] [keychain...]\n" " -a Match \"account\" string\n" @@ -319,6 +334,26 @@ const command commands[] = "If no keychains are specified to search, the default search list is used.", "Delete an internet password item."}, + { "set-internet-password-partition-list", keychain_set_internet_password_partition_list, + "[-a account] [-s service] [-S partition-list] [-k keychain password] [options...] [keychain]\n" + " -a Match \"account\" string\n" + " -c Match \"creator\" (four-character code)\n" + " -C Match \"type\" (four-character code)\n" + " -d Match \"securityDomain\" string\n" + " -D Match \"kind\" string\n" + " -j Match \"comment\" string\n" + " -l Match \"label\" string\n" + " -p Match \"path\" string\n" + " -P Match port number\n" + " -r Match \"protocol\" (four-character code)\n" + " -s Match \"server\" string\n" + " -t Match \"authenticationType\" (four-character code)\n" + " -S Comma-separated list of allowed partition IDs" + " -k password for keychain (required)" + + "If no keychains are specified to search, the default search list is used.", + "Set the partition ID list of a internet password item."}, + { "find-certificate", keychain_find_certificate, "[-a] [-c name] [-e emailAddress] [-m] [-p] [-Z] [keychain...]\n" " -a Find all matching certificates, not just the first one\n" diff --git a/SecurityTool/sub_commands.h b/SecurityTool/sub_commands.h index 39fd218c..da20e5f1 100644 --- a/SecurityTool/sub_commands.h +++ b/SecurityTool/sub_commands.h @@ -26,4 +26,5 @@ // This file can't be once, it gets included multiple times to get definitions and declarations. #include "Security/Tool/SecurityCommands.h" -#include "SOSCircle/Tool/SOSCommands.h" +#include "SOSCircle/Tool/keychain_sync.h" +#include "SOSCircle/Tool/keychain_log.h" diff --git a/codesign_wrapper/codesign_wrapper.c b/codesign_wrapper/codesign_wrapper.c index 87f1a629..3b0283b7 100644 --- a/codesign_wrapper/codesign_wrapper.c +++ b/codesign_wrapper/codesign_wrapper.c @@ -795,6 +795,21 @@ struct securityd *gSecurityd; void securityd_init(); CFArrayRef SecAccessGroupsGetCurrent(void); +SecurityClient * +SecSecurityClientGet(void) +{ + static SecurityClient client; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + client.task = SecTaskGetSelf(); + client.accessGroups = NULL; + client.allowSystemKeychain = false; + client.allowSyncBubbleKeychain = false; + client.isNetworkExtension = false, + }); + return &client; +} + CFArrayRef SecAccessGroupsGetCurrent(void) { return NULL; } diff --git a/libsecurity_smime/lib/SecCmsBase.h b/libsecurity_smime/lib/SecCmsBase.h index 0381c229..eeb5ad82 100644 --- a/libsecurity_smime/lib/SecCmsBase.h +++ b/libsecurity_smime/lib/SecCmsBase.h @@ -423,7 +423,7 @@ typedef enum { /* New PSM certificate management OIDs */ SEC_OID_CERT_RENEWAL_LOCATOR = 177, SEC_OID_NS_CERT_EXT_SCOPE_OF_USE = 178, - + /* CMS (RFC2630) OIDs */ SEC_OID_CMS_EPHEMERAL_STATIC_DIFFIE_HELLMAN = 179, SEC_OID_CMS_3DES_KEY_WRAP = 180, @@ -444,19 +444,43 @@ typedef enum { SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE = 190, - SEC_OID_SHA256 = 191, - SEC_OID_SHA384 = 192, - SEC_OID_SHA512 = 193, - - SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 194, - SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 195, - SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 196, - - SEC_OID_AES_128_KEY_WRAP = 197, - SEC_OID_AES_192_KEY_WRAP = 198, - SEC_OID_AES_256_KEY_WRAP = 199, - - SEC_OID_SHA224 = 200, + SEC_OID_SHA224 = 191, + SEC_OID_SHA256 = 192, + SEC_OID_SHA384 = 193, + SEC_OID_SHA512 = 194, + + SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 195, + SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 196, + SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 197, + + SEC_OID_AES_128_KEY_WRAP = 198, + SEC_OID_AES_192_KEY_WRAP = 199, + SEC_OID_AES_256_KEY_WRAP = 200, + + /* eContentType set by client and not understood by this library; treated + * like SEC_OID_PKCS7_DATA, except the caller's OID is encoded. */ + SEC_OID_OTHER = 201, + + /* ECDSA */ + SEC_OID_EC_PUBLIC_KEY = 202, + SEC_OID_ECDSA_WithSHA1 = 203, + SEC_OID_DH_SINGLE_STD_SHA1KDF = 204, + SEC_OID_SECP_256_R1 = 205, + SEC_OID_SECP_384_R1 = 206, + SEC_OID_SECP_521_R1 = 207, + + /* RFC 3161 Timestamping OIDs */ + SEC_OID_PKCS9_ID_CT_TSTInfo = 208, + SEC_OID_PKCS9_TIMESTAMP_TOKEN = 209, + SEC_OID_PKCS9_SIGNING_CERTIFICATE = 210, + + /* ECDSA with SHA2 */ + SEC_OID_ECDSA_WITH_SHA256 = 211, + SEC_OID_ECDSA_WITH_SHA384 = 212, + SEC_OID_ECDSA_WITH_SHA512 = 213, + + /* Apple CMS Attribute */ + SEC_OID_APPLE_HASH_AGILITY = 214, SEC_OID_TOTAL } SECOidTag; diff --git a/libsecurity_smime/lib/SecCmsSignerInfo.h b/libsecurity_smime/lib/SecCmsSignerInfo.h index 98b76f13..19cb5737 100644 --- a/libsecurity_smime/lib/SecCmsSignerInfo.h +++ b/libsecurity_smime/lib/SecCmsSignerInfo.h @@ -90,6 +90,16 @@ SecCmsSignerInfoGetCertList(SecCmsSignerInfoRef signerinfo); extern OSStatus SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime); +/*! + @function + @abstract Return the data in the signed Codesigning Hash Agility attribute. + @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value + @discussion Returns a CFDataRef containing the value of the attribute + @result A return value of SECFailure is an error. + */ +extern OSStatus +SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata); + /*! @function @abstract Return the signing cert of a CMS signerInfo. @@ -165,6 +175,14 @@ extern OSStatus SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, SECOidTag digestalg, SecIdentityRef identity); +/*! + @function + @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed Apple code signatures. +*/ +OSStatus +SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue); + /*! @function @abstract The following needs to be done in the S/MIME layer code after signature of a signerinfo has been verified. diff --git a/libsecurity_smime/lib/cmsattr.c b/libsecurity_smime/lib/cmsattr.c index 90b927e5..05d0033b 100644 --- a/libsecurity_smime/lib/cmsattr.c +++ b/libsecurity_smime/lib/cmsattr.c @@ -255,6 +255,7 @@ cms_attr_choose_attr_value_template(void *src_or_dest, Boolean encoding, const c theTemplate = SEC_ASN1_GET(kSecAsn1ObjectIDTemplate); break; case SEC_OID_PKCS9_MESSAGE_DIGEST: + case SEC_OID_APPLE_HASH_AGILITY: encoded = PR_FALSE; theTemplate = SEC_ASN1_GET(kSecAsn1OctetStringTemplate); break; diff --git a/libsecurity_smime/lib/cmsrecinfo.c b/libsecurity_smime/lib/cmsrecinfo.c index 77f4814d..f43e9bf5 100644 --- a/libsecurity_smime/lib/cmsrecinfo.c +++ b/libsecurity_smime/lib/cmsrecinfo.c @@ -471,6 +471,7 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul SecCmsOriginatorIdentifierOrKey *oiok; #endif /* 0 */ const SECAlgorithmID *algid; + SECAlgorithmID freeAlgID; PLArenaPool *poolp; SecCmsKeyTransRecipientInfoEx *extra = NULL; Boolean usesSubjKeyID; @@ -484,7 +485,6 @@ SecCmsRecipientInfoWrapBulkKey(SecCmsRecipientInfoRef ri, SecSymmetricKeyRef bul if (rv) return SECFailure; #else - SECAlgorithmID freeAlgID; const SecAsn1AlgId *length_data_swapped = (const SecAsn1AlgId *)SecCertificateGetPublicKeyAlgorithm(cert); freeAlgID.algorithm.Length = (size_t)length_data_swapped->algorithm.Data; freeAlgID.algorithm.Data = (uint8_t *)length_data_swapped->algorithm.Length; diff --git a/libsecurity_smime/lib/cmssiginfo.c b/libsecurity_smime/lib/cmssiginfo.c index 02dd9d61..3ae7c0f3 100644 --- a/libsecurity_smime/lib/cmssiginfo.c +++ b/libsecurity_smime/lib/cmssiginfo.c @@ -59,6 +59,7 @@ #include #include #include +#include #define HIDIGIT(v) (((v) / 10) + '0') @@ -822,6 +823,44 @@ SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime) return SECSuccess; } +/*! + @function + @abstract Return the data in the signed Codesigning Hash Agility attribute. + @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value + @discussion Returns a CFDataRef containing the value of the attribute + @result A return value of errSecInternal is an error trying to look up the oid. + A status value of success with null result data indicates the attribute was not present. + */ +OSStatus +SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata) +{ + SecCmsAttribute *attr; + SecAsn1Item *value; + + if (sinfo == NULL || sdata == NULL) + return errSecParam; + + *sdata = NULL; + + if (sinfo->hashAgilityAttrValue != NULL) { + *sdata = sinfo->hashAgilityAttrValue; /* cached copy */ + return SECSuccess; + } + + attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_APPLE_HASH_AGILITY, PR_TRUE); + + /* attribute not found */ + if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL) + return SECSuccess; + + sinfo->hashAgilityAttrValue = CFDataCreate(NULL, value->Data, value->Length); /* make cached copy */ + if (sinfo->hashAgilityAttrValue) { + *sdata = sinfo->hashAgilityAttrValue; + return SECSuccess; + } + return errSecAllocate; +} + /* * Return the signing cert of a CMS signerInfo. * @@ -1205,6 +1244,54 @@ SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo, return SECFailure; } +/*! + @function + @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo". + @discussion This is expected to be included in outgoing signed Apple code signatures. + */ +OSStatus +SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue) +{ + SecCmsAttribute *attr; + PLArenaPool *poolp = signerinfo->signedData->contentInfo.cmsg->poolp; + void *mark = PORT_ArenaMark(poolp); + OSStatus status = SECFailure; + + /* The value is required for this attribute. */ + if (!attrValue) { + status = errSecParam; + goto loser; + } + + /* + * SecCmsAttributeCreate makes a copy of the data in value, so + * we don't need to copy into the CSSM_DATA struct. + */ + SecAsn1Item value; + value.Length = CFDataGetLength(attrValue); + value.Data = (uint8_t *)CFDataGetBytePtr(attrValue); + + if ((attr = SecCmsAttributeCreate(poolp, + SEC_OID_APPLE_HASH_AGILITY, + &value, + PR_FALSE)) == NULL) { + status = errSecAllocate; + goto loser; + } + + if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) { + status = errSecInternal; + goto loser; + } + + PORT_ArenaUnmark(poolp, mark); + return SECSuccess; + +loser: + PORT_ArenaRelease(poolp, mark); + return status; +} + /* * XXXX the following needs to be done in the S/MIME layer code * after signature of a signerinfo is verified diff --git a/libsecurity_smime/lib/cmstpriv.h b/libsecurity_smime/lib/cmstpriv.h index e6fc277d..e8d1e33d 100644 --- a/libsecurity_smime/lib/cmstpriv.h +++ b/libsecurity_smime/lib/cmstpriv.h @@ -206,6 +206,7 @@ struct SecCmsSignerInfoStr { SecCmsVerificationStatus verificationStatus; SecPrivateKeyRef signingKey; /* Used if we're using subjKeyID*/ SecPublicKeyRef pubKey; + CFDataRef hashAgilityAttrValue; }; #define SEC_CMS_SIGNER_INFO_VERSION_ISSUERSN 1 /* what we *create* */ #define SEC_CMS_SIGNER_INFO_VERSION_SUBJKEY 3 /* what we *create* */ diff --git a/libsecurity_smime/lib/crypto-embedded.c b/libsecurity_smime/lib/crypto-embedded.c index 3bee7683..77bf3006 100644 --- a/libsecurity_smime/lib/crypto-embedded.c +++ b/libsecurity_smime/lib/crypto-embedded.c @@ -1,10 +1,24 @@ /* - * crypto-embedded.c - * libsecurity_smime + * Copyright (c) 2008-2011,2013,2015 Apple Inc. All Rights Reserved. * - * Created by Conrad Sauerwald on 2/7/08. - * Copyright (c) 2008-2011,2013 Apple Inc. All Rights Reserved. + * @APPLE_LICENSE_HEADER_START@ * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ */ #include @@ -28,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -83,11 +98,44 @@ CERT_VerifyCert(SecKeychainRef keychainOrArray __unused, CFArrayRef certs, return SECSuccess; loser: if (trust) - CFRelease(trust); + CFRelease(trust); return rv; } +static CFTypeRef CERT_FindItemInAllAvailableKeychains(CFDictionaryRef query) { + CFTypeRef item = NULL; + CFMutableDictionaryRef q = NULL; + CFDictionaryRef whoAmI = NULL; + CFErrorRef error = NULL; + CFDataRef musr = NULL; + const uint8_t activeUserUuid[16] = "\xA7\x5A\x3A\x35\xA5\x57\x4B\x10\xBE\x2E\x83\x94\x7E\x4A\x34\x72"; + + /* Do the standard keychain query */ + require_quiet(errSecItemNotFound == SecItemCopyMatching(query, &item), out); + + /* No item found. Can caller use the system keychain? */ + whoAmI = _SecSecuritydCopyWhoAmI(&error); + require_quiet(NULL == error && whoAmI && CFDictionaryGetValue(whoAmI, CFSTR("status")), out); + musr = CFDictionaryGetValue(whoAmI, CFSTR("musr")); + /* Caller has system-keychain entitlement, is in multi-user mode, and is an active user. */ + if (CFDictionaryGetValue(whoAmI, CFSTR("system-keychain")) && musr && + (16 == CFDataGetLength(musr)) && (0 == memcmp(activeUserUuid,CFDataGetBytePtr(musr),12))) { + q = CFDictionaryCreateMutableCopy(NULL, CFDictionaryGetCount(query) + 1, query); + CFDictionaryAddValue(q, kSecUseSystemKeychain, kCFBooleanTrue); + SecItemCopyMatching(q, &item); + } + +out: + if (q) + CFRelease(q); + if (whoAmI) + CFRelease(whoAmI); + if (error) + CFRelease(error); + + return item; +} SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win) @@ -97,7 +145,7 @@ SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, const void *values[] = { kSecClassCertificate, nickname_cfstr }; CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL); CFTypeRef result = NULL; - SecItemCopyMatching(query, &result); + result = CERT_FindItemInAllAvailableKeychains(query); CFRelease(query); CFRelease(nickname_cfstr); return (SecCertificateRef)result; @@ -257,7 +305,7 @@ static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef cl const void *keys[] = { kSecClass, kSecAttrIssuer, kSecAttrSerialNumber, kSecReturnRef }; const void *values[] = { class, issuer, serial, kCFBooleanTrue }; query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL); - require_noerr_quiet(SecItemCopyMatching(query, (CFTypeRef*)&ident), out); + ident = CERT_FindItemInAllAvailableKeychains(query); out: if (query) @@ -289,9 +337,8 @@ SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray __unus const void *keys[] = { kSecClass, kSecAttrSubjectKeyID, kSecReturnRef }; const void *values[] = { kSecClassIdentity, subjectkeyid, kCFBooleanTrue }; query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL); - require_noerr_quiet(SecItemCopyMatching(query, (CFTypeRef*)&ident), out); + ident = (SecIdentityRef) CERT_FindItemInAllAvailableKeychains(query); -out: if (query) CFRelease(query); if (subjectkeyid) diff --git a/libsecurity_smime/lib/secoid.c b/libsecurity_smime/lib/secoid.c index 5976887b..1eed5d7b 100644 --- a/libsecurity_smime/lib/secoid.c +++ b/libsecurity_smime/lib/secoid.c @@ -129,6 +129,7 @@ #define PKCS9_CERT_TYPES PKCS9, 0x16 #define PKCS9_CRL_TYPES PKCS9, 0x17 #define PKCS9_SMIME_IDS PKCS9, 0x10 +#define PKCS9_SMIME_CTYPE PKCS9_SMIME_IDS, 1 #define PKCS9_SMIME_ATTRS PKCS9_SMIME_IDS, 2 #define PKCS9_SMIME_ALGS PKCS9_SMIME_IDS, 3 #define PKCS12_VERSION1 PKCS12, 0x0a @@ -161,6 +162,26 @@ /* { 1.3.6.1.4.1.311 } */ #define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37 +/* ECDSA OIDs from X9.62 */ +#define ANSI_X9_62 0x2A, 0x86, 0x48, 0xCE, 0x3D +#define ANSI_X9_62_FIELD_TYPE ANSI_X9_62, 1 +#define ANSI_X9_62_PUBKEY_TYPE ANSI_X9_62, 2 +#define ANSI_X9_62_SIG_TYPE ANSI_X9_62, 4 +#define ECDSA_WITH_SHA2 ANSI_X9_62_SIG_TYPE, 3 + +/* X9.63 schemes */ +#define ANSI_X9_63 0x2B, 0x81, 0x05, 0x10, 0x86, 0x48, 0x3F +#define ANSI_X9_63_SCHEME ANSI_X9_63, 0 + +/* ECDH curves */ +#define CERTICOM_ELL_CURVE 0x2B, 0x81, 0x04, 0x00 + +/* Apple OID sapce */ +/* 1.2.840.113635 */ +#define APPLE_OID 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x63 +#define APPLE_DATA_SECURITY APPLE_OID, 0x64 +#define APPLE_CMS_ATTRIBUTES APPLE_DATA_SECURITY, 0x9 + #define CONST_OID static const unsigned char CONST_OID null_oid[] = { }; @@ -232,6 +253,10 @@ CONST_OID cmsRC2wrap[] = { PKCS9_SMIME_ALGS, 7 }; CONST_OID smimeEncryptionKeyPreference[] = { PKCS9_SMIME_ATTRS, 11 }; CONST_OID ms_smimeEncryptionKeyPreference[] = { MICROSOFT_OID, 0x10, 0x4 }; +CONST_OID smimeSigningCertificate[] = { PKCS9_SMIME_ATTRS, 12 }; +CONST_OID smimeTimeStampToken[] = { PKCS9_SMIME_ATTRS, 14 }; +CONST_OID smimeTimeStampTokenInfo[] = { PKCS9_SMIME_CTYPE, 0x04 }; + CONST_OID x520CommonName[] = { X520_ATTRIBUTE_TYPE, 3 }; CONST_OID x520CountryName[] = { X520_ATTRIBUTE_TYPE, 6 }; CONST_OID x520LocalityName[] = { X520_ATTRIBUTE_TYPE, 7 }; @@ -436,6 +461,30 @@ CONST_OID sha384[] = { SHAXXX, 2 }; CONST_OID sha512[] = { SHAXXX, 3 }; CONST_OID sha224[] = { SHAXXX, 4 }; +CONST_OID ecdsaWithSHA1[] = { ANSI_X9_62_SIG_TYPE, 1 }; +CONST_OID ecdsaWithSHA256[] = { ECDSA_WITH_SHA2, 2 }; +CONST_OID ecdsaWithSHA384[] = { ECDSA_WITH_SHA2, 3 }; +CONST_OID ecdsaWithSHA512[] = { ECDSA_WITH_SHA2, 4 }; +CONST_OID ecPublicKey[] = { ANSI_X9_62_PUBKEY_TYPE, 1 }; +/* This OID doesn't appear in a CMS msg */ +CONST_OID ecdsaSig[] = { ANSI_X9_62_SIG_TYPE }; + +/* ECDH curves */ +CONST_OID secp256r1[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }; +CONST_OID secp384r1[] = { CERTICOM_ELL_CURVE, 0x22 }; +CONST_OID secp521r1[] = { CERTICOM_ELL_CURVE, 0x23 }; + +/* RFC 3278 */ +CONST_OID dhSinglePassStdDHsha1kdf[] = {ANSI_X9_63_SCHEME, 2 }; +CONST_OID dhSinglePassCofactorDHsha1kdf[] = {ANSI_X9_63_SCHEME, 3 }; +CONST_OID mqvSinglePassSha1kdf[] = {ANSI_X9_63_SCHEME, 4 }; + +/* Apple Hash Agility */ +CONST_OID appleHashAgility[] = {APPLE_CMS_ATTRIBUTES, 1}; + +/* a special case: always associated with a caller-specified OID */ +CONST_OID noOid[] = { 0 }; + #define OI(x) { sizeof x, (uint8_t *)x } #ifndef SECOID_NO_STRINGS #if USE_CDSA_CRYPTO @@ -447,164 +496,8 @@ CONST_OID sha224[] = { SHAXXX, 4 }; #define OD(oid,tag,desc,mech,ext) { OI(oid), tag, 0, mech, ext } #endif -#if 0 // !USE_CDSA_CRYPTO - -enum { - CSSM_ALGID_NONE = 0, - CSSM_ALGID_CUSTOM = CSSM_ALGID_NONE + 1, - CSSM_ALGID_DH = CSSM_ALGID_NONE + 2, - CSSM_ALGID_PH = CSSM_ALGID_NONE + 3, - CSSM_ALGID_KEA = CSSM_ALGID_NONE + 4, - CSSM_ALGID_MD2 = CSSM_ALGID_NONE + 5, - CSSM_ALGID_MD4 = CSSM_ALGID_NONE + 6, - CSSM_ALGID_MD5 = CSSM_ALGID_NONE + 7, - CSSM_ALGID_SHA1 = CSSM_ALGID_NONE + 8, - CSSM_ALGID_NHASH = CSSM_ALGID_NONE + 9, - CSSM_ALGID_HAVAL = CSSM_ALGID_NONE + 10, - CSSM_ALGID_RIPEMD = CSSM_ALGID_NONE + 11, - CSSM_ALGID_IBCHASH = CSSM_ALGID_NONE + 12, - CSSM_ALGID_RIPEMAC = CSSM_ALGID_NONE + 13, - CSSM_ALGID_DES = CSSM_ALGID_NONE + 14, - CSSM_ALGID_DESX = CSSM_ALGID_NONE + 15, - CSSM_ALGID_RDES = CSSM_ALGID_NONE + 16, - CSSM_ALGID_3DES_3KEY_EDE = CSSM_ALGID_NONE + 17, - CSSM_ALGID_3DES_2KEY_EDE = CSSM_ALGID_NONE + 18, - CSSM_ALGID_3DES_1KEY_EEE = CSSM_ALGID_NONE + 19, - CSSM_ALGID_3DES_3KEY = CSSM_ALGID_3DES_3KEY_EDE, - CSSM_ALGID_3DES_3KEY_EEE = CSSM_ALGID_NONE + 20, - CSSM_ALGID_3DES_2KEY = CSSM_ALGID_3DES_2KEY_EDE, - CSSM_ALGID_3DES_2KEY_EEE = CSSM_ALGID_NONE + 21, - CSSM_ALGID_3DES_1KEY = CSSM_ALGID_3DES_3KEY_EEE, - CSSM_ALGID_IDEA = CSSM_ALGID_NONE + 22, - CSSM_ALGID_RC2 = CSSM_ALGID_NONE + 23, - CSSM_ALGID_RC5 = CSSM_ALGID_NONE + 24, - CSSM_ALGID_RC4 = CSSM_ALGID_NONE + 25, - CSSM_ALGID_SEAL = CSSM_ALGID_NONE + 26, - CSSM_ALGID_CAST = CSSM_ALGID_NONE + 27, - CSSM_ALGID_BLOWFISH = CSSM_ALGID_NONE + 28, - CSSM_ALGID_SKIPJACK = CSSM_ALGID_NONE + 29, - CSSM_ALGID_LUCIFER = CSSM_ALGID_NONE + 30, - CSSM_ALGID_MADRYGA = CSSM_ALGID_NONE + 31, - CSSM_ALGID_FEAL = CSSM_ALGID_NONE + 32, - CSSM_ALGID_REDOC = CSSM_ALGID_NONE + 33, - CSSM_ALGID_REDOC3 = CSSM_ALGID_NONE + 34, - CSSM_ALGID_LOKI = CSSM_ALGID_NONE + 35, - CSSM_ALGID_KHUFU = CSSM_ALGID_NONE + 36, - CSSM_ALGID_KHAFRE = CSSM_ALGID_NONE + 37, - CSSM_ALGID_MMB = CSSM_ALGID_NONE + 38, - CSSM_ALGID_GOST = CSSM_ALGID_NONE + 39, - CSSM_ALGID_SAFER = CSSM_ALGID_NONE + 40, - CSSM_ALGID_CRAB = CSSM_ALGID_NONE + 41, - CSSM_ALGID_RSA = CSSM_ALGID_NONE + 42, - CSSM_ALGID_DSA = CSSM_ALGID_NONE + 43, - CSSM_ALGID_MD5WithRSA = CSSM_ALGID_NONE + 44, - CSSM_ALGID_MD2WithRSA = CSSM_ALGID_NONE + 45, - CSSM_ALGID_ElGamal = CSSM_ALGID_NONE + 46, - CSSM_ALGID_MD2Random = CSSM_ALGID_NONE + 47, - CSSM_ALGID_MD5Random = CSSM_ALGID_NONE + 48, - CSSM_ALGID_SHARandom = CSSM_ALGID_NONE + 49, - CSSM_ALGID_DESRandom = CSSM_ALGID_NONE + 50, - CSSM_ALGID_SHA1WithRSA = CSSM_ALGID_NONE + 51, - CSSM_ALGID_CDMF = CSSM_ALGID_NONE + 52, - CSSM_ALGID_CAST3 = CSSM_ALGID_NONE + 53, - CSSM_ALGID_CAST5 = CSSM_ALGID_NONE + 54, - CSSM_ALGID_GenericSecret = CSSM_ALGID_NONE + 55, - CSSM_ALGID_ConcatBaseAndKey = CSSM_ALGID_NONE + 56, - CSSM_ALGID_ConcatKeyAndBase = CSSM_ALGID_NONE + 57, - CSSM_ALGID_ConcatBaseAndData = CSSM_ALGID_NONE + 58, - CSSM_ALGID_ConcatDataAndBase = CSSM_ALGID_NONE + 59, - CSSM_ALGID_XORBaseAndData = CSSM_ALGID_NONE + 60, - CSSM_ALGID_ExtractFromKey = CSSM_ALGID_NONE + 61, - CSSM_ALGID_SSL3PreMasterGen = CSSM_ALGID_NONE + 62, - CSSM_ALGID_SSL3MasterDerive = CSSM_ALGID_NONE + 63, - CSSM_ALGID_SSL3KeyAndMacDerive = CSSM_ALGID_NONE + 64, - CSSM_ALGID_SSL3MD5_MAC = CSSM_ALGID_NONE + 65, - CSSM_ALGID_SSL3SHA1_MAC = CSSM_ALGID_NONE + 66, - CSSM_ALGID_PKCS5_PBKDF1_MD5 = CSSM_ALGID_NONE + 67, - CSSM_ALGID_PKCS5_PBKDF1_MD2 = CSSM_ALGID_NONE + 68, - CSSM_ALGID_PKCS5_PBKDF1_SHA1 = CSSM_ALGID_NONE + 69, - CSSM_ALGID_WrapLynks = CSSM_ALGID_NONE + 70, - CSSM_ALGID_WrapSET_OAEP = CSSM_ALGID_NONE + 71, - CSSM_ALGID_BATON = CSSM_ALGID_NONE + 72, - CSSM_ALGID_ECDSA = CSSM_ALGID_NONE + 73, - CSSM_ALGID_MAYFLY = CSSM_ALGID_NONE + 74, - CSSM_ALGID_JUNIPER = CSSM_ALGID_NONE + 75, - CSSM_ALGID_FASTHASH = CSSM_ALGID_NONE + 76, - CSSM_ALGID_3DES = CSSM_ALGID_NONE + 77, - CSSM_ALGID_SSL3MD5 = CSSM_ALGID_NONE + 78, - CSSM_ALGID_SSL3SHA1 = CSSM_ALGID_NONE + 79, - CSSM_ALGID_FortezzaTimestamp = CSSM_ALGID_NONE + 80, - CSSM_ALGID_SHA1WithDSA = CSSM_ALGID_NONE + 81, - CSSM_ALGID_SHA1WithECDSA = CSSM_ALGID_NONE + 82, - CSSM_ALGID_DSA_BSAFE = CSSM_ALGID_NONE + 83, - CSSM_ALGID_ECDH = CSSM_ALGID_NONE + 84, - CSSM_ALGID_ECMQV = CSSM_ALGID_NONE + 85, - CSSM_ALGID_PKCS12_SHA1_PBE = CSSM_ALGID_NONE + 86, - CSSM_ALGID_ECNRA = CSSM_ALGID_NONE + 87, - CSSM_ALGID_SHA1WithECNRA = CSSM_ALGID_NONE + 88, - CSSM_ALGID_ECES = CSSM_ALGID_NONE + 89, - CSSM_ALGID_ECAES = CSSM_ALGID_NONE + 90, - CSSM_ALGID_SHA1HMAC = CSSM_ALGID_NONE + 91, - CSSM_ALGID_FIPS186Random = CSSM_ALGID_NONE + 92, - CSSM_ALGID_ECC = CSSM_ALGID_NONE + 93, - CSSM_ALGID_MQV = CSSM_ALGID_NONE + 94, - CSSM_ALGID_NRA = CSSM_ALGID_NONE + 95, - CSSM_ALGID_IntelPlatformRandom = CSSM_ALGID_NONE + 96, - CSSM_ALGID_UTC = CSSM_ALGID_NONE + 97, - CSSM_ALGID_HAVAL3 = CSSM_ALGID_NONE + 98, - CSSM_ALGID_HAVAL4 = CSSM_ALGID_NONE + 99, - CSSM_ALGID_HAVAL5 = CSSM_ALGID_NONE + 100, - CSSM_ALGID_TIGER = CSSM_ALGID_NONE + 101, - CSSM_ALGID_MD5HMAC = CSSM_ALGID_NONE + 102, - CSSM_ALGID_PKCS5_PBKDF2 = CSSM_ALGID_NONE + 103, - CSSM_ALGID_RUNNING_COUNTER = CSSM_ALGID_NONE + 104, - CSSM_ALGID_LAST = CSSM_ALGID_NONE + 0x7FFFFFFF, -/* All algorithms IDs that are vendor specific, and not - part of the CSSM specification should be defined relative - to CSSM_ALGID_VENDOR_DEFINED. */ - CSSM_ALGID_VENDOR_DEFINED = CSSM_ALGID_NONE + 0x80000000 -}; - -enum -{ - CSSM_ALGID_APPLE_YARROW = CSSM_ALGID_VENDOR_DEFINED, - CSSM_ALGID_AES, /* RijnDael */ - CSSM_ALGID_FEE, /* FEE Key Generation */ - CSSM_ALGID_FEE_MD5, /* FEE/ElGamal signature w/ MD5 -hash */ - CSSM_ALGID_FEE_SHA1, /* FEE/ElGamal signature w/ SHA1 hash */ - CSSM_ALGID_FEED, /* 1:1 FEE asymmetric encryption - */ - CSSM_ALGID_FEEDEXP, /* 2:1 FEE asymmetric encryption - */ - CSSM_ALGID_ASC, /* Apple Secure Compression */ - CSSM_ALGID_SHA1HMAC_LEGACY, /* HMAC/SHA1, legacy compatible */ - CSSM_ALGID_KEYCHAIN_KEY, /* derive or manipulate keychain master -keys */ - CSSM_ALGID_PKCS12_PBE_ENCR, /* PKCS12, encrypt/decrypt key */ - CSSM_ALGID_PKCS12_PBE_MAC, /* PKCS12, MAC key */ - CSSM_ALGID_SECURE_PASSPHRASE, /* passphrase acquired by SecurityServer - */ - CSSM_ALGID_PBE_OPENSSL_MD5, /* traditional openssl key derivation */ - CSSM_ALGID_SHA256, /* 256-bit SHA2 */ - CSSM_ALGID_SHA384, /* 384-bit SHA2 */ - CSSM_ALGID_SHA512, /* 512-bit SHA2 */ - CSSM_ALGID_ENTROPY_DEFAULT, /* default entropy source of (CSP) devic -e, if any */ - CSSM_ALGID_SHA224, /* SHA2, 224 bit */ - CSSM_ALGID_SHA224WithRSA, /* RSA signature on SHA224 digest */ - CSSM_ALGID_SHA256WithRSA, /* RSA signature on SHA256 digest */ - CSSM_ALGID_SHA384WithRSA, /* RSA signature on SHA384 digest */ - CSSM_ALGID_SHA512WithRSA, /* RSA signature on SHA512 digest */ - CSSM_ALGID_OPENSSH1, /* OpenSSH v1 RSA key wrapping */ - CSSM_ALGID__FIRST_UNUSED -}; - -#endif - - /* - NOTE: the order of these entries must mach the SECOidTag enum in secoidt.h! + NOTE: the order of these entries must match the SECOidTag enum in secoidt.h! @@@ We are sticking a enum type in a field of type SecAsn1AlgId, which is defined as: typedef struct { @@ -1186,6 +1079,7 @@ static const SECOidData oids[] = { "AES-256-ECB", CSSM_ALGID_AES, INVALID_CERT_EXTENSION ), OD( aes256_CBC, SEC_OID_AES_256_CBC, "AES-256-CBC", CSSM_ALGID_AES, INVALID_CERT_EXTENSION ), + /* More bogus DSA OIDs */ OD( sdn702DSASignature, SEC_OID_SDN702_DSA_SIGNATURE, "SDN.702 DSA Signature", CSSM_ALGID_SHA1WithDSA, INVALID_CERT_EXTENSION ), @@ -1194,6 +1088,8 @@ static const SECOidData oids[] = { SEC_OID_MS_SMIME_ENCRYPTION_KEY_PREFERENCE, "Microsoft S/MIME Encryption Key Preference", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION ), + + OD( sha224, SEC_OID_SHA224, "SHA-224", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), OD( sha256, SEC_OID_SHA256, "SHA-256", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), OD( sha384, SEC_OID_SHA384, "SHA-384", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), OD( sha512, SEC_OID_SHA512, "SHA-512", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), @@ -1215,7 +1111,57 @@ static const SECOidData oids[] = { OD( aes256_KEY_WRAP, SEC_OID_AES_256_KEY_WRAP, "AES-256 Key Wrap", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), - OD( sha224, SEC_OID_SHA224, "SHA-224", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + /* caller-specified OID for eContentType */ + OD( noOid, SEC_OID_OTHER, + "Caller-specified eContentType", CSSM_ALGID_NONE, INVALID_CERT_EXTENSION), + + OD( ecPublicKey, SEC_OID_EC_PUBLIC_KEY, + "ECDSA Public Key", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + OD( ecdsaWithSHA1, SEC_OID_ECDSA_WithSHA1, + "SHA-1 With ECDSA", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + OD( dhSinglePassStdDHsha1kdf, SEC_OID_DH_SINGLE_STD_SHA1KDF, + "ECDH With SHA1 KDF", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + OD( secp256r1, SEC_OID_SECP_256_R1, + "secp256r1", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + OD( secp384r1, SEC_OID_SECP_384_R1, + "secp384r1", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + OD( secp521r1, SEC_OID_SECP_521_R1, + "secp521r1", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + + OD( smimeTimeStampTokenInfo, SEC_OID_PKCS9_ID_CT_TSTInfo, + "id-ct-TSTInfo", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + + OD( smimeTimeStampToken, SEC_OID_PKCS9_TIMESTAMP_TOKEN, + "id-aa-timeStampToken", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + + OD( smimeSigningCertificate, SEC_OID_PKCS9_SIGNING_CERTIFICATE, + "id-aa-signing-certificate", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION ), + + /* ECDSA with SHA2 */ + OD( ecdsaWithSHA256, SEC_OID_ECDSA_WITH_SHA256, + "ECDSA With SHA-256", CSSM_ALGID_SHA256WithECDSA, + INVALID_CERT_EXTENSION ), + OD( ecdsaWithSHA384, SEC_OID_ECDSA_WITH_SHA384, + "ECDSA With SHA-384", CSSM_ALGID_SHA384WithECDSA, + INVALID_CERT_EXTENSION ), + OD( ecdsaWithSHA512, SEC_OID_ECDSA_WITH_SHA512, + "ECDSA With SHA-512", CSSM_ALGID_SHA512WithECDSA, + INVALID_CERT_EXTENSION ), + + /* Apple Hash Agility */ + OD( appleHashAgility, SEC_OID_APPLE_HASH_AGILITY, + "appleCodesigningHashAgilityAttribute", CSSM_ALGID_NONE, + INVALID_CERT_EXTENSION), + }; /* diff --git a/libsecurity_smime/lib/security_smime.exp b/libsecurity_smime/lib/security_smime.exp index 8290ccdc..c677ee5f 100644 --- a/libsecurity_smime/lib/security_smime.exp +++ b/libsecurity_smime/lib/security_smime.exp @@ -98,6 +98,7 @@ _SecCmsSignerInfoAddMSSMIMEEncKeyPrefs _SecCmsSignerInfoAddSMIMECaps _SecCmsSignerInfoAddSMIMEEncKeyPrefs _SecCmsSignerInfoAddSigningTime +_SecCmsSignerInfoAddAppleCodesigningHashAgility _SecCmsSignerInfoCreate _SecCmsSignerInfoCreateWithSubjKeyID _SecCmsSignerInfoGetCertList @@ -107,6 +108,7 @@ _SecCmsSignerInfoGetSignerCommonName _SecCmsSignerInfoGetSignerEmailAddress _SecCmsSignerInfoGetSigningCertificate _SecCmsSignerInfoGetSigningTime +_SecCmsSignerInfoGetAppleCodesigningHashAgility _SecCmsSignerInfoGetVerificationStatus _SecCmsSignerInfoIncludeCerts _SecCmsSignerInfoSaveSMIMEProfile diff --git a/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj b/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj index 89cd8376..4e891e66 100644 --- a/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj +++ b/libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj @@ -582,7 +582,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - GCC_OPTIMIZATION_LEVEL = 1; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; @@ -671,6 +671,7 @@ 79BDD2B10D60CA06000D84D3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + COPY_PHASE_STRIP = NO; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; HEADER_SEARCH_PATHS = ( "$(PROJECT_DIR)", @@ -686,6 +687,7 @@ PRODUCT_NAME = CMS; PUBLIC_HEADERS_FOLDER_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/Security"; SKIP_INSTALL = YES; + STRIP_INSTALLED_PRODUCT = NO; }; name = Debug; }; @@ -779,6 +781,7 @@ 79BDD2BD0D60CA0A000D84D3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + COPY_PHASE_STRIP = YES; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; HEADER_SEARCH_PATHS = ( "$(PROJECT_DIR)", @@ -794,6 +797,7 @@ PRODUCT_NAME = CMS; PUBLIC_HEADERS_FOLDER_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/Security"; SKIP_INSTALL = YES; + STRIP_INSTALLED_PRODUCT = YES; }; name = Release; }; diff --git a/resources/English.lproj/CloudKeychain.strings b/resources/English.lproj/CloudKeychain.strings index 9ecdbc5d04df5c357776765a7a623840f8c53084..12f1d28bf28e26fa74981507b7b20ed7396d1755 100644 GIT binary patch delta 20 ccmX?*bRcQN3US8L$t%UJ8A~@m6_1t#0APIxQ2+n{ delta 22 dcmX?*bRcQN3h{}rL?-VM*8ozRe~5cX0sw<13WERu diff --git a/secdtests/secdtests-entitlements.plist b/secdtests/secdtests-entitlements.plist index d71695e9..fdc1323e 100644 --- a/secdtests/secdtests-entitlements.plist +++ b/secdtests/secdtests-entitlements.plist @@ -14,6 +14,8 @@ migrate-keychain + com.apple.private.system-keychain + modify-anchor-certificates com.apple.springboard.wipedevice diff --git a/sectask/SecEntitlements.h b/sectask/SecEntitlements.h index 17fd6142..c7117da5 100644 --- a/sectask/SecEntitlements.h +++ b/sectask/SecEntitlements.h @@ -96,6 +96,19 @@ __BEGIN_DECLS /* Entitlement needed to call swcd and swcagent processes. */ #define kSecEntitlementPrivateAssociatedDomains CFSTR("com.apple.private.associated-domains") +/* Entitlement to control usage of system keychain */ +#define kSecEntitlementPrivateSystemKeychain CFSTR("com.apple.private.system-keychain") + +/* Entitlement to control usage of syncbubble keychain migration */ +#define kSecEntitlementPrivateKeychainSyncBubble CFSTR("com.apple.private.syncbubble-keychain") + +/* Entitlement to control usage of system keychain migration */ +#define kSecEntitlementPrivateKeychainMigrateSystemKeychain CFSTR("com.apple.private.migrate-musr-system-keychain") + +/* Entitlement to control usage of system keychain migration */ +#define kSecEntitlementPrivateNetworkExtension CFSTR("com.apple.developer.networking.networkextension") + + __END_DECLS #endif /* !_SECURITY_SECENTITLEMENTS_H_ */ diff --git a/securityd/securityd.xcodeproj/project.pbxproj b/securityd/securityd.xcodeproj/project.pbxproj index d2cb04e3..ee97e49a 100644 --- a/securityd/securityd.xcodeproj/project.pbxproj +++ b/securityd/securityd.xcodeproj/project.pbxproj @@ -150,6 +150,8 @@ C2407A1D1B30C86C0067E6AE /* libutilities.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C2407A1C1B30C86C0067E6AE /* libutilities.a */; }; C274C51E0F9E8E0F001ABDA3 /* auditevents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C274C51C0F9E8E0F001ABDA3 /* auditevents.cpp */; }; C274C51F0F9E8E0F001ABDA3 /* auditevents.h in Headers */ = {isa = PBXBuildFile; fileRef = C274C51D0F9E8E0F001ABDA3 /* auditevents.h */; }; + C2E8FBA51B8FABFE00156D36 /* acl_partition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2E8FBA31B8FABFE00156D36 /* acl_partition.cpp */; }; + C2E8FBA61B8FABFE00156D36 /* acl_partition.h in Headers */ = {isa = PBXBuildFile; fileRef = C2E8FBA41B8FABFE00156D36 /* acl_partition.h */; }; ED5130690E7F1259002A3749 /* securityd.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CE1878706FFC5D60079D235 /* securityd.1 */; }; /* End PBXBuildFile section */ @@ -347,6 +349,8 @@ C2CB75A90CE26A3600727A2B /* securityd-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "securityd-watch.d"; path = "dtrace/securityd-watch.d"; sourceTree = ""; }; C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokendatabase.cpp; sourceTree = ""; }; C2D425F205F3C07400CB11F8 /* tokendatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokendatabase.h; sourceTree = ""; }; + C2E8FBA31B8FABFE00156D36 /* acl_partition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = acl_partition.cpp; sourceTree = ""; }; + C2E8FBA41B8FABFE00156D36 /* acl_partition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acl_partition.h; sourceTree = ""; }; C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pcscmonitor.cpp; sourceTree = ""; }; C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pcscmonitor.h; sourceTree = ""; }; C2FDCABF0663CD5B0013F64C /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; @@ -685,6 +689,8 @@ C28654B006DBC2A30021E6E5 /* tokenacl.cpp */, 4C9264990534866F004B0E72 /* acl_keychain.h */, 4C9264980534866F004B0E72 /* acl_keychain.cpp */, + C2E8FBA41B8FABFE00156D36 /* acl_partition.h */, + C2E8FBA31B8FABFE00156D36 /* acl_partition.cpp */, ); name = ACLs; sourceTree = ""; @@ -763,6 +769,7 @@ AAC707440E6F4335003CC2B2 /* tokenacl.h in Headers */, AAC707450E6F4335003CC2B2 /* tokenaccess.h in Headers */, AAC707460E6F4335003CC2B2 /* authhost.h in Headers */, + C2E8FBA61B8FABFE00156D36 /* acl_partition.h in Headers */, AAC707470E6F4335003CC2B2 /* SharedMemoryServer.h in Headers */, AAC707480E6F4335003CC2B2 /* csproxy.h in Headers */, AAC707490E6F4335003CC2B2 /* credential.h in Headers */, @@ -957,6 +964,7 @@ AAC707750E6F4352003CC2B2 /* csproxy.cpp in Sources */, AAC707760E6F4352003CC2B2 /* credential.cpp in Sources */, AAC707780E6F4352003CC2B2 /* clientid.cpp in Sources */, + C2E8FBA51B8FABFE00156D36 /* acl_partition.cpp in Sources */, 4E0BB2B50F79590300BBFEFA /* ccaudit_extensions.cpp in Sources */, C274C51E0F9E8E0F001ABDA3 /* auditevents.cpp in Sources */, ); @@ -1023,6 +1031,8 @@ buildSettings = { HEADER_SEARCH_PATHS = ( "$(inherited)", + ../OSX/include, + "$(SDKROOT)/usr/local/include", "$(BUILT_PRODUCTS_DIR)/derived_src", "$(SRCROOT)", "$(SRCROOT)/securityd", @@ -1033,7 +1043,8 @@ "\"$(SRCROOT)/../../../build/Products\"", "\"$(SRCROOT)/securityd/../../../build/Products\"", ); - ORDER_FILE = "$(SRCROOT)/securityd/src/securityd.order"; + ORDER_FILE = src/securityd.order; + SDKROOT = macosx.internal; }; name = Debug; }; @@ -1043,6 +1054,8 @@ buildSettings = { HEADER_SEARCH_PATHS = ( "$(inherited)", + ../OSX/include, + "$(SDKROOT)/usr/local/include", "$(BUILT_PRODUCTS_DIR)/derived_src", "$(SRCROOT)", "$(SRCROOT)/securityd", @@ -1053,7 +1066,8 @@ "\"$(SRCROOT)/../../../build/Products\"", "\"$(SRCROOT)/securityd/../../../build/Products\"", ); - ORDER_FILE = "$(SRCROOT)/securityd/src/securityd.order"; + ORDER_FILE = src/securityd.order; + SDKROOT = macosx.internal; }; name = Release; }; diff --git a/securityd/src/acl_keychain.cpp b/securityd/src/acl_keychain.cpp index 97052db9..e79d5ea2 100644 --- a/securityd/src/acl_keychain.cpp +++ b/securityd/src/acl_keychain.cpp @@ -66,11 +66,46 @@ CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR KeychainPromptAclSubject::defaultSelector = { }; +// +// If we have a KeychainPromptAclSubject, we want KeychainMigrator to have +// access even if we don't have the "pop ui" credential. Do the code signing +// check first, then process this ACL as normal. +// +bool KeychainPromptAclSubject::validates(const AclValidationContext &ctx) const +{ + Process &process = Server::process(); + if (process.checkAppleSigned() && process.hasEntitlement(migrationEntitlement)) { + Syslog::info("bypassing keychain prompt for keychain migrator"); + secdebug("kcacl", "bypassing keychain prompt for keychain migrator"); + return true; // migrator client -> automatic win + } + + return SimpleAclSubject::validates(ctx); +} + + // // Validate a credential set against this subject. // -bool KeychainPromptAclSubject::validate(const AclValidationContext &context, +bool KeychainPromptAclSubject::validates(const AclValidationContext &context, const TypedList &sample) const +{ + return validateExplicitly(context, ^{ + if (SecurityServerEnvironment *env = context.environment()) { + Process& process = env->database->process(); + StLock _(process); + RefPointer clientXCode = new OSXCodeWrap(process.currentGuest()); + RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(clientXCode)); + if (SecurityServerAcl::addToStandardACL(context, subject)) { + if(env->database->dbVersion() >= CommonBlob::version_partition) { + env->acl.addClientPartitionID(process); + } + } + } + }); +} + +bool KeychainPromptAclSubject::validateExplicitly(const AclValidationContext &context, void (^alwaysAllow)()) const { if (SecurityServerEnvironment *env = context.environment()) { Process &process = Server::process(); @@ -99,37 +134,21 @@ bool KeychainPromptAclSubject::validate(const AclValidationContext &context, { case noErr: // client is signed and valid { - bool forceAllow = false; secdebug("kcacl", "client is valid, proceeding"); - CFDictionaryRef codeDictionary = NULL; - if (errSecSuccess == SecCodeCopySigningInformation(clientCode, kSecCSDefaultFlags, &codeDictionary)) { - CFTypeRef entitlementsDictionary = NULL; - entitlementsDictionary = CFDictionaryGetValue(codeDictionary, kSecCodeInfoEntitlementsDict); - if (NULL != entitlementsDictionary) { - if (CFGetTypeID(entitlementsDictionary) == CFDictionaryGetTypeID()) { - CFTypeRef migrationEntitlement = CFDictionaryGetValue((CFDictionaryRef)entitlementsDictionary, CFSTR("com.apple.private.security.allow-migration")); - if (NULL != migrationEntitlement) { - if (CFGetTypeID(migrationEntitlement) == CFBooleanGetTypeID()) { - if (migrationEntitlement == kCFBooleanTrue) { - secdebug("kcacl", "client has migration entitlement, allowing"); - forceAllow = true; - } - } - } - } - } - CFRelease(codeDictionary); - } - if (forceAllow) { - return true; - } + // This should almost always be handled by the check in KeychainPromptAclSubject::validate, but check again just in case + if (process.checkAppleSigned() && process.hasEntitlement(migrationEntitlement)) { + Syslog::info("bypassing keychain prompt for keychain migrator"); + secdebug("kcacl", "bypassing keychain prompt for keychain migrator"); + return true; // migrator client -> automatic win + } } break; case errSecCSUnsigned: { // client is not signed if (!(mode & CSSM_ACL_KEYCHAIN_PROMPT_UNSIGNED)) { - secdebug("kcacl", "client is unsigned, suppressing prompt"); + Syslog::info("supressing keychain prompt for unsigned client %s(%d)", process.getPath().c_str(), process.pid()); + secdebug("kcacl", "supressing keychain prompt for unsigned client %s(%d)", process.getPath().c_str(), process.pid()); return false; } } @@ -141,22 +160,25 @@ bool KeychainPromptAclSubject::validate(const AclValidationContext &context, { if (!(mode & CSSM_ACL_KEYCHAIN_PROMPT_INVALID)) { secdebug("kcacl", "client is invalid, suppressing prompt"); - Syslog::info("suppressing keychain prompt for invalidly signed client %s(%d)", - process.getPath().c_str(), process.pid()); + Syslog::info("suppressing keychain prompt for invalidly signed client %s(%d)", process.getPath().c_str(), process.pid()); + secdebug("kcacl", "suppressing keychain prompt for invalidly signed client %s(%d)", process.getPath().c_str(), process.pid()); return false; } - Syslog::info("attempting keychain prompt for invalidly signed client %s(%d)", - process.getPath().c_str(), process.pid()); + Syslog::info("attempting keychain prompt for invalidly signed client %s(%d)", process.getPath().c_str(), process.pid()); + secdebug("kcacl", "attempting keychain prompt for invalidly signed client %s(%d)", process.getPath().c_str(), process.pid()); } break; default: // something else went wrong - secdebug("kcacl", "client validation failed rc=%d, suppressing prompt", int32_t(validation)); + Syslog::info("suppressing keychain prompt %s(%d); code signing check failed rc=%d", process.getPath().c_str(), process.pid(), (int32_t) validation); + secdebug("kcacl", "suppressing keychain prompt %s(%d); code signing check failed rc=%d", process.getPath().c_str(), process.pid(), (int32_t) validation); return false; } } // At this point, we're committed to try to Pop The Question. Now, how? + Syslog::info("displaying keychain prompt for %s(%d)", process.getPath().c_str(), process.pid()); + secdebug("kcacl", "displaying keychain prompt for %s(%d)", process.getPath().c_str(), process.pid()); // does the user need to type in the passphrase? const Database *db = env->database; @@ -189,10 +211,7 @@ bool KeychainPromptAclSubject::validate(const AclValidationContext &context, // process an "always allow..." response if (query.remember && clientCode) { - StLock _(process); - RefPointer clientXCode = new OSXCodeWrap(clientCode); - RefPointer subject = new CodeSignatureAclSubject(OSXVerifier(clientXCode)); - SecurityServerAcl::addToStandardACL(context, subject); + alwaysAllow(); } // finally, return the actual user response diff --git a/securityd/src/acl_keychain.h b/securityd/src/acl_keychain.h index 6a143151..755e6970 100644 --- a/securityd/src/acl_keychain.h +++ b/securityd/src/acl_keychain.h @@ -41,7 +41,9 @@ class KeychainPromptAclSubject : public SimpleAclSubject { static const Version jaguarVersion = 1; // 10.2 et al -> first version selector static const Version currentVersion = jaguarVersion; // what we write today public: - bool validate(const AclValidationContext &baseCtx, const TypedList &sample) const; + bool validates(const AclValidationContext &ctx) const; + bool validates(const AclValidationContext &baseCtx, const TypedList &sample) const; + bool validateExplicitly(const AclValidationContext &baseCtx, void (^always)()) const; CssmList toList(Allocator &alloc) const; bool hasAuthorizedForSystemKeychain() const; diff --git a/securityd/src/acl_partition.cpp b/securityd/src/acl_partition.cpp new file mode 100644 index 00000000..056743b1 --- /dev/null +++ b/securityd/src/acl_partition.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000-2006,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@ + */ + + +// +// acl_partition - partition identifier store +// +// This ACL subject stores keychain partition data. +// When evaluated, it always fails. Securityd explicitly +// +#include "acl_partition.h" +#include +#include +#include + +using namespace DataWalkers; + + +// +// The dictionaryPayload is the payload blob interpreted as an XML dictionary, or NULL if that didn't work. +// +CFDictionaryRef PartitionAclSubject::createDictionaryPayload() const +{ + return makeCFDictionaryFrom(CFTempData(this->payload)); +} + +void PartitionAclSubject::setDictionaryPayload(Allocator& alloc, CFDictionaryRef dict) +{ + CFRef xmlData = makeCFData(dict); + this->payload = CssmAutoData(alloc, CFDataGetBytePtr(xmlData), CFDataGetLength(xmlData)); +} + + +// +// The partition subject matches nothing, no matter how pretty. +// +bool PartitionAclSubject::validates(const AclValidationContext &) const +{ + return false; +} + + +// +// The list form has a simple CssmData payload. +// +CssmList PartitionAclSubject::toList(Allocator &alloc) const +{ + return TypedList(Allocator::standard(), CSSM_ACL_SUBJECT_TYPE_PARTITION, + new(alloc) ListElement(alloc, this->payload)); +} + + +// +// Set payload from list input. +// +PartitionAclSubject *PartitionAclSubject::Maker::make(const TypedList &list) const +{ + Allocator &alloc = Allocator::standard(); + if (list.length() != 2) + CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + ListElement *payloadItem; + crack(list, 1, &payloadItem, CSSM_LIST_ELEMENT_DATUM); + return new PartitionAclSubject(alloc, payloadItem->data()); +} + + +// +// A PartitionAclSubject is a "null" subject that contains out of band data +// for further security evaluation. When evaluated as an ACL subject, it always fails. +// +PartitionAclSubject *PartitionAclSubject::Maker::make(Version, Reader &pub, Reader &) const +{ + Allocator& alloc = Allocator::standard(); + const void* data; size_t length; + pub.countedData(data, length); + CssmAutoData payloadData(alloc, data, length); + return new PartitionAclSubject(alloc, payloadData); +} + + +// +// Export to blob form. +// This simply writes the smallest form consistent with the heuristic above. +// +void PartitionAclSubject::exportBlob(Writer::Counter &pub, Writer::Counter &) +{ + pub.countedData(this->payload); +} + +void PartitionAclSubject::exportBlob(Writer &pub, Writer &) +{ + pub.countedData(this->payload); +} diff --git a/securityd/src/acl_partition.h b/securityd/src/acl_partition.h new file mode 100644 index 00000000..b43a58e1 --- /dev/null +++ b/securityd/src/acl_partition.h @@ -0,0 +1,75 @@ +/* + * 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@ + */ + + +// +// acl_partition - "ignore" ACL subject type +// +// A pseudo-ACL that stores partition identifier data. +// +// A PartitionAclSubject always fails to verify. +// +#ifndef _ACL_PARTITION +#define _ACL_PARTITION + +#include +#include + + +namespace Security +{ + +// +// The ANY subject simply matches everything. No sweat. +// +class PartitionAclSubject : public AclSubject { +public: + PartitionAclSubject() + : AclSubject(CSSM_ACL_SUBJECT_TYPE_PARTITION), payload(Allocator::standard()) { } + PartitionAclSubject(Allocator& alloc, const CssmData &data) + : AclSubject(CSSM_ACL_SUBJECT_TYPE_PARTITION), payload(alloc, data) { } + +public: + CssmAutoData payload; + CFDictionaryRef createDictionaryPayload() const; + void setDictionaryPayload(Allocator& alloc, CFDictionaryRef dict); + +public: + bool validates(const AclValidationContext &ctx) const; + CssmList toList(Allocator &alloc) const; + + void exportBlob(Writer::Counter &pub, Writer::Counter &priv); + void exportBlob(Writer &pub, Writer &priv); + + class Maker : public AclSubject::Maker { + public: + Maker() : AclSubject::Maker(CSSM_ACL_SUBJECT_TYPE_PARTITION) { } + PartitionAclSubject *make(const TypedList &list) const; + PartitionAclSubject *make(Version, Reader &pub, Reader &priv) const; + }; +}; + +} // end namespace Security + + +#endif //_ACL_PARTITION diff --git a/securityd/src/acls.cpp b/securityd/src/acls.cpp index f4df0940..6eacafb6 100644 --- a/securityd/src/acls.cpp +++ b/securityd/src/acls.cpp @@ -31,14 +31,16 @@ #include "agentquery.h" #include "tokendatabase.h" #include "acl_keychain.h" +#include "acl_partition.h" // ACL subjects whose Environments we implement #include #include -#include +#include "acl_keychain.h" #include #include +#include // // SecurityServerAcl is virtual @@ -71,7 +73,27 @@ void SecurityServerAcl::changeAcl(const AclEdit &edit, const AccessCredentials * { StLock _(aclSequence); SecurityServerEnvironment env(*this, db); - ObjectAcl::cssmChangeAcl(edit, cred, &env); + + // if we're setting the INTEGRITY entry, check if you're in the partition list. + if (const AclEntryInput* input = edit.newEntry()) { + if (input->proto().authorization().containsOnly(CSSM_ACL_AUTHORIZATION_INTEGRITY)) { + // Only prompt the user if these creds allow UI. + bool ui = (!!cred) && cred->authorizesUI(); + validatePartition(env, ui); // throws if fail + + // If you passed partition validation, bypass the owner ACL check entirely. + env.forceSuccess = true; + } + } + + // If these access credentials, by themselves, protect this database, force success and don't + // restrict changing PARTITION_ID + if(db && db->checkCredentials(cred)) { + env.forceSuccess = true; + ObjectAcl::cssmChangeAcl(edit, cred, &env, NULL); + } else { + ObjectAcl::cssmChangeAcl(edit, cred, &env, CSSM_APPLE_ACL_TAG_PARTITION_ID); + } } void SecurityServerAcl::changeOwner(const AclOwnerPrototype &newOwner, @@ -92,7 +114,26 @@ void SecurityServerAcl::validate(AclAuthorization auth, const AccessCredentials StLock objectSequence(aclSequence); StLock processSequence(Server::process().aclSequence); - ObjectAcl::validate(auth, cred, &env); + ObjectAcl::validate(auth, cred, &env); + + // partition validation happens outside the normal acl validation flow, in addition + bool ui = (!!cred) && cred->authorizesUI(); + + // we should only offer the chance to extend the partition ID list on a "read" operation, so check the AclAuthorization + bool readOperation = + (auth == CSSM_ACL_AUTHORIZATION_CHANGE_ACL) || + (auth == CSSM_ACL_AUTHORIZATION_DECRYPT) || + (auth == CSSM_ACL_AUTHORIZATION_GENKEY) || + (auth == CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED) || + (auth == CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR) || + (auth == CSSM_ACL_AUTHORIZATION_IMPORT_WRAPPED) || + (auth == CSSM_ACL_AUTHORIZATION_IMPORT_CLEAR) || + (auth == CSSM_ACL_AUTHORIZATION_SIGN) || + (auth == CSSM_ACL_AUTHORIZATION_DECRYPT) || + (auth == CSSM_ACL_AUTHORIZATION_MAC) || + (auth == CSSM_ACL_AUTHORIZATION_DERIVE); + + validatePartition(env, ui && readOperation); } void SecurityServerAcl::validate(AclAuthorization auth, const Context &context, Database *db) @@ -102,6 +143,130 @@ void SecurityServerAcl::validate(AclAuthorization auth, const Context &context, } +// +// Partitioning support +// +void SecurityServerAcl::validatePartition(SecurityServerEnvironment& env, bool prompt) +{ + // For the Keychain Migrator, don't even check the partition list + Process &process = Server::process(); + if (process.checkAppleSigned() && process.hasEntitlement(migrationEntitlement)) { + secdebug("integrity", "bypassing partition check for keychain migrator"); + return; // migrator client -> automatic win + } + + if (CFRef partition = this->createPartitionPayload()) { + CFArrayRef partitionList; + if (cfscan(partition, "{Partitions=%AO}", &partitionList)) { + CFRef partitionDebug = CFCopyDescription(partitionList); // for debugging only + secdebugfunc("integrity", "ACL partitionID = %s", cfString(partitionDebug).c_str()); + if (env.database) { + CFRef clientPartitionID = makeCFString(env.database->process().partitionId()); + if (CFArrayContainsValue(partitionList, CFRangeMake(0, CFArrayGetCount(partitionList)), clientPartitionID)) { + secdebugfunc("integrity", "ACL partitions match: %s", cfString(clientPartitionID).c_str()); + return; + } else { + secdebugfunc("integrity", "ACL partition mismatch: client %s ACL %s", cfString(clientPartitionID).c_str(), cfString(partitionDebug).c_str()); + if (prompt && extendPartition(env)) + return; + MacOSError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); + } + } + } + secdebugfunc("integrity", "failed to parse partition payload"); + MacOSError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } else { + // There's no partition list. This is keychain is either old or recently upgraded. + // If there's no database, let it pass. + if((!env.database) || env.database->dbVersion() < SecurityServer::CommonBlob::version_partition) { + secdebugfunc("integrity", "no partition ACL - legacy case"); + //@@@ I guess we let this pass... + } else { + secdebugfunc("integrity", "no partition ACL - adding"); + env.acl.instantiateAcl(); + this->createClientPartitionID(env.database->process()); + env.acl.changedAcl(); + Server::connection().overrideReturn(CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT); + } + } +} + + +bool SecurityServerAcl::extendPartition(SecurityServerEnvironment& env) +{ + // brute-force find the KeychainAclSubject in the ACL + KeychainPromptAclSubject *kcSubject = NULL; + SecurityServerAcl& acl = env.acl; + for (EntryMap::const_iterator it = acl.begin(); it != acl.end(); ++it) { + AclSubjectPointer subject = it->second.subject; + if (ThresholdAclSubject *threshold = dynamic_cast(subject.get())) { + unsigned size = threshold->count(); + if (KeychainPromptAclSubject* last = dynamic_cast(threshold->subject(size-1))) { + // looks standard enough + kcSubject = last; + break; + } + } + } + + if (kcSubject) { + BaseValidationContext ctx(NULL, CSSM_ACL_AUTHORIZATION_PARTITION_ID, &env); + return kcSubject->validateExplicitly(ctx, ^{ + secdebugfunc("integrity", "adding partition to list"); + env.acl.instantiateAcl(); + this->addClientPartitionID(env.database->process()); + env.acl.changedAcl(); + // trigger a special notification code on (otherwise successful) return + Server::connection().overrideReturn(CSSMERR_CSP_APPLE_ADD_APPLICATION_ACL_SUBJECT); + }); + } + secdebugfunc("integrity", "failure extending partition"); + return false; +} + + +PartitionAclSubject* SecurityServerAcl::findPartitionSubject() +{ + pair range; + switch (this->getRange(CSSM_APPLE_ACL_TAG_PARTITION_ID, range, true)) { + case 0: + secdebugfunc("integrity", "no partition tag on ACL"); + return NULL; + default: + secdebugfunc("integrity", "multiple partition ACL entries"); + MacOSError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + case 1: + break; + } + const AclEntry& entry = range.first->second; + if (!entry.authorizes(CSSM_ACL_AUTHORIZATION_PARTITION_ID)) { + secdebugfunc("integrity", "partition entry does not authorize CSSM_ACL_AUTHORIZATION_PARTITION_ID"); + MacOSError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } + if (PartitionAclSubject* partition = dynamic_cast(entry.subject.get())) { + return partition; + } else { + secdebugfunc("integrity", "partition entry is not PartitionAclSubject"); + MacOSError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } +} + + +CFDictionaryRef SecurityServerAcl::createPartitionPayload() +{ + if (PartitionAclSubject* subject = this->findPartitionSubject()) { + if (CFDictionaryRef result = subject->createDictionaryPayload()) { + return result; + } else { + secdebugfunc("integrity", "partition entry is malformed XML"); + MacOSError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } + } else { + return NULL; + } +} + + // // This helper tries to add the (new) subject given to the ACL // whose validation is currently proceeding through context. @@ -187,6 +352,47 @@ bool SecurityServerAcl::looksLikeLegacyDotMac(const AclValidationContext &contex } +// +// ACL manipulations related to keychain partitions +// +bool SecurityServerAcl::createClientPartitionID(Process& process) +{ + // Make sure the ACL is ready for edits + instantiateAcl(); + + // create partition payload + std::string partitionID = process.partitionId(); + CFTemp payload("{Partitions=[%s]}", partitionID.c_str()); + ObjectAcl::AclSubjectPointer subject = new PartitionAclSubject(); + static_cast(subject.get())->setDictionaryPayload(Allocator::standard(), payload); + ObjectAcl::AclEntry partition(subject); + partition.addAuthorization(CSSM_ACL_AUTHORIZATION_PARTITION_ID); + this->add(CSSM_APPLE_ACL_TAG_PARTITION_ID, partition); + secdebugfunc("integrity", "added partition %s to new key", partitionID.c_str()); + return true; +} + + +bool SecurityServerAcl::addClientPartitionID(Process& process) +{ + if (PartitionAclSubject* subject = this->findPartitionSubject()) { + std::string partitionID = process.partitionId(); + if (CFRef payload = subject->createDictionaryPayload()) { + CFArrayRef partitionList; + if (cfscan(payload, "{Partitions=%AO}", &partitionList)) { + CFTemp newPayload("{Partitions=[+%O,%s]}", partitionList, partitionID.c_str()); + subject->setDictionaryPayload(Allocator::standard(), newPayload); + } + return true; + } else { + MacOSError::throwMe(CSSM_ERRCODE_INVALID_ACL_SUBJECT_VALUE); + } + } else { + return createClientPartitionID(process); + } +} + + // // External storage interface // diff --git a/securityd/src/acls.h b/securityd/src/acls.h index 5df4ba25..845c7054 100644 --- a/securityd/src/acls.h +++ b/securityd/src/acls.h @@ -46,12 +46,21 @@ #include #include #include +#include "acl_partition.h" using namespace SecurityServer; class Connection; class Database; +class Process; +class SecurityServerEnvironment; + + +// +// Interesting entitlements +// +static const char migrationEntitlement[] = "com.apple.private.security.allow-migration"; // @@ -80,9 +89,20 @@ public: // a helper to (try to) add an ACL to a "standard form" item ACL static bool addToStandardACL(const AclValidationContext &context, AclSubject *subject); static bool looksLikeLegacyDotMac(const AclValidationContext &context); + + bool createClientPartitionID(Process& process); + bool addClientPartitionID(Process& process); + + // implicit partitioning support + PartitionAclSubject* findPartitionSubject(); + CFDictionaryRef createPartitionPayload(); // aclSequence is taken to serialize ACL validations to pick up mutual changes Mutex aclSequence; + +private: + void validatePartition(SecurityServerEnvironment& env, bool prompt); + bool extendPartition(SecurityServerEnvironment& env); }; diff --git a/securityd/src/clientid.cpp b/securityd/src/clientid.cpp index 8c84a05f..d75b2494 100644 --- a/securityd/src/clientid.cpp +++ b/securityd/src/clientid.cpp @@ -26,6 +26,8 @@ #include "clientid.h" #include "server.h" #include +#include +#include // @@ -34,6 +36,7 @@ // constructor. // ClientIdentification::ClientIdentification() + : mGotPartitionId(false) { } @@ -131,6 +134,93 @@ ClientIdentification::GuestState *ClientIdentification::current() const } +// +// Return the partition id ascribed to this client. +// This is assigned to the whole client process - it is not per-guest. +// +std::string ClientIdentification::partitionId() const +{ + if (!mGotPartitionId) { + mClientPartitionId = partitionIdForProcess(processCode()); + mGotPartitionId = true; + } + return mClientPartitionId; +} + + +static std::string hashString(CFDataRef data) +{ + CFIndex length = CFDataGetLength(data); + const unsigned char *hash = CFDataGetBytePtr(data); + char s[2 * length + 1]; + for (CFIndex n = 0; n < length; n++) + sprintf(&s[2*n], "%2.2x", hash[n]); + return s; +} + + +std::string ClientIdentification::partitionIdForProcess(SecStaticCodeRef code) +{ + static CFStringRef const appleReq = CFSTR("anchor apple"); + static CFStringRef const masReq = CFSTR("anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]"); + static CFStringRef const developmentOrDevIDReq = CFSTR("anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13]" + " or " + "anchor apple generic and certificate leaf[subject.CN] = \"Mac Developer:\"* and certificate 1[field.1.2.840.113635.100.6.2.1]"); + static SecRequirementRef apple; + static SecRequirementRef mas; + static SecRequirementRef developmentOrDevID; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (noErr != SecRequirementCreateWithString(appleReq, kSecCSDefaultFlags, &apple) + || noErr != SecRequirementCreateWithString(masReq, kSecCSDefaultFlags, &mas) + || noErr != SecRequirementCreateWithString(developmentOrDevIDReq, kSecCSDefaultFlags, &developmentOrDevID)) + abort(); + }); + + OSStatus rc; + switch (rc = SecStaticCodeCheckValidity(code, kSecCSBasicValidateOnly, apple)) { + case noErr: + case errSecCSReqFailed: + break; + case errSecCSUnsigned: + return "unsigned:"; + default: + MacOSError::throwMe(rc); + } + CFRef info; + if (OSStatus irc = SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref())) + MacOSError::throwMe(irc); + + if (rc == noErr) { + // for apple-signed code, take the team id if present, or make it canonical apple + if (CFStringRef teamidRef = CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier))) + return "teamid:" + cfString(teamidRef); + else if (CFEqual(CFDictionaryGetValue(info, kSecCodeInfoIdentifier), CFSTR("com.apple.security"))) + return "apple-tool:"; // take security(1) into a separate partition so it can't automatically peek into Apple's own + else + return "apple:"; + } else if (noErr == SecStaticCodeCheckValidity(code, kSecCSBasicValidateOnly, mas)) { + // for MAS-signed code, we take the embedded team identifier (verified by Apple) + return "teamid:" + cfString(CFStringRef(CFDictionaryGetValue(info, kSecCodeInfoTeamIdentifier))); + } else if (noErr == SecStaticCodeCheckValidity(code, kSecCSBasicValidateOnly, developmentOrDevID)) { + // for developer-signed code, we take the team identifier from the signing certificate's OU field + CFRef info; + if (noErr != (rc = SecCodeCopySigningInformation(code, kSecCSSigningInformation, &info.aref()))) + MacOSError::throwMe(rc); + CFArrayRef certChain = CFArrayRef(CFDictionaryGetValue(info, kSecCodeInfoCertificates)); + SecCertificateRef signingCert = SecCertificateRef(CFArrayGetValueAtIndex(certChain, 0)); + CFRef ou; + SecCertificateCopySubjectComponent(signingCert, &CSSMOID_OrganizationalUnitName, &ou.aref()); + return "teamid:" + cfString(ou); + } else { + // cannot positively classify this code, but it's signed + CFDataRef cdhashData = CFDataRef(CFDictionaryGetValue(info, kSecCodeInfoUnique)); + assert(cdhashData); + return "cdhash:" + hashString(cdhashData); + } +} + + // // Support for the legacy hash identification mechanism. // The legacy machinery deals exclusively in terms of processes. @@ -180,6 +270,20 @@ const bool ClientIdentification::checkAppleSigned() const } +bool ClientIdentification::hasEntitlement(const char *name) const +{ + CFRef info; + MacOSError::check(SecCodeCopySigningInformation(processCode(), kSecCSDefaultFlags, &info.aref())); + CFCopyRef entitlements = (CFDictionaryRef)CFDictionaryGetValue(info, kSecCodeInfoEntitlementsDict); + if (entitlements && entitlements.is()) { + CFTypeRef value = CFDictionaryGetValue(entitlements, CFTempString(name)); + if (value && value != kCFBooleanFalse) + return true; // have entitlement, it's not - bypass partition construction + } + return false; +} + + // // Bonus function: get the path out of a SecCodeRef // diff --git a/securityd/src/clientid.h b/securityd/src/clientid.h index 57d9caf7..cc28a8df 100644 --- a/securityd/src/clientid.h +++ b/securityd/src/clientid.h @@ -43,12 +43,16 @@ public: SecCodeRef processCode() const; SecCodeRef currentGuest() const; + + std::string partitionId() const; // CodeSignatures::Identity personality string getPath() const; const CssmData getHash() const; const bool checkAppleSigned() const; + bool hasEntitlement(const char *name) const; + protected: void setup(pid_t pid); @@ -71,7 +75,11 @@ private: typedef std::map GuestMap; mutable GuestMap mGuests; + mutable std::string mClientPartitionId; + mutable bool mGotPartitionId; + GuestState *current() const; + static std::string partitionIdForProcess(SecStaticCodeRef code); }; diff --git a/securityd/src/database.cpp b/securityd/src/database.cpp index 3fddcf64..d0f2ed03 100644 --- a/securityd/src/database.cpp +++ b/securityd/src/database.cpp @@ -185,6 +185,12 @@ void Database::authenticate(CSSM_DB_ACCESS_TYPE, const AccessCredentials *) CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); } +bool Database::checkCredentials(const AccessCredentials *) +{ + secdebug("database", "%p calling unimplemented checkCredentials", this); + CssmError::throwMe(CSSM_ERRCODE_FUNCTION_NOT_IMPLEMENTED); +} + SecurityServerAcl &Database::acl() { secdebug("database", "%p has no ACL implementation", this); diff --git a/securityd/src/database.h b/securityd/src/database.h index 0ab8faa8..311b9e0f 100644 --- a/securityd/src/database.h +++ b/securityd/src/database.h @@ -70,6 +70,8 @@ public: virtual bool belongsToSystem() const; // belongs to system (root) security domain + virtual uint32 dbVersion() = 0; // For databases that have a concept of version, return the version + protected: void notify(NotificationEvent event, const DLDbIdentifier &ident); }; @@ -147,6 +149,9 @@ public: CssmData *param, uint32 usage, uint32 attrs, RefPointer &derivedKey) = 0; virtual void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); + + // returns true if these credentials contain a valid password or master key for this database + virtual bool checkCredentials(const AccessCredentials *cred); virtual SecurityServerAcl &acl(); virtual bool isLocked(); @@ -205,6 +210,8 @@ public: DbCommon& common() const { return parent(); } virtual const char *dbName() const = 0; virtual void dbName(const char *name); + + virtual uint32 dbVersion() { return common().dbVersion(); } }; diff --git a/securityd/src/dbcrypto.cpp b/securityd/src/dbcrypto.cpp index 22180f63..b009f003 100644 --- a/securityd/src/dbcrypto.cpp +++ b/securityd/src/dbcrypto.cpp @@ -43,8 +43,9 @@ using LowLevelMemoryUtilities::fieldOffsetOf; // The CryptoCore constructor doesn't do anything interesting. // It just initializes us to "empty". // -DatabaseCryptoCore::DatabaseCryptoCore() : mHaveMaster(false), mIsValid(false) +DatabaseCryptoCore::DatabaseCryptoCore() : mBlobVersion(CommonBlob::version_MacOS_10_0), mHaveMaster(false), mIsValid(false) { + mBlobVersion = CommonBlob::getCurrentVersion(); } DatabaseCryptoCore::~DatabaseCryptoCore() @@ -101,11 +102,14 @@ CssmClient::Key DatabaseCryptoCore::masterKey() // If a NULL DbBlob is passed, generate a new (random) salt. // Note that the passphrase is NOT remembered; only the master key. // -void DatabaseCryptoCore::setup(const DbBlob *blob, const CssmData &passphrase) +void DatabaseCryptoCore::setup(const DbBlob *blob, const CssmData &passphrase, bool copyVersion /* = true */) { - if (blob) - memcpy(mSalt, blob->salt, sizeof(mSalt)); - else + if (blob) { + if(copyVersion) { + mBlobVersion = blob->version(); + } + memcpy(mSalt, blob->salt, sizeof(mSalt)); + } else Server::active().random(mSalt); mMasterKey = deriveDbMasterKey(passphrase); mHaveMaster = true; @@ -117,7 +121,7 @@ void DatabaseCryptoCore::setup(const DbBlob *blob, const CssmData &passphrase) // We will copy the KeyData (caller still owns its copy). // Blob/salt handling as above. // -void DatabaseCryptoCore::setup(const DbBlob *blob, CssmClient::Key master) +void DatabaseCryptoCore::setup(const DbBlob *blob, CssmClient::Key master, bool copyVersion /* = true */) { // pre-screen the key CssmKey::Header header = master.header(); @@ -127,9 +131,12 @@ void DatabaseCryptoCore::setup(const DbBlob *blob, CssmClient::Key master) CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); // accept it - if (blob) - memcpy(mSalt, blob->salt, sizeof(mSalt)); - else + if (blob) { + if(copyVersion) { + mBlobVersion = blob->version(); + } + memcpy(mSalt, blob->salt, sizeof(mSalt)); + } else Server::active().random(mSalt); mMasterKey = master; mHaveMaster = true; @@ -214,7 +221,7 @@ DbBlob *DatabaseCryptoCore::encodeCore(const DbBlob &blobTemplate, // assemble the DbBlob memset(blob, 0x7d, sizeof(DbBlob)); // deterministically fill any alignment gaps - blob->initialize(); + blob->initialize(mBlobVersion); blob->randomSignature = blobTemplate.randomSignature; blob->sequence = blobTemplate.sequence; blob->params = blobTemplate.params; @@ -231,7 +238,13 @@ DbBlob *DatabaseCryptoCore::encodeCore(const DbBlob &blobTemplate, CssmData(blob->publicAclBlob(), publicAcl.length() + cryptoBlob.length()) }; CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); - GenerateMac signer(Server::csp(), CSSM_ALGID_SHA1HMAC_LEGACY); + + CSSM_ALGORITHMS signingAlgorithm = CSSM_ALGID_SHA1HMAC; +#if defined(COMPAT_OSX_10_0) + if (blob->version() == blob->version_MacOS_10_0) + signingAlgorithm = CSSM_ALGID_SHA1HMAC_LEGACY; // BSafe bug compatibility +#endif + GenerateMac signer(Server::csp(), signingAlgorithm); signer.key(mSigningKey); signer.sign(signChunk, 2, signature); assert(signature.length() == sizeof(blob->blobSignature)); @@ -293,6 +306,7 @@ void DatabaseCryptoCore::decodeCore(const DbBlob *blob, void **privateAclBlob) } // secrets have been established + mBlobVersion = blob->version(); mIsValid = true; Allocator::standard().free(privateBlob); } @@ -308,6 +322,7 @@ void DatabaseCryptoCore::importSecrets(const DatabaseCryptoCore &src) assert(hasMaster()); mEncryptionKey = src.mEncryptionKey; mSigningKey = src.mSigningKey; + mBlobVersion = src.mBlobVersion; // make sure we copy over all state mIsValid = true; } @@ -364,7 +379,7 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, // assemble the KeyBlob memset(blob, 0, sizeof(KeyBlob)); // fill alignment gaps - blob->initialize(); + blob->initialize(mBlobVersion); if(!inTheClear) { memcpy(blob->iv, iv, sizeof(iv)); } @@ -390,7 +405,13 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, CssmData(blob->publicAclBlob(), blob->publicAclBlobLength() + blob->cryptoBlobLength()) }; CssmData signature(blob->blobSignature, sizeof(blob->blobSignature)); - GenerateMac signer(Server::csp(), CSSM_ALGID_SHA1HMAC_LEGACY); //@@@!!! CRUD + + CSSM_ALGORITHMS signingAlgorithm = CSSM_ALGID_SHA1HMAC; +#if defined(COMPAT_OSX_10_0) + if (blob->version() == blob->version_MacOS_10_0) + signingAlgorithm = CSSM_ALGID_SHA1HMAC_LEGACY; // BSafe bug compatibility +#endif + GenerateMac signer(Server::csp(), signingAlgorithm); signer.key(mSigningKey); signer.sign(signChunk, 2, signature); assert(signature.length() == sizeof(blob->blobSignature)); @@ -408,6 +429,8 @@ KeyBlob *DatabaseCryptoCore::encodeKeyCore(const CssmKey &inKey, void DatabaseCryptoCore::decodeKeyCore(KeyBlob *blob, CssmKey &key, void * &pubAcl, void * &privAcl) const { + // Note that we can't do anything with this key's version(). + // Assemble the encrypted blob as a CSSM "wrapped key" CssmKey wrappedKey; wrappedKey.KeyHeader = blob->header; diff --git a/securityd/src/dbcrypto.h b/securityd/src/dbcrypto.h index fdbc7f4b..d00648d2 100644 --- a/securityd/src/dbcrypto.h +++ b/securityd/src/dbcrypto.h @@ -52,8 +52,8 @@ public: void generateNewSecrets(); CssmClient::Key masterKey(); - void setup(const DbBlob *blob, const CssmData &passphrase); - void setup(const DbBlob *blob, CssmClient::Key master); + void setup(const DbBlob *blob, const CssmData &passphrase, bool copyVersion = true); + void setup(const DbBlob *blob, CssmClient::Key master, bool copyVersion = true); void decodeCore(const DbBlob *blob, void **privateAclBlob = NULL); DbBlob *encodeCore(const DbBlob &blobTemplate, @@ -74,6 +74,9 @@ public: public: bool validatePassphrase(const CssmData &passphrase); +protected: + uint32 mBlobVersion; // blob version of current database + private: bool mHaveMaster; // master key has been entered (setup) bool mIsValid; // master secrets are valid (decode or generateNew) diff --git a/securityd/src/kcdatabase.cpp b/securityd/src/kcdatabase.cpp index 4bae65a5..4326b29d 100644 --- a/securityd/src/kcdatabase.cpp +++ b/securityd/src/kcdatabase.cpp @@ -168,6 +168,56 @@ change_secret_on_keybag(KeychainDatabase & db, const void * secret, int secret_l } } +// Attempt to unlock the keybag with a AccessCredentials password. +// Honors UI disabled flags from clients set in the cred before prompt. +static bool +unlock_keybag_with_cred(KeychainDatabase &db, const AccessCredentials *cred){ + list samples; + if (cred && cred->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, samples)) { + for (list::iterator it = samples.begin(); it != samples.end(); it++) { + TypedList &sample = *it; + sample.checkProper(); + switch (sample.type()) { + // interactively prompt the user - no additional data + case CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT: { + StSyncLock uisync(db.common().uiLock(), db.common()); + // Once we get the ui lock, check whether another thread has already unlocked keybag + bool locked = false; + service_context_t context = db.common().session().get_current_service_context(); + if ((service_client_kb_is_locked(&context, &locked, NULL) == 0) && locked) { + QueryKeybagPassphrase keybagQuery(db.common().session(), 3); + keybagQuery.inferHints(Server::process()); + if (keybagQuery.query() == SecurityAgent::noReason) { + return true; + } + } + else { + // another thread already unlocked the keybag + return true; + } + break; + } + // try to use an explicitly given passphrase - Data:passphrase + case CSSM_SAMPLE_TYPE_PASSWORD: { + if (sample.length() != 2) + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + secdebug("KCdb", "%p attempting passphrase unlock of keybag"); + if (unlock_keybag(db, sample[1].data().data(), (int)sample[1].data().length())) { + return true; + } + break; + } + default: { + // Unknown sub-sample for unlocking. + secdebug("KCdb", "keybag: unknown sub-sample unlock (%d) ignored", sample.type()); + break; + } + } + } + } + return false; +} + // // Create a Database object from initial parameters (create operation) // @@ -311,6 +361,60 @@ KeychainDatabase::KeychainDatabase(KeychainDatabase &src, Process &proc, DbHandl common().dbName(), this, &common()); } + +// Make a new KeychainDatabase from an old one, but have entirely new operational secrets +KeychainDatabase::KeychainDatabase(KeychainDatabase &src, Process &proc) +: LocalDatabase(proc), mValidData(false), mSecret(Allocator::standard(Allocator::sensitive)), mSaveSecret(false), version(0), mBlob(NULL) +{ + mCred = DataWalkers::copy(src.mCred, Allocator::standard()); + + // Give this KeychainDatabase a temporary name + // this must canonicalize to a different path than the original DB, otherwise another process opening the existing DB wil find this new KeychainDbCommon + // and call decodeCore with the old blob, overwriting the new secrets and wreaking havoc + std::string newDbName = std::string("////") + std::string(src.identifier().dbName()) + std::string("_com.apple.security.keychain.migrating"); + DLDbIdentifier newDLDbIdent(src.identifier().dlDbIdentifier().ssuid(), newDbName.c_str(), src.identifier().dlDbIdentifier().dbLocation()); + DbIdentifier ident(newDLDbIdent, src.identifier()); + + // create common block and initialize + RefPointer newCommon = new KeychainDbCommon(proc.session(), ident); + StLock _(*newCommon); + parent(*newCommon); + + // We want to re-use the master secrets from the source database (and so the + // same password), but reroll new operational secrets. + + // Copy the master secret over... + src.unlockDb(); // precaution + + common().setup(src.blob(), src.common().masterKey(), false); // keep the new common's version intact + + // set initial database parameters from the source keychain + common().mParams = src.common().mParams; + + // and make new operational secrets + common().makeNewSecrets(); + + // import source keychain's ACL + CssmData pubAcl, privAcl; + src.acl().exportBlob(pubAcl, privAcl); + importBlob(pubAcl.data(), privAcl.data()); + src.acl().allocator.free(pubAcl); + src.acl().allocator.free(privAcl); + + // indicate that this keychain should be allowed to do some otherwise + // risky things required for copying, like re-encoding keys + mRecodingSource = &src; + + common().setUnlocked(); + mValidData = true; + + encode(); + + proc.addReference(*this); + secdebug("SSdb", "database %s(%p) created as expected copy, common at %p", + common().dbName(), this, &common()); +} + // // Destroy a Database // @@ -580,10 +684,7 @@ void KeychainDatabase::makeUnlocked(const AccessCredentials *cred) bool locked = false; service_context_t context = common().session().get_current_service_context(); if ((service_client_kb_is_locked(&context, &locked, NULL) == 0) && locked) { - StSyncLock uisync(common().uiLock(), common()); - QueryKeybagPassphrase keybagQuery(common().session(), 3); - keybagQuery.inferHints(Server::process()); - if (keybagQuery.query() != SecurityAgent::noReason) { + if (!unlock_keybag_with_cred(*this, cred)) { syslog(LOG_NOTICE, "failed to unlock iCloud keychain"); } } @@ -845,6 +946,59 @@ void KeychainDatabase::establishOldSecrets(const AccessCredentials *creds) CssmError::throwMe(CSSM_ERRCODE_OPERATION_AUTH_DENIED); } +// +// This function is almost identical to establishOldSecrets, but: +// 1. It will never prompt the user; these credentials either work or they don't +// 2. It will not change the secrets of this database +// 3. Things that are "system keychains" are checked against the system keychain file. +// +// TODO: These two functions should probably be refactored to something nicer. +bool KeychainDatabase::checkCredentials(const AccessCredentials *creds) { + // attempt system-keychain unlock + if (this->belongsToSystem()) { + SystemKeychainKey systemKeychain(kSystemUnlockFile); + + // We can unlock this keychain only if we match the signature and have + // the same master key + CssmClient::Key systemKey(Server::csp(), systemKeychain.key(), true); + return (systemKeychain.matches(mBlob->randomSignature) && + common().masterKey() == systemKey); + } + + list samples; + if (creds && creds->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, samples)) { + for (list::iterator it = samples.begin(); it != samples.end(); it++) { + TypedList &sample = *it; + sample.checkProper(); + switch (sample.type()) { + // interactively prompt the user - no additional data + case CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT: + // do nothing, because this function will never prompt the user + secdebug("integrity", "%p ignoring keychain prompt", this); + break; + // try to use an explicitly given passphrase - Data:passphrase + case CSSM_SAMPLE_TYPE_PASSWORD: + if (sample.length() != 2) + CssmError::throwMe(CSSM_ERRCODE_INVALID_SAMPLE_VALUE); + secdebug("integrity", "%p checking passphrase", this); + return validatePassphrase(sample[1]); + // try to open with a given master key - Data:CSP or KeyHandle, Data:CssmKey + case CSSM_SAMPLE_TYPE_SYMMETRIC_KEY: + case CSSM_SAMPLE_TYPE_ASYMMETRIC_KEY: + assert(mBlob); + secdebug("integrity", "%p attempting explicit key unlock", this); + CssmClient::Key checkKey = keyFromCreds(sample, 4); + return common().masterKey() == checkKey; + break; + // explicitly defeat the default action but don't try anything in particular + } + } + } + + // out of options - credentials don't match + return false; +} + bool KeychainDatabase::interactiveUnlock() { secdebug("KCdb", "%p attempting interactive unlock", this); @@ -1279,6 +1433,8 @@ void KeychainDatabase::validateBlob(const DbBlob *blob) #endif case DbBlob::version_MacOS_10_1: break; + case DbBlob::version_partition: + break; default: CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_DATABASE_BLOB); } diff --git a/securityd/src/kcdatabase.h b/securityd/src/kcdatabase.h index 3e774497..b34da0cd 100644 --- a/securityd/src/kcdatabase.h +++ b/securityd/src/kcdatabase.h @@ -112,6 +112,7 @@ public: const DbIdentifier &identifier() const {return mIdentifier; } const DLDbIdentifier &dlDbIdent() const { return identifier(); } const char *dbName() const { return dlDbIdent().dbName(); } + uint32 dbVersion() { return DatabaseCryptoCore::mBlobVersion; } bool isLoginKeychain() const { return mLoginKeychain; } DbBlob *encode(KeychainDatabase &db); @@ -165,6 +166,9 @@ public: // keychain synchronization recode to a specfic blob: KeychainDatabase(KeychainDatabase &src, Process &proc, DbHandle dbToClone); + + // Copy another database, but with new secrets + KeychainDatabase(KeychainDatabase &src, Process &proc); virtual ~KeychainDatabase(); KeychainDbCommon &common() const; @@ -184,6 +188,7 @@ public: DbBlob *blob(); void authenticate(CSSM_DB_ACCESS_TYPE mode, const AccessCredentials *cred); + bool checkCredentials(const AccessCredentials* creds); void changePassphrase(const AccessCredentials *cred); RefPointer extractMasterKey(Database &db, const AccessCredentials *cred, const AclEntryPrototype *owner, uint32 usage, uint32 attrs); diff --git a/securityd/src/kckey.cpp b/securityd/src/kckey.cpp index cd4cd039..d5917c8e 100644 --- a/securityd/src/kckey.cpp +++ b/securityd/src/kckey.cpp @@ -49,6 +49,8 @@ KeychainKey::KeychainKey(Database &db, const KeyBlob *blob) #endif case KeyBlob::version_MacOS_10_1: break; + case KeyBlob::version_partition: + break; default: CssmError::throwMe(CSSMERR_APPLEDL_INCOMPATIBLE_KEY_BLOB); } diff --git a/securityd/src/localkey.cpp b/securityd/src/localkey.cpp index 7543ded3..734d16a6 100644 --- a/securityd/src/localkey.cpp +++ b/securityd/src/localkey.cpp @@ -29,6 +29,8 @@ #include "server.h" #include "database.h" #include +#include +#include // @@ -86,6 +88,13 @@ void LocalKey::setOwner(const AclEntryPrototype *owner) acl().cssmSetInitial(*owner); // specified else acl().cssmSetInitial(new AnyAclSubject()); // defaulted + + if (this->database().dbVersion() >= CommonBlob::version_partition) { + // put payload into an AclEntry tagged as CSSM_APPLE_ACL_TAG_PARTITION_ID... + // ... unless the client has the "converter" entitlement as attested by Apple + if (!(process().checkAppleSigned() && process().hasEntitlement(migrationEntitlement))) + this->acl().createClientPartitionID(this->process()); + } } diff --git a/securityd/src/main.cpp b/securityd/src/main.cpp index 77e3077c..722edac7 100644 --- a/securityd/src/main.cpp +++ b/securityd/src/main.cpp @@ -58,6 +58,7 @@ #include #include #include "acl_keychain.h" +#include "acl_partition.h" // @@ -235,11 +236,12 @@ int main(int argc, char *argv[]) new ProtectedPasswordAclSubject::Maker(); new PromptedAclSubject::Maker(); new ThresholdAclSubject::Maker(); - new CommentAclSubject::Maker(); + new CommentAclSubject::Maker(); new ProcessAclSubject::Maker(); new CodeSignatureAclSubject::Maker(); - new KeychainPromptAclSubject::Maker(keychainAclDefault); - new PreAuthorizationAcls::OriginMaker(); + new KeychainPromptAclSubject::Maker(keychainAclDefault); + new PartitionAclSubject::Maker(); + new PreAuthorizationAcls::OriginMaker(); new PreAuthorizationAcls::SourceMaker(); // establish the code equivalents database diff --git a/securityd/src/server.h b/securityd/src/server.h index 94140801..990eab78 100644 --- a/securityd/src/server.h +++ b/securityd/src/server.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/securityd/src/tempdatabase.cpp b/securityd/src/tempdatabase.cpp index ed08fd1c..ddb8f5d4 100644 --- a/securityd/src/tempdatabase.cpp +++ b/securityd/src/tempdatabase.cpp @@ -95,6 +95,13 @@ const char *TempDatabase::dbName() const return "(transient)"; } +// +// A TempDatabase doesn't have a common object or a version, really, so overload the function to return some base version +// +uint32 TempDatabase::dbVersion() { + return CommonBlob::version_MacOS_10_0; +} + bool TempDatabase::transient() const { return true; diff --git a/securityd/src/tempdatabase.h b/securityd/src/tempdatabase.h index 10195543..88c0c23b 100644 --- a/securityd/src/tempdatabase.h +++ b/securityd/src/tempdatabase.h @@ -46,6 +46,7 @@ public: TempDatabase(Process &proc); const char *dbName() const; + uint32 dbVersion(); bool transient() const; RefPointer makeKey(const CssmKey &newKey, uint32 moreAttributes, diff --git a/securityd/src/tokendatabase.h b/securityd/src/tokendatabase.h index e48a9a3b..566df264 100644 --- a/securityd/src/tokendatabase.h +++ b/securityd/src/tokendatabase.h @@ -61,6 +61,9 @@ public: uint32 subservice() const { return token().subservice(); } std::string dbName() const; + + // TokenDbCommons have no real version, return base + uint32 dbVersion() { return CommonBlob::version_MacOS_10_0; } Adornable &store(); void resetAcls(); diff --git a/securityd/src/transition.cpp b/securityd/src/transition.cpp index 1512fd96..7f722634 100644 --- a/securityd/src/transition.cpp +++ b/securityd/src/transition.cpp @@ -546,6 +546,26 @@ kern_return_t ucsp_server_recodeDbForSync(UCSP_ARGS, DbHandle dbToClone, END_IPC(DL) } +kern_return_t ucsp_server_recodeDbToVersion(UCSP_ARGS, uint32 newVersion, DbHandle srcDb, DbHandle *newDb) +{ + BEGIN_IPC(recodeDbToVersion) + RefPointer srcKC = Server::keychain(srcDb); + + // You can only recode an unlocked keychain, so let's make sure. + srcKC->unlockDb(); + + // Currently, there's no way to ask KeychainDatabase to become a new version. + // So, let's just hope they're asking for the right version, and throw an error if they didn't. + KeychainDatabase* newKC = new KeychainDatabase(*srcKC, connection.process()); + if(newKC->blob()->version() != newVersion) { + CssmError::throwMe(CSSM_ERRCODE_INCOMPATIBLE_VERSION); + } + + *newDb = newKC->handle(); + + END_IPC(DL) +} + kern_return_t ucsp_server_authenticateDbsForSync(UCSP_ARGS, DATA_IN(dbHandleArray), DATA_IN(agentData), DbHandle* authenticatedDBHandle) { @@ -563,7 +583,7 @@ kern_return_t ucsp_server_authenticateDbsForSync(UCSP_ARGS, DATA_IN(dbHandleArra int index; for (index=0; index < ipcDbHandleArrayCount; index++) { - *currIPCDbHandleArrayPtr = *dbHandleArrayPtr; + *currIPCDbHandleArrayPtr = *dbHandleArrayPtr; Server::keychain(*currIPCDbHandleArrayPtr)->lockDb(); // lock this db if it was unlocked in the past (user could have deleted the kc, resetLogin, etc.) currIPCDbHandleArrayPtr++; dbHandleArrayPtr++; @@ -1119,7 +1139,10 @@ kern_return_t ucsp_server_getAcl(UCSP_ARGS, AclKind kind, KeyHandle key, BEGIN_IPC(getAcl) uint32 count; AclEntryInfo *aclList; - Server::aclBearer(kind, key).getAcl(haveTag ? tag : NULL, count, aclList); + + AclSource& aclRef = Server::aclBearer(kind, key); + secdebug("SecAccess", "getting the ACL for handle %d [%d] (%p)", key, (uint32_t) kind, &aclRef); + aclRef.getAcl(haveTag ? tag : NULL, count, aclList); CSSM_ACL_ENTRY_INFO_ARRAY aclsArray = { count, aclList }; void *acls_data; u_int acls_length; @@ -1151,7 +1174,10 @@ kern_return_t ucsp_server_changeAcl(UCSP_ARGS, AclKind kind, KeyHandle key, CopyOutAccessCredentials creds(cred, credLength); CopyOutAclEntryInput entryacl(acl, aclLength); - Server::aclBearer(kind, key).changeAcl(AclEdit(mode, handle, entryacl), creds); + AclSource& aclRef = Server::aclBearer(kind, key); + secdebug("SecAccess", "changing the ACL for handle %d [%d] (%p)", key, (uint32_t) kind, &aclRef); + aclRef.changeAcl(AclEdit(mode, handle, entryacl), creds); + END_IPC(CSP) } -- 2.45.2