]> git.saurik.com Git - apple/security.git/commitdiff
Security-57337.40.85.tar.gz os-x-10114 v57337.40.85
authorApple <opensource@apple.com>
Wed, 13 Jul 2016 22:37:23 +0000 (22:37 +0000)
committerApple <opensource@apple.com>
Wed, 13 Jul 2016 22:37:23 +0000 (22:37 +0000)
410 files changed:
CircleJoinRequested/CircleJoinRequested.m
IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist
IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist
OSX/IDSKeychainSyncingProxy/com.apple.security.idskeychainsyncingproxy.plist
OSX/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist
OSX/Keychain Circle Notification/KNAppDelegate.m
OSX/OSX.xcodeproj/project.pbxproj
OSX/OSX.xcodeproj/xcshareddata/xcschemes/World.xcscheme
OSX/OSX.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme
OSX/authd/authorization.plist
OSX/authd/engine.c
OSX/authd/server.c
OSX/codesign_tests/CaspianTests/CaspianTests
OSX/lib/security.exp-in
OSX/libsecurity_apple_csp/lib/RSA_DSA_utils.cpp
OSX/libsecurity_apple_cspdl/lib/SSCSPDLSession.cpp
OSX/libsecurity_apple_cspdl/lib/SSDLSession.cpp
OSX/libsecurity_apple_cspdl/lib/SSDatabase.cpp
OSX/libsecurity_apple_cspdl/lib/SSDatabase.h
OSX/libsecurity_apple_cspdl/lib/SSKey.cpp
OSX/libsecurity_apple_x509_tp/lib/TPCertInfo.cpp
OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp
OSX/libsecurity_asn1/lib/secasn1d.c
OSX/libsecurity_asn1/lib/secasn1e.c
OSX/libsecurity_cdsa_client/lib/aclclient.h
OSX/libsecurity_cdsa_client/lib/dlclient.cpp
OSX/libsecurity_cdsa_client/lib/dlclient.h
OSX/libsecurity_cdsa_client/lib/keychainacl.cpp
OSX/libsecurity_cdsa_client/lib/keychainacl.h
OSX/libsecurity_cdsa_client/lib/securestorage.cpp
OSX/libsecurity_cdsa_plugin/lib/CSPsession.cpp
OSX/libsecurity_cdsa_utilities/lib/Schema.h
OSX/libsecurity_cdsa_utilities/lib/Schema.m4
OSX/libsecurity_cdsa_utilities/lib/acl_any.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_any.h
OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_codesigning.h
OSX/libsecurity_cdsa_utilities/lib/acl_comment.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_comment.h
OSX/libsecurity_cdsa_utilities/lib/acl_preauth.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_preauth.h
OSX/libsecurity_cdsa_utilities/lib/acl_process.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_process.h
OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_protectedpw.h
OSX/libsecurity_cdsa_utilities/lib/acl_secret.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_secret.h
OSX/libsecurity_cdsa_utilities/lib/acl_threshold.cpp
OSX/libsecurity_cdsa_utilities/lib/acl_threshold.h
OSX/libsecurity_cdsa_utilities/lib/aclsubject.cpp
OSX/libsecurity_cdsa_utilities/lib/aclsubject.h
OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.cpp
OSX/libsecurity_cdsa_utilities/lib/cssmaclpod.h
OSX/libsecurity_cdsa_utilities/lib/cssmcred.cpp
OSX/libsecurity_cdsa_utilities/lib/cssmcred.h
OSX/libsecurity_cdsa_utilities/lib/cssmdb.cpp
OSX/libsecurity_cdsa_utilities/lib/cssmdb.h
OSX/libsecurity_cdsa_utilities/lib/objectacl.cpp
OSX/libsecurity_cdsa_utilities/lib/objectacl.h
OSX/libsecurity_cdsa_utilities/lib/walkers.h
OSX/libsecurity_cms/lib/CMSDecoder.cpp
OSX/libsecurity_cms/lib/CMSEncoder.cpp
OSX/libsecurity_cms/lib/CMSEncoder.h
OSX/libsecurity_cms/lib/CMSPrivate.h
OSX/libsecurity_cms/lib/security_cms.exp
OSX/libsecurity_cms/libsecurity_cms.xcodeproj/project.pbxproj
OSX/libsecurity_cms/regressions/cms-hashagility-test.c [new file with mode: 0644]
OSX/libsecurity_cms/regressions/cms-hashagility-test.h [new file with mode: 0644]
OSX/libsecurity_cms/regressions/cms_regressions.h [new file with mode: 0644]
OSX/libsecurity_codesigning/lib/CSCommon.h
OSX/libsecurity_codesigning/lib/CSCommonPriv.h
OSX/libsecurity_codesigning/lib/Code.cpp
OSX/libsecurity_codesigning/lib/CodeSigner.cpp
OSX/libsecurity_codesigning/lib/CodeSigner.h
OSX/libsecurity_codesigning/lib/SecCode.cpp
OSX/libsecurity_codesigning/lib/SecCode.h
OSX/libsecurity_codesigning/lib/SecCodeSigner.cpp
OSX/libsecurity_codesigning/lib/SecCodeSigner.h
OSX/libsecurity_codesigning/lib/SecStaticCode.cpp
OSX/libsecurity_codesigning/lib/SecStaticCode.h
OSX/libsecurity_codesigning/lib/StaticCode.cpp
OSX/libsecurity_codesigning/lib/StaticCode.h
OSX/libsecurity_codesigning/lib/bundlediskrep.cpp
OSX/libsecurity_codesigning/lib/bundlediskrep.h
OSX/libsecurity_codesigning/lib/cdbuilder.cpp
OSX/libsecurity_codesigning/lib/cdbuilder.h
OSX/libsecurity_codesigning/lib/codedirectory.cpp
OSX/libsecurity_codesigning/lib/codedirectory.h
OSX/libsecurity_codesigning/lib/csutilities.h
OSX/libsecurity_codesigning/lib/diskimagerep.cpp [new file with mode: 0644]
OSX/libsecurity_codesigning/lib/diskimagerep.h [new file with mode: 0644]
OSX/libsecurity_codesigning/lib/diskrep.cpp
OSX/libsecurity_codesigning/lib/diskrep.h
OSX/libsecurity_codesigning/lib/machorep.cpp
OSX/libsecurity_codesigning/lib/machorep.h
OSX/libsecurity_codesigning/lib/opaquewhitelist.cpp
OSX/libsecurity_codesigning/lib/policydb.h
OSX/libsecurity_codesigning/lib/policyengine.cpp
OSX/libsecurity_codesigning/lib/reqinterp.cpp
OSX/libsecurity_codesigning/lib/reqinterp.h
OSX/libsecurity_codesigning/lib/resources.cpp
OSX/libsecurity_codesigning/lib/resources.h
OSX/libsecurity_codesigning/lib/security_codesigning.exp
OSX/libsecurity_codesigning/lib/signer.cpp
OSX/libsecurity_codesigning/lib/signer.h
OSX/libsecurity_codesigning/lib/signerutils.cpp
OSX/libsecurity_codesigning/lib/signerutils.h
OSX/libsecurity_codesigning/lib/singlediskrep.cpp
OSX/libsecurity_codesigning/lib/singlediskrep.h
OSX/libsecurity_codesigning/lib/xpcengine.cpp
OSX/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj
OSX/libsecurity_cssm/lib/cssmapple.h
OSX/libsecurity_cssm/lib/cssmapplePriv.h
OSX/libsecurity_filedb/lib/AppleDatabase.cpp
OSX/libsecurity_filedb/lib/AppleDatabase.h
OSX/libsecurity_keychain/lib/ACL.cpp
OSX/libsecurity_keychain/lib/ACL.h
OSX/libsecurity_keychain/lib/Access.cpp
OSX/libsecurity_keychain/lib/Access.h
OSX/libsecurity_keychain/lib/CCallbackMgr.cp
OSX/libsecurity_keychain/lib/Certificate.cpp
OSX/libsecurity_keychain/lib/Certificate.h
OSX/libsecurity_keychain/lib/Globals.cpp
OSX/libsecurity_keychain/lib/Globals.h
OSX/libsecurity_keychain/lib/Item.cpp
OSX/libsecurity_keychain/lib/Item.h
OSX/libsecurity_keychain/lib/KCCursor.cpp
OSX/libsecurity_keychain/lib/KCCursor.h
OSX/libsecurity_keychain/lib/KeyItem.cpp
OSX/libsecurity_keychain/lib/KeyItem.h
OSX/libsecurity_keychain/lib/Keychains.cpp
OSX/libsecurity_keychain/lib/Keychains.h
OSX/libsecurity_keychain/lib/SecACL.cpp
OSX/libsecurity_keychain/lib/SecAccess.cpp
OSX/libsecurity_keychain/lib/SecAccess.h
OSX/libsecurity_keychain/lib/SecCertificate.cpp
OSX/libsecurity_keychain/lib/SecCertificatePriv.h
OSX/libsecurity_keychain/lib/SecFrameworkP.c
OSX/libsecurity_keychain/lib/SecImportExportCrypto.cpp
OSX/libsecurity_keychain/lib/SecItem.cpp
OSX/libsecurity_keychain/lib/SecItemConstants.c
OSX/libsecurity_keychain/lib/SecItemPriv.h
OSX/libsecurity_keychain/lib/SecKeychain.cpp
OSX/libsecurity_keychain/lib/SecKeychainItem.cpp
OSX/libsecurity_keychain/lib/SecKeychainItemPriv.h
OSX/libsecurity_keychain/lib/SecKeychainPriv.h
OSX/libsecurity_keychain/lib/SecPolicy.cpp
OSX/libsecurity_keychain/lib/SecPolicyPriv.h
OSX/libsecurity_keychain/lib/StorageManager.cpp
OSX/libsecurity_keychain/lib/StorageManager.h
OSX/libsecurity_keychain/lib/Trust.cpp
OSX/libsecurity_keychain/lib/Trust.h
OSX/libsecurity_keychain/lib/security_keychain.exp
OSX/libsecurity_keychain/libDER/libDER.xcodeproj/project.pbxproj
OSX/libsecurity_keychain/libDER/libDER/oids.c
OSX/libsecurity_keychain/libDER/libDER/oidsPriv.h
OSX/libsecurity_keychain/libsecurity_keychain.xcodeproj/project.pbxproj
OSX/libsecurity_keychain/regressions/kc-30-xara-helpers.h [new file with mode: 0644]
OSX/libsecurity_keychain/regressions/kc-30-xara-item-helpers.h [new file with mode: 0644]
OSX/libsecurity_keychain/regressions/kc-30-xara-key-helpers.h [new file with mode: 0644]
OSX/libsecurity_keychain/regressions/kc-30-xara-upgrade-helpers.h [new file with mode: 0644]
OSX/libsecurity_keychain/regressions/kc-30-xara.c [new file with mode: 0644]
OSX/libsecurity_keychain/regressions/kc-42-trust-revocation.c
OSX/libsecurity_keychain/regressions/keychain_regressions.h
OSX/libsecurity_manifest/lib/ManifestInternal.cpp
OSX/libsecurity_smime/lib/SecCmsBase.h
OSX/libsecurity_smime/lib/SecCmsSignerInfo.h
OSX/libsecurity_smime/lib/cmsattr.c
OSX/libsecurity_smime/lib/cmssigdata.c
OSX/libsecurity_smime/lib/cmssiginfo.c
OSX/libsecurity_smime/lib/cmstpriv.h
OSX/libsecurity_smime/lib/secoid.c
OSX/libsecurity_smime/lib/security_smime.exp
OSX/libsecurity_transform/lib/SecCustomTransform.cpp
OSX/libsecurity_transform/lib/c++utils.cpp
OSX/libsecurity_utilities/lib/CSPDLTransaction.cpp [new file with mode: 0644]
OSX/libsecurity_utilities/lib/CSPDLTransaction.h [new file with mode: 0644]
OSX/libsecurity_utilities/lib/cfmunge.cpp
OSX/libsecurity_utilities/lib/cfutilities.h
OSX/libsecurity_utilities/lib/debugging_internal.cpp
OSX/libsecurity_utilities/lib/debugging_internal.h
OSX/libsecurity_utilities/lib/exports
OSX/libsecurity_utilities/lib/hashing.h
OSX/libsecurity_utilities/lib/macho++.cpp
OSX/libsecurity_utilities/lib/macho++.h
OSX/libsecurity_utilities/lib/memstreams.h
OSX/libsecurity_utilities/lib/superblob.h
OSX/libsecurity_utilities/lib/threading.cpp
OSX/libsecurity_utilities/lib/threading.h
OSX/libsecurity_utilities/lib/unix++.h
OSX/libsecurity_utilities/libsecurity_utilities.xcodeproj/project.pbxproj
OSX/libsecurityd/lib/ssblob.cpp
OSX/libsecurityd/lib/ssblob.h
OSX/libsecurityd/lib/ssclient.h
OSX/libsecurityd/lib/transition.cpp
OSX/libsecurityd/mig/ucsp.defs
OSX/regressions/regressions.xcodeproj/project.pbxproj
OSX/regressions/test/testenv.c [deleted file]
OSX/regressions/test/testenv.m [new file with mode: 0644]
OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.h
OSX/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m
OSX/sec/SOSCircle/CloudKeychainProxy/cloudkeychainproxy.m
OSX/sec/SOSCircle/IDSKeychainSyncingProxy/IDSProxy.m
OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.entitlements.plist
OSX/sec/SOSCircle/IDSKeychainSyncingProxy/idskeychainsyncingproxy.m
OSX/sec/SOSCircle/Regressions/SOSRegressionUtilities.c
OSX/sec/SOSCircle/Regressions/SOSTestDataSource.c
OSX/sec/SOSCircle/Regressions/SOSTestDevice.c
OSX/sec/SOSCircle/Regressions/sc-130-resignationticket.c
OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.c
OSX/sec/SOSCircle/SecureObjectSync/SOSAccount.h
OSX/sec/SOSCircle/SecureObjectSync/SOSAccountBackup.c
OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c
OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c
OSX/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h
OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.c
OSX/sec/SOSCircle/SecureObjectSync/SOSBackupSliceKeyBag.h
OSX/sec/SOSCircle/SecureObjectSync/SOSCircle.c
OSX/sec/SOSCircle/SecureObjectSync/SOSCirclePriv.h
OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.c
OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircle.h
OSX/sec/SOSCircle/SecureObjectSync/SOSCloudCircleInternal.h
OSX/sec/SOSCircle/SecureObjectSync/SOSCoder.c
OSX/sec/SOSCircle/SecureObjectSync/SOSDataSource.h
OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.c
OSX/sec/SOSCircle/SecureObjectSync/SOSEngine.h
OSX/sec/SOSCircle/SecureObjectSync/SOSExports.exp-in
OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c
OSX/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.h
OSX/sec/SOSCircle/SecureObjectSync/SOSInternal.h
OSX/sec/SOSCircle/SecureObjectSync/SOSPeer.c
OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.c
OSX/sec/SOSCircle/SecureObjectSync/SOSPeerCoder.h
OSX/sec/SOSCircle/SecureObjectSync/SOSPeerInfoV2.c
OSX/sec/SOSCircle/SecureObjectSync/SOSSysdiagnose.c [new file with mode: 0644]
OSX/sec/SOSCircle/SecureObjectSync/SOSTransport.c
OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.c [deleted file]
OSX/sec/SOSCircle/SecureObjectSync/SOSTransportCoder.h [deleted file]
OSX/sec/SOSCircle/SecureObjectSync/SOSTransportMessageIDS.c
OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.c [deleted file]
OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.h [deleted file]
OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c [deleted file]
OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.h [deleted file]
OSX/sec/SOSCircle/Tool/SOSCommands.h [deleted file]
OSX/sec/SOSCircle/Tool/keychain_log.c [new file with mode: 0644]
OSX/sec/SOSCircle/Tool/keychain_log.h [new file with mode: 0644]
OSX/sec/SOSCircle/Tool/keychain_sync.c
OSX/sec/SOSCircle/Tool/keychain_sync.h [new file with mode: 0644]
OSX/sec/SOSCircle/Tool/secToolFileIO.c [new file with mode: 0644]
OSX/sec/SOSCircle/Tool/secToolFileIO.h [new file with mode: 0644]
OSX/sec/Security/AppleBaselineEscrowCertificates.h
OSX/sec/Security/Regressions/Security_regressions.h
OSX/sec/Security/Regressions/secitem/si-13-item-system.m [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si-17-item-system-bluetooth.m [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si-20-sectrust.c
OSX/sec/Security/Regressions/secitem/si-20-sectrust.h
OSX/sec/Security/Regressions/secitem/si-30-keychain-upgrade.c
OSX/sec/Security/Regressions/secitem/si-31-keychain-bad.c
OSX/sec/Security/Regressions/secitem/si-31-keychain-unreadable.c
OSX/sec/Security/Regressions/secitem/si-73-secpasswordgenerate.c
OSX/sec/Security/Regressions/secitem/si-76-shared-credentials.c
OSX/sec/Security/Regressions/secitem/si-88-sectrust-vpnprofile.c
OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.c [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si-89-cms-hash-agility.h [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si-90-emcs.m [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.c [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si-91-sectrust-ast2.h [new file with mode: 0644]
OSX/sec/Security/Regressions/secitem/si_77_SecAccessControl.c
OSX/sec/Security/SecCMS.c
OSX/sec/Security/SecCertificate.c
OSX/sec/Security/SecCertificate.h
OSX/sec/Security/SecCertificateInternal.h
OSX/sec/Security/SecEMCS.m [new file with mode: 0644]
OSX/sec/Security/SecEMCSPriv.h [new file with mode: 0644]
OSX/sec/Security/SecExports.exp-in
OSX/sec/Security/SecFrameworkStrings.h
OSX/sec/Security/SecItem.c
OSX/sec/Security/SecItemBackup.c
OSX/sec/Security/SecItemBackup.h
OSX/sec/Security/SecItemConstants.c
OSX/sec/Security/SecItemInternal.h
OSX/sec/Security/SecItemPriv.h
OSX/sec/Security/SecOTRPacketData.h
OSX/sec/Security/SecPasswordGenerate.c
OSX/sec/Security/SecPolicy.c
OSX/sec/Security/SecPolicyInternal.h
OSX/sec/Security/SecPolicyPriv.h
OSX/sec/Security/SecSharedCredential.c
OSX/sec/Security/SecTrust.c
OSX/sec/Security/SecuritydXPC.c
OSX/sec/Security/SecuritydXPC.h
OSX/sec/SecurityTool/builtin_commands.h
OSX/sec/SecurityTool/entitlements.plist
OSX/sec/SecurityTool/syncbubble.m [new file with mode: 0644]
OSX/sec/SecurityTool/whoami.m [new file with mode: 0644]
OSX/sec/ipc/client.c
OSX/sec/ipc/securityd_client.h
OSX/sec/ipc/server.c
OSX/sec/sec.xcodeproj/project.pbxproj
OSX/sec/securityd/Regressions/SecdTestKeychainUtilities.c
OSX/sec/securityd/Regressions/secd-01-items.c
OSX/sec/securityd/Regressions/secd-05-corrupted-items.c [deleted file]
OSX/sec/securityd/Regressions/secd-05-corrupted-items.m [new file with mode: 0644]
OSX/sec/securityd/Regressions/secd-154-engine-backoff.c [new file with mode: 0644]
OSX/sec/securityd/Regressions/secd-20-keychain_upgrade.m [new file with mode: 0644]
OSX/sec/securityd/Regressions/secd-21-transmogrify.m [new file with mode: 0644]
OSX/sec/securityd/Regressions/secd-33-keychain-ctk.c
OSX/sec/securityd/Regressions/secd-34-backup-der-parse.c
OSX/sec/securityd/Regressions/secd-62-account-backup.c
OSX/sec/securityd/Regressions/secd-70-engine.c
OSX/sec/securityd/Regressions/secd-80-views-basic.c
OSX/sec/securityd/Regressions/secd-81-item-acl-stress.c
OSX/sec/securityd/Regressions/secd-81-item-acl.c
OSX/sec/securityd/Regressions/secd60-account-cloud-exposure.c [new file with mode: 0644]
OSX/sec/securityd/Regressions/secd_regressions.h
OSX/sec/securityd/SOSCloudCircleServer.c
OSX/sec/securityd/SOSCloudCircleServer.h
OSX/sec/securityd/SecCAIssuerRequest.c
OSX/sec/securityd/SecDbItem.c
OSX/sec/securityd/SecDbItem.h
OSX/sec/securityd/SecDbQuery.c
OSX/sec/securityd/SecDbQuery.h
OSX/sec/securityd/SecItemDataSource.c
OSX/sec/securityd/SecItemDb.c
OSX/sec/securityd/SecItemDb.h
OSX/sec/securityd/SecItemSchema.c
OSX/sec/securityd/SecItemSchema.h
OSX/sec/securityd/SecItemServer.c
OSX/sec/securityd/SecItemServer.h
OSX/sec/securityd/SecKeybagSupport.c
OSX/sec/securityd/SecPolicyServer.c
OSX/sec/securityd/SecTrustServer.c
OSX/sec/securityd/entitlements.plist
OSX/sec/securityd/iCloudTrace.c
OSX/sec/securityd/spi.c
OSX/sectests/SecurityTests-Entitlements.plist
OSX/sectests/testlist.h
OSX/security2/sub_commands.h
OSX/utilities/Regressions/su-41-secdb-stress.c
OSX/utilities/SecurityTool/security_tool_commands.h
OSX/utilities/src/SecAKSWrappers.c
OSX/utilities/src/SecAKSWrappers.h
OSX/utilities/src/SecAppleAnchor.c
OSX/utilities/src/SecAppleAnchorPriv.h
OSX/utilities/src/SecDb.c
OSX/utilities/src/SecDb.h
OSX/utilities/src/SecTrace.c [new file with mode: 0644]
OSX/utilities/src/SecTrace.h [new file with mode: 0644]
OSX/utilities/src/debugging.c
OSX/utilities/src/der_plist.h
OSX/utilities/utilities.xcodeproj/project.pbxproj
OTAPKIAssetTool/OTAServiceApp.m
RegressionTests/Security.plist [new file with mode: 0644]
RegressionTests/Security_edumode.plist [new file with mode: 0644]
RegressionTests/secbackupntest/secbackupntest.m [new file with mode: 0644]
RegressionTests/secbackuptest/secbackuptest.entitlements [new file with mode: 0644]
RegressionTests/secbackuptest/secbackuptest.m [new file with mode: 0644]
RegressionTests/secedumodetest/secedumodetest.entitlements [new file with mode: 0644]
RegressionTests/secedumodetest/secedumodetest.m [new file with mode: 0644]
Security.xcodeproj/project.pbxproj
Security.xcodeproj/xcshareddata/xcschemes/Debug.xcscheme
Security.xcodeproj/xcshareddata/xcschemes/Release.xcscheme
Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme
SecurityTests/SecurityTests-Entitlements.plist
SecurityTool/SecurityTool.xcodeproj/project.pbxproj
SecurityTool/entitlements.plist
SecurityTool/keychain_find.c
SecurityTool/keychain_find.h
SecurityTool/keychain_unlock.c
SecurityTool/keychain_utilities.c
SecurityTool/keychain_utilities.h
SecurityTool/security.c
SecurityTool/sub_commands.h
codesign_wrapper/codesign_wrapper.c
libsecurity_smime/lib/SecCmsBase.h
libsecurity_smime/lib/SecCmsSignerInfo.h
libsecurity_smime/lib/cmsattr.c
libsecurity_smime/lib/cmsrecinfo.c
libsecurity_smime/lib/cmssiginfo.c
libsecurity_smime/lib/cmstpriv.h
libsecurity_smime/lib/crypto-embedded.c
libsecurity_smime/lib/secoid.c
libsecurity_smime/lib/security_smime.exp
libsecurity_smime/libsecurity_smime.xcodeproj/project.pbxproj
resources/English.lproj/CloudKeychain.strings
secdtests/secdtests-entitlements.plist
sectask/SecEntitlements.h
securityd/securityd.xcodeproj/project.pbxproj
securityd/src/acl_keychain.cpp
securityd/src/acl_keychain.h
securityd/src/acl_partition.cpp [new file with mode: 0644]
securityd/src/acl_partition.h [new file with mode: 0644]
securityd/src/acls.cpp
securityd/src/acls.h
securityd/src/clientid.cpp
securityd/src/clientid.h
securityd/src/database.cpp
securityd/src/database.h
securityd/src/dbcrypto.cpp
securityd/src/dbcrypto.h
securityd/src/kcdatabase.cpp
securityd/src/kcdatabase.h
securityd/src/kckey.cpp
securityd/src/localkey.cpp
securityd/src/main.cpp
securityd/src/server.h
securityd/src/tempdatabase.cpp
securityd/src/tempdatabase.h
securityd/src/tokendatabase.h
securityd/src/transition.cpp

index bdb248f50fa13ec5adde7bd96c4ddec2e66511aa..4c8bddd3b0920ad490996864cddd74d387f43cdf 100644 (file)
@@ -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 = @{
index e571be54c5f928792a4a685132279b52bdb1af28..9f09d8bc67aa54b6a20a178ec7cadcc5f8848f7f 100644 (file)
@@ -19,6 +19,8 @@
        <string>com.apple.security.idskeychainsyncingproxy</string>
        <key>EnvironmentVariables</key>
        <dict>
+               <key>DEBUGSCOPE</key>
+               <string>all</string>
                <key>WAIT4DEBUGGER</key>
                <string>NO</string>
        </dict>
index 93d2bd9207b95683dc2d00f420f4ee7c094a9b54..f62eceff9494fe7bbf3fba9a1b394abb8abfcbf8 100644 (file)
@@ -4,6 +4,10 @@
 <dict>
        <key>com.apple.wifi.manager-access</key>
        <true/>
+       <key>com.apple.private.ids.force-encryption-off</key>
+       <array>
+               <string>com.apple.private.alloy.keychainsync</string>
+       </array>
        <key>com.apple.private.ids.remoteurlconnection</key>
        <true/>
        <key>com.apple.private.ids.messaging.high-priority</key>
index 6732c26478fd9050229aeca864d63ffee44902ed..6c9d8691d5d9571912deae3282f4c44899dc2c04 100644 (file)
@@ -19,6 +19,8 @@
        <string>com.apple.security.idskeychainsyncingproxy</string>
        <key>EnvironmentVariables</key>
        <dict>
+               <key>DEBUGSCOPE</key>
+               <string>all</string>
                <key>WAIT4DEBUGGER</key>
                <string>NO</string>
        </dict>
index 93d2bd9207b95683dc2d00f420f4ee7c094a9b54..9d23eb1c09f0fb0a3ab223d7012c244a85d27659 100644 (file)
@@ -6,6 +6,10 @@
        <true/>
        <key>com.apple.private.ids.remoteurlconnection</key>
        <true/>
+       <key>com.apple.private.ids.force-encryption-off</key>
+       <array>
+               <string>com.apple.private.alloy.keychainsync</string>
+       </array>
        <key>com.apple.private.ids.messaging.high-priority</key>
        <array>
                <string>com.apple.private.alloy.keychainsync</string>
index 224bc12359612c8d08642b3bdc24fd6274ca983a..044bd17b424f16d862fa9da22f60ae277ef9b254 100644 (file)
@@ -483,7 +483,7 @@ bool isAppleInternal(void)
                message = [message stringByAppendingString: reason_str];
        }
 
-       // <rdar://problem/21988060> Improve wording of the iCloud keychain drop/reset error messages
+       // <rdar://problem/21988060> [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)
                }
        }
 
-       // <rdar://problem/21988060> Improve wording of the iCloud keychain drop/reset error messages
+       // <rdar://problem/21988060> [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
index 71ef2e338c773ab5cc82eb8e345e9605fa472bb6..2bb44ff5beaf692a9982fc2c355f7182c01c3a66 100644 (file)
                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 */; };
                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 */
 
                        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 */;
                EB22F3F618A26BA50016A8EC /* breadcrumb_regressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breadcrumb_regressions.h; path = Breadcrumb/breadcrumb_regressions.h; sourceTree = "<group>"; };
                EB22F3F718A26BA50016A8EC /* SecBreadcrumb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SecBreadcrumb.c; path = Breadcrumb/SecBreadcrumb.c; sourceTree = "<group>"; };
                EB22F3F818A26BA50016A8EC /* SecBreadcrumb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecBreadcrumb.h; path = Breadcrumb/SecBreadcrumb.h; sourceTree = "<group>"; };
+               EB93FF531BE088F600978606 /* secbackupntest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = secbackupntest.m; path = secbackupntest/secbackupntest.m; sourceTree = "<group>"; };
+               EB93FF541BE088FC00978606 /* Security.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Security.plist; sourceTree = "<group>"; };
+               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 = "<group>"; };
+               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 = "<group>"; };
 /* End PBXFileReference section */
 
                        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 */,
                        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 */,
                        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 */,
                        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 */,
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               EBF2E29D1BEC8D9200626DE4 /* IOKit.framework in Frameworks */,
                                43C3B0D41AFD569600786702 /* Security.framework in Frameworks */,
                                43C3B3311AFD5E1100786702 /* CoreFoundation.framework in Frameworks */,
                        );
                                37AB39101A44A88000B56E04 /* gk_reset_check */,
                                CD63ACE11A8061FA001B5671 /* IDSKeychainSyncingProxy */,
                                5EF7C20B1B00E25400E5E99C /* secacltests */,
+                               EB93FF2A1BE0889E00978606 /* RegressionTests */,
                                1807384D146D0D4E00F05C24 /* Frameworks */,
                                1807384C146D0D4E00F05C24 /* Products */,
                        );
                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 */,
                        isa = PBXGroup;
                        children = (
                                1879B654146DE750007E536C /* libsecurity_cms.a */,
+                               D4CBC1281BE981DE00C5795E /* libsecurity_cms_regressions.a */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                        name = Breadcrumb;
                        sourceTree = "<group>";
                };
+               EB93FF2A1BE0889E00978606 /* RegressionTests */ = {
+                       isa = PBXGroup;
+                       children = (
+                               EB93FF541BE088FC00978606 /* Security.plist */,
+                               EB93FF521BE088E000978606 /* secbackupntest */,
+                       );
+                       name = RegressionTests;
+                       path = ../RegressionTests;
+                       sourceTree = "<group>";
+               };
+               EB93FF521BE088E000978606 /* secbackupntest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               EB93FF531BE088F600978606 /* secbackupntest.m */,
+                       );
+                       name = secbackupntest;
+                       sourceTree = "<group>";
+               };
                F93C493C1AB8FF670047E01A /* ckcdiagnose */ = {
                        isa = PBXGroup;
                        children = (
                        buildRules = (
                        );
                        dependencies = (
+                               D4CBC11A1BE981DE00C5795E /* PBXTargetDependency */,
                                0C6C632E15D19D2900BC68CD /* PBXTargetDependency */,
                                ACB6173F18B5232700EBEDD7 /* PBXTargetDependency */,
                                0CBD50C716C3260D00713B6C /* PBXTargetDependency */,
                        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;
                        name = XPCTimeStampingService;
                        targetProxy = D4A2FC7D1BC89D5200BF6E56 /* PBXContainerItemProxy */;
                };
+               D4CBC11A1BE981DE00C5795E /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       name = libsecurity_cms_regressions;
+                       targetProxy = D4CBC1191BE981DE00C5795E /* PBXContainerItemProxy */;
+               };
                E76079FA1951FDF600F69731 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        name = liblogging;
index 84b9ae52cc4a21b0b982496d99f40a8810c11131..081a81f48103af9518cf31c34a5b4f844e3fb328 100644 (file)
             argument = "ssl-42-ciphers"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "kc-30-xara"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "ssl-43-ciphers"
             isEnabled = "NO">
@@ -80,7 +84,7 @@
          </CommandLineArgument>
          <CommandLineArgument
             argument = "ssl-46-SSLGetSupportedCiphers"
-            isEnabled = "YES">
+            isEnabled = "NO">
          </CommandLineArgument>
          <CommandLineArgument
             argument = "ssl-47-falsestart"
             argument = "ssl-54-dhe"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_33_keychain_backup"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "cms-hash-agility-test"
+            isEnabled = "NO">
+         </CommandLineArgument>
       </CommandLineArguments>
       <AdditionalOptions>
       </AdditionalOptions>
index ba3b7779cca04cfb82b82ea4159b590ec9d2b5ef..f92e458a673aeed1f34cc3fc898942e2232c1c1f 100644 (file)
@@ -11,7 +11,8 @@
             buildForRunning = "YES"
             buildForProfiling = "YES"
             buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
+            buildForAnalyzing = "YES"
+            hideIssues = "NO">
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "182BB598146FE295000BF1F3"
@@ -25,7 +26,8 @@
             buildForRunning = "YES"
             buildForProfiling = "YES"
             buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
+            buildForAnalyzing = "YES"
+            hideIssues = "NO">
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "0CC3350716C1ED8000399E53"
             argument = "-s"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "secd_60_account_cloud_exposure"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "secd_60_account_cloud_identity"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "secd_64_circlereset"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "sc_42_circlegencount"
             isEnabled = "NO">
index da098fe2133e89f4e47523fb54fed79d7a5f67d1..8406e487c799f7b34d319acf97979f000d0d63f1 100644 (file)
@@ -1428,6 +1428,13 @@ See remaining rules for examples.
                                <string>authenticate-admin-30</string>
                        </array>
                </dict>
+               <key>com.apple.security.syntheticinput</key>
+               <dict>
+                   <key>class</key>
+                   <string>rule</string>
+                   <key>rule</key>
+                   <string>authenticate-session-owner</string>
+               </dict>         
        </dict>
        <key>rules</key>
        <dict>
index 276ac5f269d6330cb360a54195fab96afdd0901c..5e6d2ae82fcc20127a2ae73da1a495e09c9017e5 100644 (file)
@@ -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;
     }
     
index b29182f10d174ee9aef2c9e19d46c0f12f357f95..ef07e3251ba4704c3a88fe39c459ce0fed8cf6fb 100644 (file)
@@ -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);
index 241645c8d332b164924415b145ba13640dfe11eb..6865b0dd232e06d7cf0978fecda7e445e1f26e97 100755 (executable)
@@ -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
 
 #
 #
index e04e8e537c3de62c8f9e915bfe012206c8752540..39d7aed2150630b222a2e67cdf13791bc8cda5b3 100644 (file)
@@ -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
index 8ae93c2e218321fceaa9ae30639226a6c113b283..6f15d7a52713d6b27f3250654ac5ccc3bf35577e 100644 (file)
@@ -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_ptr<Dictionary>apd(d);
index 3c6b24e4f0ae74dcfe533cf0c1d1c8a8a0c1108b..cfc622367338e8e1e54b8d4fc710ebd2b9129ce0 100644 (file)
@@ -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<SSKey>(inKey);
+
+    secdebug("SecAccessReference", "looked up a sskey with handle %d [%d]", theKey.keyHandle(), theKey.keyReference());
        
        #ifdef someday 
        /* 
index 8fa42e4458de44a24609bf8246bb65f1bed8447a..40bc29fa0982d5742cd65441a8608b6821336df7 100644 (file)
@@ -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);
index 672dae883fd887b51fd25171abd9108effd07fd1..755d232af87da4d44859a26a2f22d6846272a879 100644 (file)
@@ -22,6 +22,8 @@
 #include "SSDatabase.h"
 
 #include <security_cdsa_utilities/KeySchema.h>
+#include <security_utilities/CSPDLTransaction.h>
+#include <Security/SecBasePriv.h>
 
 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<const void *>(1));
+    }
+    catch (...)
+    {
+        // Something went wrong rollback the transaction
+        passThrough(CSSM_APPLEFILEDL_ROLLBACK, NULL);
+        passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT,
+                reinterpret_cast<const void *>(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<const void *>(1));
-       }
-       catch (...)
-       {
-               // Something went wrong rollback the transaction
-               passThrough(CSSM_APPLEFILEDL_ROLLBACK, NULL);
-               passThrough(CSSM_APPLEFILEDL_TOGGLE_AUTOCOMMIT,
-                       reinterpret_cast<const void *>(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<DbBlob>(dbb.length());
+    memcpy(x, dbb, dbb.length());
+    uint32 version = x->version();
+    Allocator::standard().free(x);
+    return version;
+}
+
 DbUniqueRecordImpl *
 SSDatabaseImpl::newDbUniqueRecord()
 {
index 1566aed277e170e7d9845355acaf3f82a263e6cf..04ed9c05f762ccf07282936579ea61f18abe2f1a 100644 (file)
@@ -25,6 +25,8 @@
 #include <security_cdsa_client/dlclient.h>
 #include <security_utilities/unix++.h>
 #include <securityd_client/ssclient.h>
+#include <securityd_client/ssblob.h>
+#include <security_utilities/CSPDLTransaction.h>
 
 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;
 };
 
 
index 5eacdf9595ef08a8b747519af2c4cd08ee8e7a09..69c57b511225c7d2727582475c8766f89c5812d7 100644 (file)
@@ -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
        }
 
index 4781af8c9c31fa81c762eb5ea85a35fd971948df..165228a51327a6a9c8e7c3200731714286946265 100644 (file)
@@ -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;
index 5ba632f959498ad730dad61b40b75a9f5b99c4a1..0810f0ba2df25677dd9b8493aaac47014e0b219f 100644 (file)
@@ -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;
index d09592be93c767eaa9304b4244a676d87f3cf473..456309ab44af281365366271485f94b32a4749d1 100644 (file)
@@ -37,6 +37,7 @@
  *
  * $Id: secasn1d.c,v 1.16 2004/05/13 15:29:13 dmitch Exp $
  */
+#include <limits.h>
 
 #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);
index e695972f30f0a4075a60c3940556a3eb123009c4..5f383adeae2a174ac0a682745466f722bfb4b036 100644 (file)
@@ -40,6 +40,8 @@
 
 #include "secasn1.h"
 
+#include <syslog.h>
+
 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);
index 00b5b513d574025e3d3e3299d9fa52323a73830e..2daa1cfda54e817881f4acbaffbcb8625261e0a8 100644 (file)
@@ -120,6 +120,7 @@ protected:
                Allocator &allocator;
 
         operator const AccessCredentials* () const { return mCredentials; }
+        AccessCredentials* getAccessCredentials() const { return mCredentials; }
        
     protected:
                AutoCredentials *mCredentials;
index 882fde1e21e082de2761d9043d0972c9965e4d4e..127f9b1308799fd2e2b4350197f5767f9d3142b6 100644 (file)
@@ -24,6 +24,7 @@
 #include <Security/cssmapple.h>
 #include <Security/cssmapplePriv.h>
 #include <Security/SecBase.h>
+#include <security_cdsa_utilities/Schema.h>
 
 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
+        }
+    }
+}
index 23c242c2437c8c3948684209711b2076a1f46a63..6617a392377c616c565f9ba954268f5a43c195b3 100644 (file)
@@ -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();
 };
 
 
index 271774c9d3c8f1a91aa25f3bb1f25f5123bdef0a..f116654100b3636815cd5d279c49daf9528d9f9b 100644 (file)
@@ -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);
-}
index 05e1354d742ab887397723ee9feb16de16c449cb..5cf097b4d953cdbfa83a22b8688bd485ea508935 100644 (file)
@@ -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;
index 6fb56f0d4bb2135a420270ac177ea4f32f68db09..40b1c0edecc31dfbac8efe86a3c44a37c5e13ec0 100644 (file)
@@ -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<CssmKey *>(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<CssmKey *>(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;
 }
 
index 41f4ee856bfc8def88937535e13ad90568cbb2a6..f2b674ff61fecf632203248e4d4a19f11461840b 100644 (file)
@@ -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;
 }
 
index 69fd626f783cb772f0d7507d248aa25ada989bce..5331db0d77c305401427c0e54a761c236ea3d281 100644 (file)
@@ -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;
index 5bc9248fc21664acbbb5976199e72b170a100fae..f3b84278beda715bc3e69b10d404682cb90daa2a 100644 (file)
@@ -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)
 {
index 25f6a0e5191cd1c15f6f08ed0347d875bf9e96fc..99479cc7870cb565a5a488a3d77c628327f6e721 100644 (file)
@@ -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;
 }
index b985c872d8ea5e2d59b2a302a8d83ca80bd14fae..7553652f0d246bf328724e71e1d7b3c3d728b54e 100644 (file)
@@ -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 {
index a848449f4365a165111d50d3ea4644fe092f36c6..5c0cc03fd892693aa8f62e61fd07a78784018186 100644 (file)
@@ -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<Environment>())
index 2dc2b2b3dee81b8266b72479429eab1f43d40b52..39628f2b01a830e52204f18a6a7ece99367802c8 100644 (file)
@@ -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);
index 8cf7501f739dd5eaf728adc7f12cc547ff0d16aa..fdc29c9f5780bb9567c84b0bee7d9ebcaada968f 100644 (file)
@@ -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;
 }
index 98a90b92477239cbb04b7bb22c6a4ada99e87e22..55796b7e139ec6e63663e4258f82fc3d1aea6a7e 100644 (file)
@@ -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);
index 121b2a272b82007f38ac1d6e283e60fe4985ebfc..cd4a5f812879fa3ceae6d727eebec312c1e8b4b8 100644 (file)
@@ -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<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<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;
                        }
index ee56b95e170ac5b90519542a069183666739da63..333be37f795a4c08dc72ac96deaf6629de5c553f 100644 (file)
@@ -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,
index f8a8cea9e7c11794bb19d8f30638cc5692eccad4..7918ff4704dfdd41d7e4d262d31db3ef56e0c99d 100644 (file)
@@ -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));
index 79bf66b3905d9f39ff34c77a1b5534fddac1f19d..de7632fb50463aec51b6f20ddab8fa36c806d850 100644 (file)
@@ -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)
index be4c25878208c07c3c82a7ed46eb6ed5b4e810ac..cfced63e971ebef9beecd451d19002d415cdc999 100644 (file)
@@ -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) {
index 10c11fdc52f33d252a3eb6e522fd87d69dac246e..a1c9c777128959dc21ba99ecc8514f2b2ca5dde3 100644 (file)
@@ -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);
index 87a6c19327962a4ec5799d4c44d1c3e986680643..df678e2a9740b9e494b131c3a51d8789969a0ee7 100644 (file)
@@ -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);
index 1166eafa5812c3e3f04e50583d5a89e47c3b01e7..ead024a5f630e22cb82d52b7a9596c9f8e3ca9be 100644 (file)
@@ -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);
index 17e568f91165dd6e06c078f1685d441437d74008..835a56be68d45e117822f1bdfeb78934a0f7a5f2 100644 (file)
@@ -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)
index 437f78f02a82891bdf42c5aff9ed1c97337e3e2f..edbc3e7b17ad833cd0f8c08696606c1605c3daf3 100644 (file)
@@ -50,7 +50,7 @@ class ThresholdAclSubject : public SimpleAclSubject {
     typedef ObjectAcl::AclSubjectPointer AclSubjectPointer;
     typedef vector<AclSubjectPointer> 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);
index 70ec05e5c83ecc94c5b947ff535b1e633d000677..07951e032e74d1d7e77e6ff63125ca85248c3720 100644 (file)
@@ -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
                }
index 4ad713477323269e14c16c3f4d66b5ccdac19324..d76031849309576f5639419ded6cf584b04b60c8 100644 (file)
@@ -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;
 };
 
index 96a32b50be92e84244148196df97f0483a21adea..347971db7896ce5129be18719ab636e51713db59 100644 (file)
@@ -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
 {
index bf23f7df4f83f6e6e75f737319827de2404c5812..8a4635aac6ac3c4ce291fc0774324a9adf0ea7db 100644 (file)
@@ -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;
 };
 
index ff7d0925c00969429503d972cbfe4268acb9c7b4..44a31a05bef60421823d3bc127f7da45a55f7a63 100644 (file)
@@ -77,6 +77,35 @@ void AccessCredentials::tag(const char *tagString)
                strcpy(EntryTag, tagString);
 }
 
+bool AccessCredentials::authorizesUI() const {
+    list<CssmSample> 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<CssmSample>::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
index e0e8aae3cd87b30e71f94d4683bf51924a5dad6b..1b70b7675652251846d7fbead371a3efdfdf4316 100644 (file)
@@ -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
        
index e3546459fa3a551d62c1432c7b4140b821a217e5..58b6f7816a8c1127804a2b9fd28d5e55603a6788 100644 (file)
@@ -26,6 +26,9 @@
 //
 //
 #include <security_cdsa_utilities/cssmdb.h>
+#include <CommonCrypto/CommonDigest.h>
+
+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
 //
index 5ecb5a2964f257b55513105801675938bd04d09d..186e766987171bbb381abc81b5993a44ed80ac1e 100644 (file)
@@ -33,7 +33,7 @@
 #include <security_cdsa_utilities/cssmdata.h>
 #include <security_cdsa_utilities/cssmpods.h>
 #include <security_cdsa_utilities/cssmalloc.h>
-#include <security_cdsa_utilities/walkers.h>
+#include <security_cdsa_utilities/cssmwalkers.h>
 #include <security_cdsa_utilities/cssmdbname.h>
 
 
@@ -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);
 };
 
index c89cb273121b504f9430513d8ea1fc3fb07061c4..90f8d484baf05a5ab13db8f30893386a62e5c2c1 100644 (file)
@@ -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<EntryMap::const_iterator, EntryMap::const_iterator> 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<EntryMap::const_iterator, EntryMap::const_iterator> &range) const
+       pair<EntryMap::const_iterator, EntryMap::const_iterator> &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<AclEntryInfo>(count);
     uint32 n = 0;
+
+    secdebugfunc("SecAccess", "getting the ACL for %p (%d entries) tag: %s", this, count, tag ? tag : "<none>");
+
     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);
index c1d0825364afd02abae1e5edf9ba0e55268fb626..78a08bf7e822413907bdd92c63f62318fb014149 100644 (file)
@@ -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 <class Action>
                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 <class Action>
         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<EntryMap::const_iterator, EntryMap::const_iterator> &range) const; 
+               pair<EntryMap::const_iterator, EntryMap::const_iterator> &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);
 
index 6178a3597116a5b2f745a9092b6c500f37a5f869..b8fcb598077e14d81739256c6d095fc50d4db61a 100644 (file)
@@ -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
index a420e5eba76d6305bf7034e8ce52566ddeef2d80..a8d81d095e1077a502396eb4412331b9367cd076 100644 (file)
@@ -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;
+}
index c60110c7af64109f9e9207f5d549912050481e44..4055192abc609712ae6a00163dc093c62cd4a88c 100644 (file)
@@ -47,6 +47,7 @@
 #include <Security/SecAsn1Templates.h>
 #include <CoreFoundation/CFRuntime.h>
 #include <pthread.h>
+#include <utilities/SecCFRelease.h>
 
 #include <security_smime/tsaSupport.h>
 #include <security_smime/cmspriv.h>
@@ -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,
index 955989bb6147e8640a65c7aff8f393732b162b01..f24227b253a9fdf9822ae73b3fbb551860320525 100644 (file)
@@ -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
 };
 
 /*
index 3b90d51ad6ac7e8128cdaca441156454eac87803..b61296b24c9fa86ccb9427f827a45124461cfbca 100644 (file)
@@ -32,6 +32,7 @@
 #include <Security/SecCmsEncoder.h>
 #include <Security/SecCmsDecoder.h>
 #include <Security/SecCmsMessage.h>
+#include <AvailabilityMacros.h>
 
 #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
 }
index c416c46afd45aff33afdf214e3ce21fe6985aa14..81256d881d3b7d31d606c57c09db170e2298bfdb 100644 (file)
@@ -19,6 +19,7 @@ _CMSEncoderSetEncapsulatedContentTypeOID
 _CMSEncoderSetEncoder
 _CMSEncoderAddSignedAttributes
 _CMSEncoderSetSigningTime
+_CMSEncoderSetAppleCodesigningHashAgility
 _CMSEncoderSetCertificateChainMode
 _CMSEncoderGetCertificateChainMode
 _CMSEncoderUpdateContent
@@ -46,5 +47,6 @@ _CMSDecoderCopySignerTimestampWithPolicy
 _CMSDecoderCopySignerTimestampCertificates
 _CMSEncoderCopySignerTimestamp
 _CMSEncoderCopySignerTimestampWithPolicy
+_CMSDecoderCopySignerAppleCodesigningHashAgility
 
 
index 5963aa793e3417ae89bda668a304c3ac787d505c..8900beecffc74c6a1a612727a92d44645644ccd3 100644 (file)
@@ -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 */
                1844617A146E984400B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = "<group>"; };
                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 = "<group>"; };
+               D4C334571BE29F5200D8C1EF /* cms_regressions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cms_regressions.h; path = regressions/cms_regressions.h; sourceTree = "<group>"; };
+               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 = "<group>"; };
+               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 = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                        );
                        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 */,
                        isa = PBXGroup;
                        children = (
                                4CA1FEBE052A3C8100F22E42 /* libsecurity_cms.a */,
+                               D4C3345C1BE2A2B100D8C1EF /* libsecurity_cms_regressions.a */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                };
+               D4C334561BE29F1700D8C1EF /* regressions */ = {
+                       isa = PBXGroup;
+                       children = (
+                               D4C334571BE29F5200D8C1EF /* cms_regressions.h */,
+                               D4C334611BE2A31200D8C1EF /* cms-hashagility-test.c */,
+                               D4C334621BE2A31200D8C1EF /* cms-hashagility-test.h */,
+                       );
+                       name = regressions;
+                       sourceTree = "<group>";
+               };
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
                        );
                        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 */
                        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 */
                        isa = PBXProject;
                        attributes = {
                                LastUpgradeCheck = 0700;
+                               TargetAttributes = {
+                                       D4C3345B1BE2A2B100D8C1EF = {
+                                               CreatedOnToolsVersion = 7.1;
+                                       };
+                               };
                        };
                        buildConfigurationList = C263E67909A2971B000043F1 /* Build configuration list for PBXProject "libsecurity_cms" */;
                        compatibilityVersion = "Xcode 3.2";
                        projectRoot = "";
                        targets = (
                                4CA1FEBD052A3C8100F22E42 /* libsecurity_cms */,
+                               D4C3345B1BE2A2B100D8C1EF /* libsecurity_cms_regressions */,
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               D4C334581BE2A2B100D8C1EF /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               D4C334631BE2A31200D8C1EF /* cms-hashagility-test.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
 /* End PBXSourcesBuildPhase section */
 
 /* Begin XCBuildConfiguration section */
                        };
                        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 */
                        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 (file)
index 0000000..3024ca4
--- /dev/null
@@ -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 <test/testmore.h>
+#include <Security/SecBase.h>
+#include <utilities/SecCFRelease.h>
+#include <Security/CMSEncoder.h>
+#include <Security/SecImportExport.h>
+#include <Security/CMSPrivate.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecTrust.h>
+#include <Security/SecPolicy.h>
+#include <Security/SecKeychain.h>
+#include <Security/SecIdentity.h>
+
+#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 (file)
index 0000000..24055e7
--- /dev/null
@@ -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 <stdio.h>
+
+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 (file)
index 0000000..30a2e4e
--- /dev/null
@@ -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 <test/testmore.h>
+
+ONE_TEST(cms_hash_agility_test)
\ No newline at end of file
index 70058cf17baa4515af348dc04ac9c9c44c358768..be1be0fd4b615d91ab0035e653df9ee75824fd5d 100644 (file)
@@ -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
 
index a03ac61d90e5731ddc4857af59f5787fda77dbd3..29299cb80bf3e3056df9301cb82a3685f771bc05 100644 (file)
@@ -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
-};
        
        
 /*
index 643c4f58d9e424113aa5e5541ef0d5f4e63d4370..3194bf3dfe638aac0b8666d7bfe6f83b01cf94b1 100644 (file)
@@ -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))
index 3d80482c8e73c89b3baf8f6e983443f7fbb1db6b..783262bab48ab431512db05cfbebde46c78a9cb0 100644 (file)
@@ -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<CFNumberRef>(kSecCodeSignerDigestAlgorithm))
-               state.mDigestAlgorithm = cfNumber<unsigned int>(digestAlgorithm);
+       if (CFCopyRef<CFTypeRef> digestAlgorithms = get<CFTypeRef>(kSecCodeSignerDigestAlgorithm)) {
+               CFRef<CFArrayRef> array = cfArrayize(digestAlgorithms);
+               CFToVector<CodeDirectory::HashAlgorithm, CFNumberRef, cfNumber<CodeDirectory::HashAlgorithm> > digests(array);
+               std::copy(digests.begin(), digests.end(), std::inserter(state.mDigestAlgorithms, state.mDigestAlgorithms.begin()));
+       }
 
        if (CFNumberRef cmsSize = get<CFNumberRef>(CFSTR("cmssize")))
                state.mCMSSize = cfNumber<size_t>(cmsSize);
index c17c5801c4e9c3461faeb2665cfff856b370ffab..e9e41d288ca3acfd31e20902553d19f700122438 100644 (file)
@@ -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<SecIdentityRef> 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
index 2544d654212275a3f0e5245d0c9dea531de88e07..59587ce7d25aedf193557ba8e082dc128fc98e74 100644 (file)
@@ -209,6 +209,7 @@ OSStatus SecCodeCheckValidityWithErrors(SecCodeRef codeRef, SecCSFlags flags,
 
        checkFlags(flags,
                  kSecCSConsiderExpiration
+               | kSecCSStrictValidate
                | kSecCSEnforceRevocationChecks);
        SecPointer<SecCode> 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");
index 415506b4b3e36eeb36941a9b55c539cd644bf2ad..a5c7dd0e9ee5d0139e54305667b26c602306248f 100644 (file)
@@ -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);
index e9965556c7012a4f6ff91b66865461490c8a190b..bae22bd5c07430a3910afe690b61df9c5e7bb613 100644 (file)
@@ -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
 //
index 4dead60df822c11309eb1beb3b15e0969238b572..7b3704b2ff4388adecb42bf6585291b0960d0033 100644 (file)
@@ -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
 };
 
 
index 0d3ed8b1dbe301ad6592d02654d4c75283dc332a..18625c275fa8e71cf0b2cfb8989d1af8264bfd02 100644 (file)
@@ -120,6 +120,7 @@ OSStatus SecStaticCodeCheckValidityWithErrors(SecStaticCodeRef staticCodeRef, Se
                | kSecCSStrictValidate
                | kSecCSCheckGatekeeperArchitectures
                | kSecCSRestrictSymlinks
+               | kSecCSRestrictToAppLike
        );
 
        if (errors)
index a5e17ebb746eec23511fe15e2f1202afa146491c..c8f9d40e2cb1c18b7718705fcb47b6e9b9112dda 100644 (file)
@@ -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,
index 6bcfb5005208a7ca8ff1bf8dfb0eb62183b19c80..0b993cc7358cf874ddf443d289e4ef63c3917cb8 100644 (file)
@@ -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<CFDataRef> 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<const CodeDirectory *>(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<CFDataRef> cdData = diskRep()->component(slot);
+               if (!cdData)
+                       return false;
+               const CodeDirectory* cd = reinterpret_cast<const CodeDirectory*>(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<CFMutableArrayRef> cdList = makeCFMutableArray(0);
+               for (auto it = mCodeDirectories.begin(); it != mCodeDirectories.end(); ++it) {
+                       const CodeDirectory *cd = (const CodeDirectory *)CFDataGetBytePtr(it->second);
+                       if (CFRef<CFDataRef> 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<uint32_t> *)CFDataGetBytePtr(topDirectory);
+               const auto topDataEnd = topData + CFDataGetLength(topDirectory) / sizeof(*topData);
+               std::vector<uint32_t> signedVector(topData, topDataEnd);
+               
+               std::vector<uint32_t> 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<CFArrayRef> 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<CFDataRef> hashBag;
+       switch (OSStatus rc = CMSDecoderCopySignerAppleCodesigningHashAgility(cms, 0, &hashBag.aref())) {
+       case noErr:
+               if (hashBag) {
+                       CFRef<CFDictionaryRef> 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<CFMutableDictionaryRef> 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<CFDataRef> data = cfLoadFile(fullpath)) {
                                MakeHash<CodeDirectory> 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<CFURLRef> 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<CodeDirectory> 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<SecStaticCode> 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<CFMutableArrayRef> 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<CFArrayRef> 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<CFDateRef> date = CFDateCreate(NULL, time))
                                        CFDictionaryAddValue(dict, kSecCodeInfoTime, date);
                        if (CFAbsoluteTime time = this->signingTimestamp())
                                if (CFRef<CFDateRef> 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)
index c74ae3e7296774229c09772dcefa776daeabfea1..bb73341a91bab6da6f144d693f9381ed4950df20 100644 (file)
@@ -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<CodeDirectory::HashAlgorithm, CFCopyRef<CFDataRef> > 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<DiskRep> mRep;                       // on-disk representation
+       mutable CodeDirectoryMap mCodeDirectories; // available CodeDirectory blobs by digest type
+       mutable CFRef<CFDataRef> mBaseDir;      // the primary CodeDirectory blob (whether it's chosen or not)
        CFRef<CFDataRef> 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<CFDataRef> mDir;                          // code directory data
+       mutable CFRef<CFDataRef> mDir;          // code directory data
+       mutable CodeDirectory::HashAlgorithms mHashAlgorithms; // available hash algorithms
        CFRef<CFDataRef> mSignature;            // CMS signature data
        CFAbsoluteTime mSigningTime;            // (signed) signing time
        CFAbsoluteTime mSigningTimestamp;               // Timestamp time (from timestamping authority)
@@ -256,7 +266,8 @@ private:
        CFRef<CFDictionaryRef> mEntitlements; // derived from mCache slot
        CFRef<CFDictionaryRef> mResourceDict; // derived from mCache slot
        const Requirement *mDesignatedReq;      // cached designated req if we made one up
-       CFRef<CFDataRef> mCDHash;                       // hash of CodeDirectory
+       CFRef<CFDataRef> mCDHash;                       // hash of chosen CodeDirectory
+       CFRef<CFArrayRef> mCDHashes;            // hashes of all CodeDirectories (in digest type code order)
        
        bool mGotResourceBase;                          // asked mRep for resourceBasePath
        CFRef<CFURLRef> mResourceBase;          // URL form of resource base directory
index cf3a41d85eef9c8e993bbd11a712e7fe563c8ddd..571c33e12a592fef51d6823c81e065a78840ed9d 100644 (file)
@@ -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<CFURLRef> 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<OSStatus> 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)
index b1b4db4b7ffc75d0383464ead23cf23ddc322741..d0c5ee6568579488f5cc52d9284f950908ca6365 100644 (file)
@@ -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<CFURLRef> 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<DiskRep> mExecRep;                   // DiskRep for main executable file
        std::set<OSStatus> mStrictErrors;               // strict validation errors encountered
index 719a01b3364cdd72f1924266f7440195c8342119..c4e75a2e1e0656b6ef86c6b60404f1545131affe 100644 (file)
@@ -92,6 +92,7 @@ void CodeDirectory::Builder::specialSlot(SpecialSlot slot, CFDataRef data)
        MakeHash<Builder> 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 <rdar://problem/16102695>, 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<Builder> hasher(this);
                generateHash(hasher, mExec, (*mDir)[slot], thisPage);
                remaining -= thisPage;
        }
+       assert(remaining == 0);
        
        // all done. Pass ownership to caller
        return mDir;
index 21f92405df3ff9147b5519255e27ab5d1ede84a0..c4de2bec09a4b6ad0c3ff8e7db69e9c12ecb169a 100644 (file)
@@ -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<Slot> 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<Slot> 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
index 7697e273455dad7c583899f6f1112344a241de58..f675c4b82f38cdab5df6903a73c67cbba1be5572 100644 (file)
@@ -27,6 +27,7 @@
 #include "codedirectory.h"
 #include "csutilities.h"
 #include "CSCommonPriv.h"
+#include <vector>
 
 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<RefPointer<DynamicHash> > 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<CFMutableDictionaryRef> 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
index 9e074099b620d40d1401fc297a5e530289ff34c9..4b0bbbd98134853eb50b105f2da85726a9b73a2c 100644 (file)
@@ -47,6 +47,7 @@
 #include <security_utilities/cfutilities.h>
 #include <security_utilities/hashing.h>
 #include <Security/CSCommonPriv.h>
+#include <set>
 
 
 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<uint32_t> spare2;                // unused (must be zero)
        Endian<uint32_t> scatterOffset; // offset of optional scatter vector (zero if absent)
        Endian<uint32_t> teamIDOffset;  // offset of optional teamID string
+       Endian<uint32_t> spare3;                // unused (most be zero)
+       Endian<uint64_t> 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<HashAlgorithm> 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<const char>(identOffset); }
        char *identifier() { return at<char>(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
        
index 1de1450554ccd79f060c17823d7470d215803468..0cc63cb4e5711448bce305e947ab56ea18297773 100644 (file)
@@ -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 <class _Hash>
-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 <class _Hash>
+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 <class _Hash>
 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 (file)
index 0000000..7bc89b4
--- /dev/null
@@ -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 <security_utilities/endian.h>
+#include <algorithm>
+
+
+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 (file)
index 0000000..96a63a2
--- /dev/null
@@ -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 <DiskImages/DiskImages.h>
+#undef check   // sadness is having to live with C #defines of this kind...
+#include <security_utilities/unix++.h>
+
+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
index af0a336b2a1c436940b0a6a4045b42aed7b7f976..0501e3774faa63c87ef1fa5ad75c1799dc0cf7fa 100644 (file)
@@ -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()
index b92195218a01c6aec7af58194f004839883a7573..21d2d5a88eb3bd57ad9ad093c17a9506fa68803a 100644 (file)
@@ -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:
index d362b5ab9d82dbf4c8b07c77d0007cddda80ddae..de4b43a4a099d02b68cf2c2e0c3a4797544c226c 100644 (file)
@@ -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> macho(mExecutable->architecture());
-               if (cd->codeLimit != macho->signingExtent())
+               if (cd->signingLimit() != macho->signingExtent())
                        MacOSError::throwMe(errSecCSSignatureInvalid);
        }
 }
index 07bba9e42f9bcb76e3cdb5e8effe313317ec046c..214efb6a876616129efce018d26e11250b263295 100644 (file)
@@ -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
        
index 7fbde5fcc3f10670f247b4894d69c189bb3dd704..483ca40ceaef65e321dc9f58fc10f8051008f5cc 100644 (file)
@@ -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<CFDataRef> 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<CFDataRef> 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<CFDataRef> signature = CFDataCreateMutable(NULL, 0);
-       CFTemp<CFDictionaryRef> arguments("{%O=%O, %O=#N, %O=%O}",
+       CFTemp<CFDictionaryRef> arguments("{%O=%O, %O=#N, %O=%d, %O=%O}",
                kSecCodeSignerDetached, signature.get(),
                kSecCodeSignerIdentity, /* kCFNull, */
+               kSecCodeSignerDigestAlgorithm, kSecCodeSignatureHashSHA1,
                kSecCodeSignerResourceRules, rules.get());
        CFRef<SecCodeSignerRef> signer;
        SecCSFlags creationFlags = kSecCSSignOpaque | kSecCSSignNoV1 | kSecCSSignBundleRoot;
index b26c7e6c0926f3168602350edeae901225b95a1c..65dded83b300548e647b19e597d52a9f82e37fc5 100644 (file)
@@ -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
 };
 
 
index 0823943999175532cd394da0253c82435678fe06..cba2bdc40d7c9f1d43a5ae2a4b6b43eb069f5af5 100644 (file)
@@ -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<CFDataRef> 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<CFDataRef> 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<CFDataRef> signature = CFDataCreateMutable(NULL, 0);
-               CFTemp<CFDictionaryRef> arguments("{%O=%O, %O=#N}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity);
+               CFTemp<CFMutableDictionaryRef> arguments("{%O=%O, %O=#N, %O=%d}", kSecCodeSignerDetached, signature.get(), kSecCodeSignerIdentity,
+                       kSecCodeSignerDigestAlgorithm, (matchFlags & kAuthorityFlagWhitelistSHA256) ? kSecCodeSignatureHashSHA256 : kSecCodeSignatureHashSHA1);
                CFRef<SecCodeSignerRef> 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<CFNumberRef>(kSecAssessmentUpdateKeyPriority))
                CFNumberGetValue(pri, kCFNumberDoubleType, &priority);
@@ -1036,7 +1051,7 @@ void PolicyEngine::normalizeTarget(CFRef<CFTypeRef> &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<CFDictionaryRef> info;
                                MacOSError::check(SecCodeCopySigningInformation(code, kSecCSInternalInformation, &info.aref()));
index effd233ee54c8f82e4fa0d8dd44caadd923fad4c..3837d426da139d5fad24fad17f7f2e80e0939e18 100644 (file)
@@ -30,6 +30,9 @@
 #include <Security/SecCertificatePriv.h>
 #include <security_utilities/memutils.h>
 #include <security_utilities/logging.h>
+#include <sys/csr.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFUnserialize.h>
 #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<CFMutableArrayRef> keys = makeCFMutableArray(0);
+
+    try {
+        io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
+        if (entry == IO_OBJECT_NULL)
+            return NULL;
+
+        CFRef<CFDataRef> configData = (CFDataRef)IORegistryEntryCreateCFProperty(entry, kAMFINVRAMTrustedKeys, kCFAllocatorDefault, 0);
+        IOObjectRelease(entry);
+        if (!configData)
+            return NULL;
+
+        CFRef<CFDictionaryRef> 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<CFDataRef> 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;
 }
 
index a221f96d5e0d047acba25aa4f60872cfedf6021c..fd0188d356fc4a997f9428068b20da2148201cbe 100644 (file)
@@ -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;
 };
 
index 5695800eabce99099c96aecb947cc1d414247952..490b1e07bb378d6dc4ca690dc3752b68d46078c7 100644 (file)
@@ -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<ResourceBuilder> hasher(this);
+       RefPointer<DynamicHash> 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<CFMutableDictionaryRef> 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<CFDictionaryRef>("{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));
 }
 
 
index 4bdcc7e61f25cfe52738fcb3710560cc46e447cc..8d68314b2fdefde0a2d051a4abb5f8396c9e6243 100644 (file)
@@ -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<CFDictionaryRef> mRawRules;
        typedef std::vector<Rule *> 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<CFDictionaryRef> mDict;
        CFStringRef mRequirement;
        CFStringRef mLink;
        uint32_t mFlags;
index 7a907d31ece1de6c8e1cb0015add5508d71b464a..160559fad34364459f318201f4e73b7731c74f9f 100644 (file)
@@ -97,6 +97,7 @@ _kSecCodeInfoEntitlementsDict
 _kSecCodeInfoFlags
 _kSecCodeInfoFormat
 _kSecCodeInfoDigestAlgorithm
+_kSecCodeInfoDigestAlgorithms
 _kSecCodeInfoIdentifier
 _kSecCodeInfoImplicitDesignatedRequirement
 _kSecCodeInfoMainExecutable
@@ -107,6 +108,7 @@ _kSecCodeInfoSource
 _kSecCodeInfoStatus
 _kSecCodeInfoTrust
 _kSecCodeInfoUnique
+_kSecCodeInfoCdHashes
 _kSecCodeInfoCodeDirectory
 _kSecCodeInfoCodeOffset
 _kSecCodeInfoResourceDirectory
index daa2dac7b30357987d9221680acbdd972ef1357c..387f68b5535f1968b9b158527f4ef912863e1ae1 100644 (file)
@@ -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<CFDictionaryRef> resourceRules;
        if (!rpath.empty()) {
                // explicitly given resource rules always win
-               CFCopyRef<CFDictionaryRef> 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<size_t>(state.mPageSize) : rep->pageSize(state);
-    
-    // Timestamping setup
-    CFRef<SecIdentityRef> mTSAuth;     // identity for client-side authentication to the Timestamp server
+       pagesize = state.mPageSize ? cfNumber<size_t>(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<CFDictionaryRef> rules2 = cfget<CFDictionaryRef>(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<CFMutableDictionaryRef> 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<CFMutableDictionaryRef>("{symlink=%s}", target));
                                } else {
-                                       seal.take(cfmake<CFMutableDictionaryRef>("{hash=%O}",
-                                               CFRef<CFDataRef>(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<CFMutableDictionaryRef> 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<SecStaticCode> 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<CFMutableDictionaryRef>("{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<ArchEditor> editor(state.mDetached
                ? static_cast<ArchEditor *>(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<size_t> 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<CFDataRef> 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<CFArrayRef> hashes = cdSet.hashBag();
+               CFTemp<CFDictionaryRef> hashDict("{cdhashes=%O}", hashes.get());
+               CFRef<CFDataRef> hashBag = makeCFData(hashDict.get());
+               CFRef<CFDataRef> 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<DiskRep::Writer> 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<CFDataRef> identification = rep->identification();
                writer->component(cdIdentificationSlot, identification);
-       }       
-       
-       CodeDirectory *cd = builder.build();
-       CFRef<CFDataRef> 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<CFArrayRef> hashes = cdSet.hashBag();
+       CFTemp<CFDictionaryRef> hashDict("{cdhashes=%O}", hashes.get());
+       CFRef<CFDataRef> hashBag = makeCFData(hashDict.get());
+       CFRef<CFDataRef> 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<CFDataRef> 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<Endian<uint32_t> > slotVector;
+               slotVector.push_back(cdCodeDirectorySlot);      // mandatory
+               std::set<CodeDirectory::Slot> 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 <security_smime/tsaSupport.h>
 
 //
 // 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<CFMutableDictionaryRef> 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<CFErrorRef> 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;
+}
 
 
 //
index 3902d5bb71518efab48e9bb84dbb47a7afef8160..fafa3fe351b0606f01c8d666a629f2f94aa6ab39 100644 (file)
@@ -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<Endian<uint32_t> > 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<DiskRep> rep;                // DiskRep of Code being signed
        CFRef<CFDictionaryRef> resourceDirectory;       // resource directory
        CFRef<CFDataRef> resourceDictData; // XML form of resourceDirectory
+       CodeDirectory::HashAlgorithms hashAlgorithms; // hash algorithm(s) to use
        std::string identifier;                 // signing identifier
        std::string teamID;             // team identifier
        CFRef<CFDataRef> entitlements;  // entitlements
index eb19d2d3e2ea037017433b6a2ed4755c412fba2b..25a327bade515d5df04ac1ab43767b1f88c1d93a 100644 (file)
@@ -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<CodeDirectory*>(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<CFMutableArrayRef> hashList = makeCFMutableArray(0);
+       for (auto it = begin(); it != end(); ++it) {
+               CFRef<CFDataRef> cdhash = it->second->cdhash();
+               CFArrayAppendValue(hashList, cdhash);
+       }
+       return hashList.yield();
+}
 
 
 } // end namespace CodeSigning
index 906be1ea415224bcfb23350424516b620f22ed97..88cb2055fee373c2b6d4c2c58bf2937246870ff7 100644 (file)
@@ -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<MachO> source;                 // Mach-O object to be signed
-               CodeDirectory::Builder cdbuilder; // builder for CodeDirectory
+               std::map<CodeDirectory::HashAlgorithm, RefPointer<CodeDirectory::Builder> > 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<DiskRep::Writer> 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<CFArrayRef> mCerts;               // hold cert chain
 };
+       
+       
+//
+// A collector of CodeDirectories for hash-agile construction of signatures.
+//
+class CodeDirectorySet : public std::map<CodeDirectory::HashAlgorithm, const CodeDirectory *> {
+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
index 5b01b1381f777e051ba5c01e2dadb970f9c63516..84c5a78149243782ef6e53497ce3a67b66b6176a 100644 (file)
@@ -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);
 }
 
index 1992dc163a20090eb095361827aa9ae11e418aa4..cc15854c6a4796ceba6f526898665425a08b5bb8 100644 (file)
@@ -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;
index 2da4e67fd3aa4b9feb9fc0bdaa51fa4445ebb0a3..6e4152988fa3bd7107de9a60d651e8cd34c74609 100644 (file)
@@ -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<SecStaticCodeRef> code;
+               MacOSError::check(SecStaticCodeCreateWithPath(path, kSecCSDefaultFlags, &code.aref()));
+               CFRef<CFURLRef> 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<int64_t>(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<CFDataRef> data;
                        MacOSError::check(SecRequirementCopyData(SecRequirementRef(target), kSecCSDefaultFlags, &data.aref()));
                        xpc_dictionary_set_data(msg, "requirement", CFDataGetBytePtr(data), CFDataGetLength(data));
index deba680eb727f641a47f8894e89b35e44aa41e4f..edb3cacb9bad9c402e92fc806d49dd6a24e52174 100644 (file)
                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 */; };
                C2CC310E0B852424005FA59D /* SecIntegrityLib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SecIntegrityLib.c; sourceTree = "<group>"; };
                C2CC31130B85254F005FA59D /* antlrplugin.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = antlrplugin.cpp; path = lib/antlrplugin.cpp; sourceTree = "<group>"; };
                C2CC31140B85254F005FA59D /* antlrplugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = antlrplugin.h; path = lib/antlrplugin.h; sourceTree = "<group>"; };
+               C2D296781BCF16C000B0A29B /* diskimagerep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = diskimagerep.cpp; sourceTree = "<group>"; };
+               C2D296791BCF16C000B0A29B /* diskimagerep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = diskimagerep.h; sourceTree = "<group>"; };
                C2D383120A237F47005C63A2 /* bundlediskrep.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bundlediskrep.cpp; sourceTree = "<group>"; };
                C2D383130A237F47005C63A2 /* bundlediskrep.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bundlediskrep.h; sourceTree = "<group>"; };
                C2D383140A237F47005C63A2 /* cdbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cdbuilder.cpp; sourceTree = "<group>"; };
                                C2BD519A0A9392FD000FE43D /* machorep.cpp */,
                                C2A436140F2133B2007A41A6 /* slcrep.h */,
                                C2A436130F2133B2007A41A6 /* slcrep.cpp */,
+                               C2D296791BCF16C000B0A29B /* diskimagerep.h */,
+                               C2D296781BCF16C000B0A29B /* diskimagerep.cpp */,
                                C2C3BCD20BA1E47E00E869D1 /* singlediskrep.h */,
                                C2C3BCD10BA1E47E00E869D1 /* singlediskrep.cpp */,
                                C28342EC0E36719D00E54360 /* detachedrep.h */,
                                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 */,
                                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 */,
                                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 = (
                                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 = (
index 8539c227381944309e4a5294b9272f43becb4408..23f383ad44be6472dc5528c001124eaa0b8b2727 100644 (file)
@@ -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);
index f5dc442e01472d623e48753f73fce8282fa7af2c..e3c013a295d256d8ba9bd438994e5feb25c93c3e 100644 (file)
@@ -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 */
index ddad1a74be58123b1ddc4c39d0088a6271b0345e..aa307033e3c546b14cdbb68ea92ae142389bcd46 100644 (file)
@@ -34,6 +34,7 @@
 #include <fcntl.h>
 #include <Security/cssmapplePriv.h>
 #include <syslog.h>
+#include <copyfile.h>
 
 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);
+    }
+}
+
index c0e9dbd7c621234a12754706a9f65a22368219a3..c5f429d92adadd759f9a0230255be7eed9192810 100644 (file)
@@ -441,8 +441,8 @@ public:
 
        bool hasTable(Table::Id inTableid);
 
-protected:
     void modifyDatabase();
+protected:
     const RefPointer<const DbVersion> 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;
index 9b655a693761d4502aa76397e9ab7b7c615e792b..6dfd8f28e97d4335240e34ac029ede37846edb7d 100644 (file)
@@ -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<DevRandomGenerator>().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<Mutex>_(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<Mutex>_(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
        }
index 5ad2a2df83611ea91c03eeba74b950c55ba4d99b..ceacab9b3ed9a796e1d89a3d3af80388857a2128 100644 (file)
@@ -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;
index d510cd9833cf621d73b515a5681982779541b588..2aa23a18ef93e6544b0b20f616ac6c7403f77861 100644 (file)
@@ -49,11 +49,11 @@ const CSSM_ACL_HANDLE Access::ownerHandle;
 //
 Access::Access() : mMutex(Mutex::recursive)
 {
-       SecPointer<ACL> owner = new ACL(*this);
+       SecPointer<ACL> owner = new ACL();
        owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL);
        addOwner(owner);
        
-       SecPointer<ACL> any = new ACL(*this);
+       SecPointer<ACL> any = new ACL();
        add(any);
 }
 
@@ -87,12 +87,12 @@ void Access::makeStandard(const string &descriptor, const ACL::ApplicationList &
        StLock<Mutex>_(mMutex);
 
        // owner "entry"
-       SecPointer<ACL> owner = new ACL(*this, descriptor, ACL::defaultSelector);
+       SecPointer<ACL> owner = new ACL(descriptor, ACL::defaultSelector);
        owner->setAuthorization(CSSM_ACL_AUTHORIZATION_CHANGE_ACL);
        addOwner(owner);
 
        // unlimited entry
-       SecPointer<ACL> unlimited = new ACL(*this, descriptor, ACL::defaultSelector);
+       SecPointer<ACL> 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<ACL> limited = new ACL(*this, descriptor, ACL::defaultSelector);
+       SecPointer<ACL> 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> &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<Mutex>_(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<Mutex>_(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);
        }
 }
 
index ec562dd8c8fd3d0c1cf4e1e1586d5f3adee2bbd5..e3d22db1c8787a7ac5434176febddea80b544ad0 100644 (file)
@@ -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 <class Container>
        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 <class Container>
+    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;
index 66741f9fb78a6634013afc6a57d8a42435661640..877dc9d08a74573aeb1ff48888c11f9ec46adb48 100644 (file)
@@ -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.
index 1b625a497f47e65f9bf40a57c337c69b395c5707..0b7cc0b2691c5ed417c3353c683f32d4417370d9 100644 (file)
@@ -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<Mutex>_(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()
 {
index 867cd48037b91a3d054820ce64e3b01601dbe1b3..cc74c6193d76eb357f99eb6bf35d324514e9ba16 100644 (file)
@@ -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;
 };
 
index f8d1e70e9e67d511270daa5889ac16e6997203af..6c299b926c2fe31c6b9b2275b75bf470785b7c07 100644 (file)
@@ -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() 
index 4b192b0db98831772f4b1385e4ca96805540b809..5147ea55ec86e6ca6f49e2437476a90be149b0be 100644 (file)
@@ -56,10 +56,13 @@ public:
        // Public globals
        StorageManager storageManager;
 
+    bool integrityProtection() { return mIntegrityProtection; }
+
 private:
 
        // Other "globals"
        bool mUI;
+    bool mIntegrityProtection;
        CssmClient::AclFactory mACLFactory;
 };
 
index 057f0618084e8692be08ebba4cb472024c072206..025c8b3ae419ece620c2f5d743457dec08082281 100644 (file)
 #include <Security/SecKeychainItemPriv.h>
 #include <Security/cssmapple.h>
 #include <CommonCrypto/CommonDigest.h>
+#include <utilities/der_plist.h>
+
+#include <security_utilities/CSPDLTransaction.h>
+#include <SecBasePriv.h>
 
 #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> 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<CFMutableDictionaryRef> 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<CFDataRef> label = NULL;
+
+        switch(actualInfo.nameFormat()) {
+            case CSSM_DB_ATTRIBUTE_NAME_AS_STRING: {
+                const char* stringname = actualInfo.stringName();
+                label.take(CFDataCreate(NULL, reinterpret_cast<const UInt8*>(stringname), strlen(stringname)));
+                break;
+            }
+            case CSSM_DB_ATTRIBUTE_NAME_AS_OID: {
+                const CssmOid& oidname = actualInfo.oidName();
+                label.take(CFDataCreate(NULL, reinterpret_cast<const UInt8*>(oidname.data()), oidname.length()));
+                break;
+            }
+            case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: {
+                uint32 iname = actualInfo.intName();
+                label.take(CFDataCreate(NULL, reinterpret_cast<const UInt8*>(&(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<CFMutableArrayRef> attributeDataContainer;
+        attributeDataContainer.take(CFArrayCreateMutable(NULL, data.size(), &kCFTypeArrayCallBacks));
+
+        for(int j = 0; j < data.size(); j++) {
+            CssmData& entry = data.values()[j];
+
+            CFRef<CFDataRef> 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<const UInt8*>(data.values()[j].data()), data.values()[j].length()));
+                    break;
+
+                case CSSM_DB_ATTRIBUTE_FORMAT_UINT32: {
+                    uint32 x = entry.length() == 1 ? *reinterpret_cast<uint8 *>(entry.Data) :
+                               entry.length() == 2 ? *reinterpret_cast<uint16 *>(entry.Data) :
+                               entry.length() == 4 ? *reinterpret_cast<uint32 *>(entry.Data) : 0;
+                    datadata.take(CFDataCreate(NULL, reinterpret_cast<const UInt8*>(&x), sizeof(x)));
+                    break;
+                }
+
+                case CSSM_DB_ATTRIBUTE_FORMAT_SINT32: {
+                    sint32 x = entry.length() == 1 ? *reinterpret_cast<sint8 *>(entry.Data) :
+                               entry.length() == 2 ? *reinterpret_cast<sint16 *>(entry.Data) :
+                               entry.length() == 4 ? *reinterpret_cast<sint32 *>(entry.Data) : 0;
+                    datadata.take(CFDataCreate(NULL, reinterpret_cast<const UInt8*>(&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<CFDataRef> 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> 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<CC_LONG>(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<ACL *> 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> 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> 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> 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<SSDbImpl *>(&(*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> 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<SecPointer<ACL> > 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<void **>(&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<void **>(&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<const void *>(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<const void *>(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<SSDbUniqueRecordImpl *>(&(*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> 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<SSDbUniqueRecordImpl *>(&(*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<SSDbImpl *>(&(*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<SecPointer<ACL> > 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<CssmClient::DbAttributes> 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<Mutex> _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_ptr<DbAttributes>dbDupAttributes (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<SSDbUniqueRecordImpl &>(*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)
 {
index ff1e205aeee88791c66c3ef7e867db3953df34fe..26d7d7f24780bd59518a39f0a5d06c2524f9006f 100644 (file)
@@ -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> 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<CssmDataContainer> mData;
        auto_ptr<CssmClient::DbAttributes> mDbAttributes;
index fc968cfc0d4e8594cfc465e65670f2a969a942cc..1c0cdb9d15766bb45b9794402254dfa142252fd4 100644 (file)
@@ -36,6 +36,7 @@
 #include "StorageManager.h"
 #include <Security/SecKeychainItemPriv.h>
 #include <SecBase.h>
+#include <Security/SecBasePriv.h>
 
 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<Mutex> 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<Mutex> _(gActivationMutex()); // force serialization of cursor creation
-                Keychain &kc = *mCurrent;
-                Mutex* mutex = kc->getKeychainMutex();
-                StLock<Mutex> _(*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> _(*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<Mutex> _(gActivationMutex()); // force serialization of cursor creation
+                    Keychain &kc = *mCurrent;
+                    Mutex* mutex = kc->getKeychainMutex();
+                    StLock<Mutex> _(*mutex);
+                    (*mCurrent)->database()->activate();
+                    mDbCursor = DbCursor((*mCurrent)->database(), *this);
+                }
+                catch(const CommonError &err)
+                {
+                    ++mCurrent;
+                }
+            }
+
+            Keychain &kc = *mCurrent;
+            Mutex* mutex = kc->getKeychainMutex();
+            StLock<Mutex> _(*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<Mutex> _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);
+    }
+}
index a05db8e7b2f97429133ef78bc2e2037fbcc15665..c65bf0606478a8ee87c39039a3c8c598a402a5f9 100644 (file)
@@ -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);
 };
 
 
index 69e7f91951f9c2e26bcf5620812a36af8eea155a..0fe303bac09357acf728409b2accdfd7c44cbad4 100644 (file)
 #include <security_cdsa_client/genkey.h>
 #include <security_cdsa_client/signclient.h>
 #include <security_cdsa_client/cryptoclient.h>
+#include <security_utilities/CSPDLTransaction.h>
 
 #include <security_keychain/Globals.h>
 #include "KCEventNotifier.h"
 #include <CommonCrypto/CommonDigest.h>
 #include <SecBase.h>
+#include <SecBasePriv.h>
 
 // @@@ 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<KeyItem> 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<KeyItem*>(keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId).get());
+        privateKeyItem = dynamic_cast<KeyItem*>(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<Access> 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<KeyItem*>(&(*publicKeyItem));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-
-               outPublicKey = impl;
-
-               impl = dynamic_cast<KeyItem*>(&(*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<KeyItem> 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<KeyItem*>(keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId).get());
+        privateKeyItem = dynamic_cast<KeyItem*>(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<Access> 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<KeyItem*>(&(*publicKeyItem));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-
-               outPublicKey = impl;
-
-               impl = dynamic_cast<KeyItem*>(&(*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> 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<KeyItem *>(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;
+    }
+}
index 9ac071d1cfbc9ac3f4220c087a417ad9c0f5046b..56776933cdf166ce08277c404cf41a89fee6bb11 100644 (file)
@@ -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:
index 1d94dee2325d43c88b63e8473256ceada1bcf461..de34f0b4fb106e27ac8bcf7f981b19b964f2487b 100644 (file)
@@ -38,6 +38,8 @@
 #include <security_cdsa_utilities/cssmdb.h>
 #include <security_utilities/trackingallocator.h>
 #include <security_keychain/SecCFTypes.h>
+#include <securityd_client/ssblob.h>
+#include <Security/TrustSettingsSchema.h>
 
 #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<Mutex> _(mDbItemMapMutex);
        pair<DbItemMap::iterator, bool> 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<Mutex> _(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<Mutex> _(mDbItemMapMutex);
+            StLock<Mutex> __(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<Mutex>_(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<Mutex>_(mMutex);
+       StLock<Mutex> _(mMutex);
        
        const CssmAutoDbRecordAttributeInfo &infos =
                primaryKeyInfosFor(primaryKeyAttrs.recordType());
@@ -960,23 +1007,28 @@ void KeychainImpl::gatherPrimaryKeyAttributes(DbAttributes& primaryKeyAttrs)
 ItemImpl *
 KeychainImpl::_lookupItem(const PrimaryKey &primaryKey)
 {
+    StLock<Mutex> _(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<Mutex>_(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<Mutex> __(mDbItemMapMutex);
        pair<DbItemMap::iterator, bool> 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<Mutex> _(mDbItemMapMutex);
+        DbItemMap::iterator it = mDbItemMap.find(primaryKey);
+        if (it != mDbItemMap.end() && (ItemImpl*) it->second == inItemImpl) {
+            mDbItemMap.erase(it);
+        }
+    } // drop mDbItemMapMutex
+
+    {
+        StLock<Mutex> _(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<Mutex> _(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<Mutex> _(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<Mutex>_(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;
+}
+
index 7931313e3a9ad4215f1c0b86d6f4214e357d60eb..334cd682eac606e677d84b7ad279cf9083b8cbdb 100644 (file)
@@ -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<Mutex>_(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<PrimaryKey, __weak ItemImpl *> DbItemMap;
-       // Weak reference map of all items we know about that have a primaryKey
+    typedef map<PrimaryKey, ItemImpl *> 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<KeychainImpl>(new KeychainImpl(db)) {}
 
index 335c6cf9c8453eb3b7cb73350fa5b5feeddc4f94..fabae2419c8e9a9570ea7bf12840662edfa0a53e 100644 (file)
@@ -64,7 +64,7 @@ OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef,
 {
        BEGIN_SECAPI
        SecPointer<Access> access = Access::required(accessRef);
-       SecPointer<ACL> acl = new ACL(*access, cfString(description), *promptSelector);
+       SecPointer<ACL> 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 = 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;
index 9491f85c7f9d05a9a793e8a209af46a78c9c8e40..39a8b120a091a8210f33d96a56c8683ba21fb8da 100644 (file)
@@ -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
index 9464790fc9aafa4d7a2993fb7e7ce62a8283e811..f355ab94830faaa63f0b75559b959ae6801677d9 100644 (file)
@@ -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
index 9950aa330f23290aa4815945d2eaf27b31af1564..8c908f6465f000adcbeb40029e726b4f0eb00169 100644 (file)
@@ -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
index 429fbc2ac3956285232ee82e1b9d22e6c101b4c4..1827773dd926c5dcb499b96445b7d8b480c83893 100644 (file)
@@ -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);
 
index 5c143ab74fb16702777d33921bfc47cc18478db9..64bdd381d82864bf0bc110b9c6d0e6a25b37792e 100644 (file)
 
 #include <utilities/debugging.h>
 
-/* 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;
index 71a4b3158a520697da754c1f1a89d57eea14b737..1f89f4cef3d9b486b5ca8761b479395721dc8f1c 100644 (file)
@@ -41,6 +41,7 @@
 #include <security_cdsa_client/securestorage.h>
 #include <security_cdsa_client/dlclient.h>
 #include <Security/cssmapi.h>
+#include <security_keychain/KeyItem.h>
 
 /*
  * 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
index 2467ebb173328ae7ae00ec4410ca59fcdbbd1945..173eb892576f4483ac6b399a4b636822bd072307 100644 (file)
@@ -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);
        }
index 06dc4b415d370c5d1e50f2179d77f587ec3b2682..994a1fea1ddce84c65beeb3c07ab3b0f537b81a4 100644 (file)
@@ -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");
index f46a1646933c74d4f8dd405bf994d4d8c81be9e5..58ecbbe6a7f72ef1beddd79da43c882a6c036522 100644 (file)
@@ -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_ */
index 8a48d3f2a5ae87728ee7878e43b468810ad01afd..9580a994b3db8984f101fdd91e12564dad80a1a8 100644 (file)
@@ -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
index 30bb1d3e6890b889095b4ffef2dc09296df9564c..e606a1918b5d97ce032e20249c01c8fd9a1edc23 100644 (file)
@@ -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<CFTypeRef>(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.
index c7eb963d5c574fd0f2bae76b6a03c96440da361b..f3ed51e7b09e64295debd1b1276642fac19713f7 100644 (file)
@@ -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
index d4528aca98d0d9b99fb16fd8959072401c0adaf3..e9650f9695bd8d1cdd4e2c0cd274908baefe12ec 100644 (file)
@@ -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.
index 269db0b1f4d206ae60119f7b8a2d0e5b8b49a014..95fc6f36fdcf761c47071d1199c08e7bb055ec59 100644 (file)
@@ -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
index 0612aa33cfaa82078b48e172614d11b149e0c5c2..6243ab9e2f0200a4df2affada6dd8f09b34fb37d 100644 (file)
@@ -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)
index f5d16aedf35388a431617e6752f32972913ca905..551769159eb9aaf32d9db464308624b7172002e5 100644 (file)
@@ -52,6 +52,7 @@
 #include <security_keychain/SecCFTypes.h>
 #include "TrustSettingsSchema.h"
 #include <security_cdsa_client/wrapkey.h>
+#include <securityd_client/ssblob.h>
 
 //%%% 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<Mutex>_(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<Mutex>__(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<Mutex>_(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)
index edd02841af76e95140c66987cef0d6cc5b1424f8..b1f82cf40092fcdb64414bb460118defbcfee174 100644 (file)
@@ -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<DLDbIdentifier, __weak KeychainImpl *> KeychainMap;
-       // Weak reference map of all keychains we know about that aren't deleted
+    typedef map<DLDbIdentifier, KeychainImpl *> KeychainMap;
+       // Reference map of all keychains we know about that aren't deleted
        // or removed
     KeychainMap mKeychains;
 
index c1514284fdb7ed9754d9141ddb5c378fbf3c5e49..45a28a494e78459cd2e6c87f3f64ff9460352815 100644 (file)
@@ -35,6 +35,7 @@
 #include "TrustAdditions.h"
 #include "TrustKeychains.h"
 #include <security_cdsa_client/dlclient.h>
+#include <security_keychain/Keychains.h>
 
 
 using namespace Security;
@@ -65,29 +66,6 @@ ModuleNexus<TrustStore> 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<TPEvidenceInfo>();
        }
index 1df98146ef98ca22ab1274b44ead7a7d7aed2ef4..3ebdf780c0e7666dac4d11c37e69aa91c52adfe1 100644 (file)
@@ -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
index 8b6b926941d0af857bf616f1aead597416dd771d..8672c7900d981632af43d6f74720e4f044779dca 100644 (file)
@@ -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
index a9f1f2c9e6f1d1c617ecb88a20d35b295da71bb7..f14c162a343970f8863cd351404fb1ebf7839319 100644 (file)
                        baseConfigurationReference = 1828EAA114E334E200BE00C2 /* debug.xcconfig */;
                        buildSettings = {
                                COMBINE_HIDPI_IMAGES = YES;
+                               SDKROOT = macosx.internal;
                        };
                        name = Debug;
                };
                        baseConfigurationReference = 1828EAA314E334E200BE00C2 /* release.xcconfig */;
                        buildSettings = {
                                COMBINE_HIDPI_IMAGES = YES;
+                               SDKROOT = macosx.internal;
                        };
                        name = Release;
                };
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                RUN_CLANG_STATIC_ANALYZER = YES;
+                               SDKROOT = macosx.internal;
                        };
                        name = Debug;
                };
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                RUN_CLANG_STATIC_ANALYZER = YES;
+                               SDKROOT = macosx.internal;
                        };
                        name = Release;
                };
index d6f28263cce223539c978b7b447ae571bf3d4393..2a65d35cdb6d2fc1aa78bb5303eff671676199f7 100644 (file)
 /* 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)};
 
 
 
index 8834d9ca8cfa2bf53b5a85ad4dc7cfd4fb4e4007..302459d5328eb4780b0064bcdd49306408deb6e2 100644 (file)
@@ -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);
index 72226efb76dd0ff2b44b92376c5991b9c9a5d7b8..57e98c0b951b17bdf262f1c78729b9b56331cfab 100644 (file)
                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 */
 
                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 = "<group>"; };
                D6E1457C0A632A5A008AA7E8 /* KCEventNotifier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = KCEventNotifier.h; sourceTree = "<group>"; };
+               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 = "<group>"; };
+               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 = "<group>"; };
+               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 = "<group>"; };
+               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 = "<group>"; };
+               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 = "<group>"; };
                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 = "<group>"; };
 /* End PBXFileReference section */
 
                        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 */,
                        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 */,
                        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 (file)
index 0000000..e5e89a0
--- /dev/null
@@ -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 <Security/Security.h>
+#include <Security/cssmapi.h>
+#include <security_utilities/debugging.h>
+#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 (file)
index 0000000..e2f523c
--- /dev/null
@@ -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 <rdar://problem/23515265> 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 (file)
index 0000000..d9593f1
--- /dev/null
@@ -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 <rdar://problem/8431281> 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 <rdar://problem/8431281> 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 (file)
index 0000000..e76f69a
--- /dev/null
@@ -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 (file)
index 0000000..469aab6
--- /dev/null
@@ -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 <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <Security/SecBase.h>
+#include <Security/SecBasePriv.h>
+#include <Security/SecKeychainPriv.h>
+#include <TargetConditionals.h>
+#include <Security/cssmapi.h>
+#include <stdlib.h>
+
+#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;
+}
index 2996b5c889508d520d5edc31a90103fd4ea4d466..77f288fbbdcd36586582cdf60847a8cf10f49526 100644 (file)
 #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]={
index e670b866bf3d4d0d17b0ed4af550ca1c307dae0c..89ab2b025e25741fac72fcdd54e0ce60c5a909c0 100644 (file)
@@ -4,9 +4,10 @@
  */
 #include <test/testmore.h>
 
-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)
index 2c8abdcc0edd50ff989946389ae943e084e5e770..9ce1aedc6347e247ab81451ae9915654bc43d916 100644 (file)
@@ -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;
 }
 
 
index c3c036909119016bd627ca1a4dcc088c0943310c..cebe62ffa7e8a2991756d349a32c91e7b7563a4b 100644 (file)
@@ -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;
index ebacbf12d8f4aa5bc057fe16deb7127e564c26fc..7c94cabb0c4e15d11e7cb922777c0457d89bcf3f 100644 (file)
@@ -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.
index f7c7cc8151f9dd26332cb19ebbf6a15b0fcbf53c..39c72172e34369059f63f07d3192f8d5fe738fe2 100644 (file)
@@ -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;
index e5d8b6cfe884841fe3ee1a66f7ed72d8a91d9465..6e85d7b52319f658a70872380ede7f41f1566059 100644 (file)
@@ -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);
index d375f82dc3e79d6be622e79e28e3d952ebaa2b36..c211139556e728d6132681c385e6e29a22f616bc 100644 (file)
@@ -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
index f2d10f49262bf2d899b15c734d08fae88c5e45ce..012ff4962baee39690cd688c14af16d5e2cac12f 100644 (file)
@@ -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* */
index ac33842a3e78f0e388c69c77c69b2bc4edd74cb3..d5bdd5cc4c243badc89478e32d19f22b287c612e 100644 (file)
 #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
 /* 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),
+
 };
 
 /*
index bfbea85a667693f65ae0ed1ed26dc99ae82cee52..ff2d9897aa3e33e14df242e0599025787f25dd62 100644 (file)
@@ -114,6 +114,7 @@ _SecCmsSignerInfoAddMSSMIMEEncKeyPrefs
 _SecCmsSignerInfoAddSMIMECaps
 _SecCmsSignerInfoAddSMIMEEncKeyPrefs
 _SecCmsSignerInfoAddSigningTime
+_SecCmsSignerInfoAddAppleCodesigningHashAgility
 _SecCmsSignerInfoCreate
 _SecCmsSignerInfoCreateWithSubjKeyID
 _SecCmsSignerInfoDestroy
@@ -125,6 +126,7 @@ _SecCmsSignerInfoGetSignerEmailAddress
 _SecCmsSignerInfoGetSigningCertificate
 _SecCmsSignerInfoGetSigningTime
 _SecCmsSignerInfoGetTimestampTime
+_SecCmsSignerInfoGetAppleCodesigningHashAgility
 _SecCmsSignerInfoGetVerificationStatus
 _SecCmsSignerInfoGetEncDigest
 _SecCmsSignerInfoIncludeCerts
index e8a243e8ed58af686b7c43010513b23b7b0faeb4..9653f90184e0e8b593cbc4dcc1faf7962c0cbf03 100644 (file)
@@ -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");
index 6bc113e4857ae7d74db8e1073a3d77bb0accdd2f..cb00ea23257f6c98b4673180024478d648b833b2 100644 (file)
@@ -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 (file)
index 0000000..1cbe0d0
--- /dev/null
@@ -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 <Security/SecBasePriv.h>
+#include <syslog.h>
+
+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<void **>(&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<const void *>(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<const void *>(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<void **>(&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 (file)
index 0000000..2a5adce
--- /dev/null
@@ -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 <security_cdsa_client/dlclient.h>
+
+//
+// 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
index d2c6a4dc8ac4b4675176549b0d1215c30a789071..b3776ed5356c99362fbb6b9601a29978195602d2 100644 (file)
@@ -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) {
index ad4fc80d2169b7b4e6b6c5812c8d719f8c0eb739..b8a38d3a17d8386ae8d52dd28760c835b0703d59 100644 (file)
@@ -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 <class Data>
 inline CFDataRef makeCFData(const Data &source)
 {
@@ -618,7 +623,7 @@ CFToVector<VectorBase, CFRefType, convert>::CFToVector(CFArrayRef arrayRef)
 // Make CFArrays from stuff.
 //
 template <class Iterator, class Generator>
-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 <class Container, class Generator>
-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;
index 83d2624cc9ae78305ae6854d86815d0f812babca..53aeecd7a7288ec6526d1ea93984f6bd380d23c4 100644 (file)
@@ -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);
+    }
+}
index f4e7cb852adab7ccef50134ddaf8b69224af6533..6f990296c7bf5d004a33377a008fd60387af36b9 100644 (file)
@@ -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))
 
 //
index b799d116aa2187913d89e133fa074b2c09bb2a77..d9e60230551a121a855c2c12f962ce5712ea23cd 100644 (file)
@@ -1 +1,2 @@
 _secdebug_internal
+_secdebugfunc_internal
index a54d2b4e375364cc8b971a6cd6cd504d118f307b..b9117998286771b30d5f2d319a7236393a8556b9 100644 (file)
@@ -31,6 +31,7 @@
 #include <cstring>
 #include <memory>
 #include <sys/types.h>
+#include <security_utilities/refcount.h>
 #include <CommonCrypto/CommonDigestSPI.h>      // 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 <uint32_t _size, class _HashType>
 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<typename _Dataoid>
+       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 _HashType>
-class DynamicHashInstance : public DynamicHash, public _HashType {
-public:
-       // (wish we had C++0x already...)
-       DynamicHashInstance() { }
-       template <class Arg1>
-       DynamicHashInstance(const Arg1 &arg1) : _HashType(arg1) { }
-       template <class Arg1, class Arg2>
-       DynamicHashInstance(const Arg1 &arg1, const Arg2 &arg2) : _HashType(arg1, arg2) { }
-       template <class Arg1, class Arg2, class Arg3>
-       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 _Giver, DynamicHash *(_Giver::*_fetcher)() const = &_Giver::getHash>
-class MakeHash : public std::auto_ptr<DynamicHash> {
+class MakeHash : public RefPointer<DynamicHash> {
 public:
-       MakeHash(const _Giver *giver) : std::auto_ptr<DynamicHash>((giver->*_fetcher)()) { }
+       MakeHash(const _Giver *giver) : RefPointer<DynamicHash>((giver->*_fetcher)()) { }
        
        operator DynamicHash *() const { return this->get(); }
 };
index 97b2ea6c17a65a9cd00ea7159d7244d47ae35b55..ed3a2fea9e8f2d67dabda92ffb1b619274aebd96 100644 (file)
@@ -412,6 +412,19 @@ const linkedit_data_command *MachOBase::findLibraryDependencies() const
                return reinterpret_cast<const linkedit_data_command *>(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<const version_min_command *>(command);
+               }
+       return NULL;
+}
 
 
 //
index d75b0843461c0e54e4e47bc4f40a40ac118e7e13..b9e9bc7b9b3b8ab2df58916d4501f11276e6deac 100644 (file)
@@ -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
index 0c7ac4968c04b03c4b7514d50cf5b18f27e75f39..f3287805cd67c239dd20349341bc9e11b9205e23 100644 (file)
@@ -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 <class Data>
        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 <class T>
+    T *operator () (const T &obj)
+    { return Writer::operator() (obj) - basePos; }
+
+    void *operator () (const void *addr, size_t size)
+    { return reinterpret_cast<void *>(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
index 785f51ce33e9283eea3fcc8cd285a8541d3c0fda..e6b8edc86b4eac6e9b203ff34810f89842c90e69 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <security_utilities/blob.h>
 #include <map>
+#include <vector>
 
 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<size_t> &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 <class _BlobType, uint32_t _magic, class _Type>
-size_t SuperBlobCore<_BlobType, _magic, _Type>::Maker::size(size_t size1, ...) const
+size_t SuperBlobCore<_BlobType, _magic, _Type>::Maker::size(const std::vector<size_t> &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 <class _BlobType, uint32_t _magic, class _Type>
 _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<size_t>(), 0);
        _BlobType *result = (_BlobType *)malloc(total);
        if (!result)
                UnixError::throwMe(ENOMEM);
index 9e0bed6454d8b2aa7bbe68593ec23bbd79f0222b..bfe6427ca92ddf131ca8de151cbd1dce8bb2405b 100644 (file)
@@ -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;
+}
+
 
 
 //
index a903dc100b96bf5ed1db9f4598f4a3ae85cd85f5..60168536e66e006ba4b877483713e11fb647216a 100644 (file)
@@ -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 <class TakeLock, class ReleaseLock,
        void (TakeLock::*_lock)() = &TakeLock::lock,
        void (TakeLock::*_unlock)() = &TakeLock::unlock,
index 26360eb7d30d1d12c3b23392c4d4f23ca8731a81..d6f4aa5a5972d796c0fcd94e9cfa0c8d35cde0d8 100644 (file)
@@ -208,8 +208,6 @@ public:
        void removeAttr(const std::string &name, int options = 0)
        { return removeAttr(name.c_str(), options); }
        size_t listAttr(char *value, size_t length, int options = 0);
-       size_t listAttr(const std::string &name, size_t length, int options = 0)
-       { return listAttr(name.c_str(), length, options); }
        
        // xattrs with string values (not including trailing null bytes)
        void setAttr(const std::string &name, const std::string &value, int options = 0);
index 0fb83593615ff91784d901b743a3df611941e745..48b634e2f672e8c940fbf166a4899c1b99a462c7 100644 (file)
                C2EF2B5A066E516600F205D4 /* pcsc++.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2EF2B58066E516600F205D4 /* pcsc++.cpp */; };
                D65C871405DC11C300B401EF /* cfclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D65C871205DC11C300B401EF /* cfclass.cpp */; };
                D6C5F6BD05DD47EC00722571 /* seccfobject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D6C5F6BB05DD47EC00722571 /* seccfobject.cpp */; };
+               DC27E9F51BBC589500C9BC39 /* CSPDLTransaction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DC27E9F31BBC589500C9BC39 /* CSPDLTransaction.cpp */; };
+               DC27E9F61BBC589500C9BC39 /* CSPDLTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = DC27E9F41BBC589500C9BC39 /* CSPDLTransaction.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                D65C871305DC11C300B401EF /* cfclass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cfclass.h; sourceTree = "<group>"; };
                D6C5F6BB05DD47EC00722571 /* seccfobject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = seccfobject.cpp; sourceTree = "<group>"; };
                D6C5F6BC05DD47EC00722571 /* seccfobject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = seccfobject.h; sourceTree = "<group>"; };
+               DC27E9F31BBC589500C9BC39 /* CSPDLTransaction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSPDLTransaction.cpp; sourceTree = "<group>"; };
+               DC27E9F41BBC589500C9BC39 /* CSPDLTransaction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSPDLTransaction.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                4CA6847F0525011D00233BF2 /* lib */ = {
                        isa = PBXGroup;
                        children = (
+                               DC27E9F31BBC589500C9BC39 /* CSPDLTransaction.cpp */,
+                               DC27E9F41BBC589500C9BC39 /* CSPDLTransaction.h */,
                                AAAA49980CC587B50099E9D4 /* crc.c */,
                                AAAA49990CC587B50099E9D4 /* crc.h */,
                                C2B1EBFE06D557B300F68F34 /* adornments.h */,
                                181EA39B146D1D5A00A6D320 /* powerwatch.h in Headers */,
                                181EA39C146D1D5A00A6D320 /* refcount.h in Headers */,
                                181EA39D146D1D5A00A6D320 /* seccfobject.h in Headers */,
+                               DC27E9F61BBC589500C9BC39 /* CSPDLTransaction.h in Headers */,
                                181EA39E146D1D5A00A6D320 /* security_utilities.h in Headers */,
                                181EA39F146D1D5A00A6D320 /* simpleprefs.h in Headers */,
                                181EA3A0146D1D5A00A6D320 /* sqlite++.h in Headers */,
                                D6C5F6BD05DD47EC00722571 /* seccfobject.cpp in Sources */,
                                C2EF2B5A066E516600F205D4 /* pcsc++.cpp in Sources */,
                                C2A7D0B706AEDB94009A7A1E /* unixchild.cpp in Sources */,
+                               DC27E9F51BBC589500C9BC39 /* CSPDLTransaction.cpp in Sources */,
                                C20A206B06B03FDC00979EF3 /* osxcode.cpp in Sources */,
                                C24DAED406B8952E00387C29 /* cfmach++.cpp in Sources */,
                                C2B1EBFF06D557B300F68F34 /* adornments.cpp in Sources */,
index 2a47bd26ae6a1bc3c0f00ec09a01b7b4c63aa660..a758dc3b5a840bc8210f3d4cfc62fe19e7c0c80f 100644 (file)
 namespace Security {
 namespace SecurityServer {
 
+uint32 CommonBlob::getCurrentVersion() {
+  uint32 ret = version_MacOS_10_0;
+  // If the integrity protections are turned on, use version_partition.
+  // else, use version_MacOS_10_0.
+  CFTypeRef integrity = (CFNumberRef)CFPreferencesCopyValue(CFSTR("KeychainIntegrity"), CFSTR("com.apple.security"), kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
+  if (integrity && CFGetTypeID(integrity) == CFBooleanGetTypeID()) {
+    bool integrityProtections = CFBooleanGetValue((CFBooleanRef)integrity);
+
+    if(integrityProtections) {
+      secdebugfunc("integrity", "creating a partition keychain; global is on");
+      ret = version_partition;
+    } else {
+      secdebugfunc("integrity", "creating a old-style keychain; global is off");
+      ret = version_MacOS_10_0;
+    }
+    CFRelease(integrity);
+  }
+
+  return ret;
+}
+
+
+void CommonBlob::initialize()
+{
+    magic = magicNumber;
+
+    this->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;
 }
 
index d05f2b73338ba5fc9f725ad1db9c903a9651054d..e39414be98214ff579fb33faa3f421944fafb7ed 100644 (file)
@@ -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;
        
index 6af1fd97a9cdf393e405a1af23900e30215e27da..5b4e2d78a5213980148e50d674e4d76fb748289e 100644 (file)
@@ -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,
index 58a208235b20d30d1d7dec4e5a226ffa3ee2410d..b34fa376713f0634ebf89b4bfb5f4a65cfbca5b8 100644 (file)
@@ -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)
 {
index 0dc58dde63719672ef1e32608a671b735346d04b..e7bb73484824ea1b3ce4faa506cec2848188e50c 100644 (file)
@@ -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);
index 03fad3c98a212d23e7e2ceed4f16ca465bed8ee8..d2c407cfa2e02548599b343b5d9b7df1023e7856 100644 (file)
@@ -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 = "<group>"; };
                0C25A6C012271FAF0050C2BD /* security.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = security.pl; sourceTree = "<group>"; };
                0C25A6C312271FAF0050C2BD /* testcpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testcpp.h; sourceTree = "<group>"; };
-               0C25A6C412271FAF0050C2BD /* testenv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testenv.c; sourceTree = "<group>"; };
+               0C25A6C412271FAF0050C2BD /* testenv.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = testenv.m; sourceTree = "<group>"; };
                0C25A6C512271FAF0050C2BD /* testenv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testenv.h; sourceTree = "<group>"; };
                0C25A6C812271FAF0050C2BD /* testmore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testmore.c; sourceTree = "<group>"; };
                0C25A6C912271FAF0050C2BD /* testmore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = testmore.h; sourceTree = "<group>"; };
@@ -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 */,
                        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.c
deleted file mode 100644 (file)
index bd85e15..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (c) 2005-2007,2009-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@
- *
- * testenv.c
- */
-
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <time.h>
-#include <sys/time.h>
-
-#include "testmore.h"
-#include "testenv.h"
-
-#include <utilities/debugging.h>
-#include <utilities/SecCFRelease.h>
-#include <utilities/SecCFWrappers.h>
-#include <utilities/SecFileLocations.h>
-
-#include <dispatch/dispatch.h>
-
-
-int test_strict_bats = 1;
-int test_verbose = 0;
-int test_onebatstest = 0;
-
-#ifdef NO_SERVER
-#include <securityd/spi.h>
-
-static int current_dir = -1;
-static char scratch_dir[50];
-static char *home_var;
-static bool keep_scratch_dir = false;
-
-static int
-rmdir_recursive(const char *path)
-{
-#if (!TARGET_IPHONE_SIMULATOR)
-    char command_buf[256];
-       if (strlen(path) + 10 > sizeof(command_buf) || strchr(path, '\''))
-       {
-               fprintf(stdout, "# rmdir_recursive: invalid path: %s", path);
-               return -1;
-       }
-
-       sprintf(command_buf, "/bin/rm -rf '%s'", path);
-       return system(command_buf);
-#else
-    fprintf(stdout, "# rmdir_recursive: simulator can't rmdir, leaving path: %s\n", path);
-    return 0;
-#endif
-}
-#endif
-
-static int tests_init(void) {
-    int ok = 0;
-#ifdef NO_SERVER
-       char preferences_dir[80];
-       char library_dir[70];
-
-       setup("tests_init");
-
-    /* Create scratch dir for tests to run in. */
-    sprintf(scratch_dir, "/tmp/tst-%d", getpid());
-    if (keep_scratch_dir) {
-        printf("running tests with HOME=%s\n", scratch_dir);
-    }
-
-    sprintf(library_dir, "%s/Library", scratch_dir);
-    sprintf(preferences_dir, "%s/Preferences", library_dir);
-    ok =  (ok_unix(mkdir(scratch_dir, 0755), "mkdir") &&
-           ok_unix(current_dir = open(".", O_RDONLY), "open") &&
-           ok_unix(chdir(scratch_dir), "chdir") &&
-           ok_unix(setenv("HOME", scratch_dir, 1), "setenv") &&
-           /* @@@ Work around a bug that the prefs code in
-            libsecurity_keychain never creates the Library/Preferences
-            dir. */
-           ok_unix(mkdir(library_dir, 0755), "mkdir") &&
-           ok_unix(mkdir(preferences_dir, 0755), "mkdir") &&
-           ok(home_var = getenv("HOME"), "getenv"));
-    
-    if (ok > 0)
-        securityd_init(scratch_dir);
-#endif
-
-    return ok;
-}
-
-static int
-tests_end(void)
-{
-#ifdef NO_SERVER
-       setup("tests_end");
-       /* Restore previous cwd and remove scratch dir. */
-       int ok = ok_unix(fchdir(current_dir), "fchdir");
-       if (ok)
-               ok = ok_unix(close(current_dir), "close");
-       if (ok) {
-               if (!keep_scratch_dir) {
-                       ok = ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive");
-               }
-       }
-    
-       return ok;
-#else
-    return 0;
-#endif
-}
-
-static void usage(const char *progname)
-{
-    fprintf(stderr, "usage: %s [-k][-w][testname [testargs] ...]\n", progname);
-    exit(1);
-}
-
-/* run one test, described by test, return info in test struct */
-static int tests_run_test(struct one_test_s *test, int argc, char * const *argv)
-{
-    int ch;
-
-    while ((ch = getopt(argc, argv, "v")) != -1)
-    {
-        switch  (ch)
-        {
-            case 'v':
-                test_verbose++;
-                break;
-            default:
-                usage(argv[0]);
-        }
-    }
-
-    if (test_onebatstest)
-        fprintf(stdout, "[TEST] %s\n", test->name);
-    else
-        fprintf(stdout, "[BEGIN] %s\n", test->name);
-
-    const char *token = "PASS";
-    if (test->entry == NULL) {
-        fprintf(stdout, "%s:%d: error, no entry\n", __FILE__, __LINE__);
-        test->failed_tests = 1;
-    } else {
-        struct timeval start, stop;
-        gettimeofday(&start, NULL);
-        test->entry(argc, argv);
-        gettimeofday(&stop, NULL);
-        /* this may overflow... */
-        test->duration = (stop.tv_sec-start.tv_sec) * 1000 + (stop.tv_usec / 1000) - (start.tv_usec / 1000);
-        if (test_plan_ok()) {
-            token = "WARN";
-        }
-    }
-
-    test_plan_final(&test->failed_tests, &test->todo_pass_tests, &test->todo_tests,
-                    &test->actual_tests, &test->planned_tests,
-                    &test->plan_file, &test->plan_line);
-    if (test_verbose) {
-        // TODO Use ccperf timing and  printing routines that use proper si scaling
-        fprintf(stdout, "%s  took %lu ms\n", test->name, test->duration);
-    }
-    if (test->failed_tests) {
-        token = "FAIL";
-    }
-    fprintf(stdout, "[%s] %s\n", token, test->name);
-
-    return test->failed_tests;
-}
-
-static int strcmp_under_is_dash(const char *s, const char *t) {
-    for (;;) {
-        char a = *s++, b = *t++;
-        if (a != b) {
-            if (a != '_' || b != '-')
-                return a - b;
-        } else if (a == 0) {
-            return 0;
-        }
-    }
-}
-
-static int tests_named_index(const char *testcase)
-{
-    int i;
-
-    for (i = 0; testlist[i].name; ++i) {
-        if (strcmp_under_is_dash(testlist[i].name, testcase) == 0) {
-            return i;
-        }
-    }
-
-    return -1;
-}
-
-static int tests_run_all(int argc, char * const *argv)
-{
-    int curroptind = optind;
-    int i;
-    int failcount=0;
-
-    for (i = 0; testlist[i].name; ++i) {
-        if(!testlist[i].off) {
-            failcount+=tests_run_test(&testlist[i], argc, argv);
-            optind = curroptind;
-        }
-    }
-
-    return failcount;
-}
-
-static void
-tests_summary(const char *progname) {
-    int failed_tests = 0;
-    int todo_pass_tests = 0;
-    int todo_tests = 0;
-    int actual_tests = 0;
-    int planned_tests = 0;
-
-    // First compute the totals to help decide if we need to print headers or not.
-    for (int i = 0; testlist[i].name; ++i) {
-        if (!testlist[i].off) {
-            failed_tests += testlist[i].failed_tests;
-            todo_pass_tests += testlist[i].todo_pass_tests;
-            todo_tests += testlist[i].todo_tests;
-            actual_tests += testlist[i].actual_tests;
-            planned_tests += testlist[i].planned_tests;
-        }
-    }
-
-    if (!test_onebatstest) {
-        fprintf(stdout, "[%s] %s\n", failed_tests ? "FAIL" : (actual_tests == planned_tests ? "PASS" : "WARN"), progname);
-    }
-
-    fprintf(stdout, "[SUMMARY]\n");
-
-    // -v -v makes the summary verbose as well.
-    fprintf(stdout, "Test name                                                 failed !failed  todo  total   plan\n");
-    if (test_verbose > 1 || failed_tests || todo_pass_tests || actual_tests != planned_tests || (test_verbose && todo_tests)) {
-        fprintf(stdout, "============================================================================================\n");
-    }
-    for (int i = 0; testlist[i].name; ++i) {
-        if (!testlist[i].off) {
-            const char *token = NULL;
-            if (testlist[i].failed_tests) {
-                token = "FAIL";
-            } else if (testlist[i].actual_tests != testlist[i].planned_tests) {
-                token = "WARN";
-            } else if (testlist[i].todo_pass_tests) {
-                token = "WARN";
-            } else if (test_verbose > 1 || (test_verbose && testlist[i].todo_tests)) {
-                token = "PASS";
-            }
-            if (token) {
-                fprintf(stdout, "[%s] %-50s %6d %6d %6d %6d %6d\n", token, testlist[i].name, testlist[i].failed_tests, testlist[i].todo_pass_tests, testlist[i].todo_tests, testlist[i].actual_tests, testlist[i].planned_tests);
-            }
-        }
-    }
-    if (test_verbose > 1 || failed_tests || todo_pass_tests || actual_tests != planned_tests || (test_verbose && todo_tests)) {
-        fprintf(stdout, "============================================================================================\n");
-    }
-    fprintf(stdout, "Totals                                                    %6d %6d %6d %6d %6d\n", failed_tests, todo_pass_tests, todo_tests, actual_tests, planned_tests);
-    
-}
-
-#define ASYNC_LOGGING  0
-#define DATE_LOGGING   0
-
-int
-tests_begin(int argc, char * const *argv) {
-    const char *testcase = NULL;
-    bool initialized = false;
-    __block bool print_security_logs = false;
-    int testix = -1;
-    int failcount = 0;
-       int ch;
-    int loop = 0;
-    int list = 0;
-
-#if ASYNC_LOGGING
-    dispatch_queue_t show_queue = dispatch_queue_create("sec log queue", DISPATCH_QUEUE_SERIAL);
-#endif
-
-    security_log_handler handle_logs = ^(int level, CFStringRef scope, const char *function, const char *file, int line, CFStringRef message) {
-        time_t now = time(NULL);
-#if DATE_LOGGING
-        char *date = ctime(&now);
-        date[19] = '\0';
-        CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-                                                      CFSTR("%s %@{} %s %@\n"), date + 4,
-                                                      scope ? scope : CFSTR(""), function, message);
-#else
-        CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-                                                      CFSTR("%lu %@{} %s %@\n"), now,
-                                                      scope ? scope : CFSTR(""), function, message);
-#endif
-#if ASYNC_LOGGING
-        dispatch_async(show_queue, ^{ CFShow(logStr); CFReleaseSafe(logStr); });
-#else
-        CFShow(logStr);
-        CFReleaseSafe(logStr);
-#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)
-        {
-            switch  (ch)
-            {
-#ifdef NO_SERVER
-            case 'k':
-                keep_scratch_dir = true;
-                break;
-#endif
-            case 's':
-                if (!print_security_logs) {
-                    add_security_log_handler(handle_logs);
-                    print_security_logs = true;
-                }
-                break;
-
-            case 'b':
-                test_strict_bats = 0;
-                break;
-
-            case 'v':
-                test_verbose++;
-                break;
-
-            case 'w':
-                sleep(100);
-                break;
-            case 'l':
-                loop=1;
-                break;
-            case 'L':
-                list=1;
-                break;
-            case '1':
-                test_onebatstest=1;
-                break;
-            case '?':
-            default:
-                printf("invalid option %c\n",ch); 
-                usage(argv[0]);
-            }
-        }
-
-        if (optind < argc) {
-            testix = tests_named_index(argv[optind]);
-            if(testix<0) {
-                printf("invalid test %s\n",argv[optind]); 
-                usage(argv[0]);
-            }
-        }
-
-        if (!list && !initialized && !test_onebatstest)
-            fprintf(stdout, "[TEST] %s\n", progname);
-        if (testix < 0) {
-            if (!initialized) {
-                tests_init();
-                initialized = true;
-                (void)initialized;
-                if (!list)
-                    failcount+=tests_run_all(argc, argv);
-            }
-            break;
-        } else {
-            if (!initialized) {
-                tests_init();
-                initialized = true;
-                for (int i = 0; testlist[i].name; ++i) {
-                    testlist[i].off = 1;
-                }
-            }
-            optind++;
-            testlist[testix].off = 0;
-            if (!list)
-                failcount+=tests_run_test(&testlist[testix], argc, argv);
-            testix = -1;
-        }
-    }
-    if (list) {
-        for (int i = 0; testlist[i].name; ++i) {
-            if (!testlist[i].off) {
-                    fprintf(stdout, "%s\n", testlist[i].name);
-            }
-        }
-    } else {
-        tests_summary(progname);
-    }
-    
-    remove_security_log_handler(handle_logs);
-    fflush(stdout);
-
-
-    /* Cleanups */
-    tests_end();
-
-    if (loop) {
-        printf("Looping until key press 'q'. You can run leaks now.\n");
-        while(getchar()!='q');
-    }
-
-    return failcount;
-}
-
diff --git a/OSX/regressions/test/testenv.m b/OSX/regressions/test/testenv.m
new file mode 100644 (file)
index 0000000..4bdf467
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2005-2007,2009-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@
+ *
+ * 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 <Foundation/Foundation.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "testmore.h"
+#include "testenv.h"
+
+#include <utilities/debugging.h>
+#include <utilities/SecCFRelease.h>
+#include <utilities/SecCFWrappers.h>
+#include <utilities/SecFileLocations.h>
+
+#include <dispatch/dispatch.h>
+
+
+int test_strict_bats = 1;
+int test_verbose = 0;
+int test_onebatstest = 0;
+
+#ifdef NO_SERVER
+#include <securityd/spi.h>
+
+static int current_dir = -1;
+static char scratch_dir[50];
+static char *home_var;
+static bool keep_scratch_dir = false;
+
+static int
+rmdir_recursive(const char *path)
+{
+#if (!TARGET_IPHONE_SIMULATOR)
+    char command_buf[256];
+       if (strlen(path) + 10 > sizeof(command_buf) || strchr(path, '\''))
+       {
+               fprintf(stdout, "# rmdir_recursive: invalid path: %s", path);
+               return -1;
+       }
+
+       sprintf(command_buf, "/bin/rm -rf '%s'", path);
+       return system(command_buf);
+#else
+    fprintf(stdout, "# rmdir_recursive: simulator can't rmdir, leaving path: %s\n", path);
+    return 0;
+#endif
+}
+#endif
+
+static int tests_init(void) {
+    int ok = 0;
+#ifdef NO_SERVER
+       char preferences_dir[80];
+       char library_dir[70];
+
+       setup("tests_init");
+
+    /* Create scratch dir for tests to run in. */
+    sprintf(scratch_dir, "/tmp/tst-%d", getpid());
+    if (keep_scratch_dir) {
+        printf("running tests with HOME=%s\n", scratch_dir);
+    }
+
+    sprintf(library_dir, "%s/Library", scratch_dir);
+    sprintf(preferences_dir, "%s/Preferences", library_dir);
+    ok =  (ok_unix(mkdir(scratch_dir, 0755), "mkdir") &&
+           ok_unix(current_dir = open(".", O_RDONLY), "open") &&
+           ok_unix(chdir(scratch_dir), "chdir") &&
+           ok_unix(setenv("HOME", scratch_dir, 1), "setenv") &&
+           /* @@@ Work around a bug that the prefs code in
+            libsecurity_keychain never creates the Library/Preferences
+            dir. */
+           ok_unix(mkdir(library_dir, 0755), "mkdir") &&
+           ok_unix(mkdir(preferences_dir, 0755), "mkdir") &&
+           ok(home_var = getenv("HOME"), "getenv"));
+    
+    if (ok > 0)
+        securityd_init(scratch_dir);
+#endif
+
+    return ok;
+}
+
+static int
+tests_end(void)
+{
+#ifdef NO_SERVER
+       setup("tests_end");
+       /* Restore previous cwd and remove scratch dir. */
+       int ok = ok_unix(fchdir(current_dir), "fchdir");
+       if (ok)
+               ok = ok_unix(close(current_dir), "close");
+       if (ok) {
+               if (!keep_scratch_dir) {
+                       ok = ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive");
+               }
+       }
+    
+       return ok;
+#else
+    return 0;
+#endif
+}
+
+static void usage(const char *progname)
+{
+    fprintf(stderr, "usage: %s [-k][-w][testname [testargs] ...]\n", progname);
+    exit(1);
+}
+
+/* run one test, described by test, return info in test struct */
+static int tests_run_test(struct one_test_s *test, int argc, char * const *argv)
+{
+    int ch;
+
+    while ((ch = getopt(argc, argv, "v")) != -1)
+    {
+        switch  (ch)
+        {
+            case 'v':
+                test_verbose++;
+                break;
+            default:
+                usage(argv[0]);
+        }
+    }
+
+    if (test_onebatstest)
+        fprintf(stdout, "[TEST] %s\n", test->name);
+    else
+        fprintf(stdout, "[BEGIN] %s\n", test->name);
+
+    const char *token = "PASS";
+    if (test->entry == NULL) {
+        fprintf(stdout, "%s:%d: error, no entry\n", __FILE__, __LINE__);
+        test->failed_tests = 1;
+    } else {
+        struct timeval start, stop;
+        gettimeofday(&start, NULL);
+        test->entry(argc, argv);
+        gettimeofday(&stop, NULL);
+        /* this may overflow... */
+        test->duration = (stop.tv_sec-start.tv_sec) * 1000 + (stop.tv_usec / 1000) - (start.tv_usec / 1000);
+        if (test_plan_ok()) {
+            token = "WARN";
+        }
+    }
+
+    test_plan_final(&test->failed_tests, &test->todo_pass_tests, &test->todo_tests,
+                    &test->actual_tests, &test->planned_tests,
+                    &test->plan_file, &test->plan_line);
+    if (test_verbose) {
+        // TODO Use ccperf timing and  printing routines that use proper si scaling
+        fprintf(stdout, "%s  took %lu ms\n", test->name, test->duration);
+    }
+    if (test->failed_tests) {
+        token = "FAIL";
+    }
+    fprintf(stdout, "[%s] %s\n", token, test->name);
+
+    return test->failed_tests;
+}
+
+static int strcmp_under_is_dash(const char *s, const char *t) {
+    for (;;) {
+        char a = *s++, b = *t++;
+        if (a != b) {
+            if (a != '_' || b != '-')
+                return a - b;
+        } else if (a == 0) {
+            return 0;
+        }
+    }
+}
+
+static int tests_named_index(const char *testcase)
+{
+    int i;
+
+    for (i = 0; testlist[i].name; ++i) {
+        if (strcmp_under_is_dash(testlist[i].name, testcase) == 0) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+static int tests_run_all(int argc, char * const *argv)
+{
+    int curroptind = optind;
+    int i;
+    int failcount=0;
+
+    for (i = 0; testlist[i].name; ++i) {
+        if(!testlist[i].off) {
+            @autoreleasepool {
+                failcount+=tests_run_test(&testlist[i], argc, argv);
+            }
+            optind = curroptind;
+        }
+    }
+
+    return failcount;
+}
+
+static void
+tests_summary(const char *progname) {
+    int failed_tests = 0;
+    int todo_pass_tests = 0;
+    int todo_tests = 0;
+    int actual_tests = 0;
+    int planned_tests = 0;
+
+    // First compute the totals to help decide if we need to print headers or not.
+    for (int i = 0; testlist[i].name; ++i) {
+        if (!testlist[i].off) {
+            failed_tests += testlist[i].failed_tests;
+            todo_pass_tests += testlist[i].todo_pass_tests;
+            todo_tests += testlist[i].todo_tests;
+            actual_tests += testlist[i].actual_tests;
+            planned_tests += testlist[i].planned_tests;
+        }
+    }
+
+    if (!test_onebatstest) {
+        fprintf(stdout, "[%s] %s\n", failed_tests ? "FAIL" : (actual_tests == planned_tests ? "PASS" : "WARN"), progname);
+    }
+
+    fprintf(stdout, "[SUMMARY]\n");
+
+    // -v -v makes the summary verbose as well.
+    fprintf(stdout, "Test name                                                 failed !failed  todo  total   plan\n");
+    if (test_verbose > 1 || failed_tests || todo_pass_tests || actual_tests != planned_tests || (test_verbose && todo_tests)) {
+        fprintf(stdout, "============================================================================================\n");
+    }
+    for (int i = 0; testlist[i].name; ++i) {
+        if (!testlist[i].off) {
+            const char *token = NULL;
+            if (testlist[i].failed_tests) {
+                token = "FAIL";
+            } else if (testlist[i].actual_tests != testlist[i].planned_tests) {
+                token = "WARN";
+            } else if (testlist[i].todo_pass_tests) {
+                token = "WARN";
+            } else if (test_verbose > 1 || (test_verbose && testlist[i].todo_tests)) {
+                token = "PASS";
+            }
+            if (token) {
+                fprintf(stdout, "[%s] %-50s %6d %6d %6d %6d %6d\n", token, testlist[i].name, testlist[i].failed_tests, testlist[i].todo_pass_tests, testlist[i].todo_tests, testlist[i].actual_tests, testlist[i].planned_tests);
+            }
+        }
+    }
+    if (test_verbose > 1 || failed_tests || todo_pass_tests || actual_tests != planned_tests || (test_verbose && todo_tests)) {
+        fprintf(stdout, "============================================================================================\n");
+    }
+    fprintf(stdout, "Totals                                                    %6d %6d %6d %6d %6d\n", failed_tests, todo_pass_tests, todo_tests, actual_tests, planned_tests);
+    
+}
+
+#define ASYNC_LOGGING  0
+#define DATE_LOGGING   0
+
+int
+tests_begin(int argc, char * const *argv) {
+    const char *testcase = NULL;
+    bool initialized = false;
+    __block bool print_security_logs = false;
+    int testix = -1;
+    int failcount = 0;
+       int ch;
+    int loop = 0;
+    int list = 0;
+
+#if ASYNC_LOGGING
+    dispatch_queue_t show_queue = dispatch_queue_create("sec log queue", DISPATCH_QUEUE_SERIAL);
+#endif
+
+    security_log_handler handle_logs = ^(int level, CFStringRef scope, const char *function, const char *file, int line, CFStringRef message) {
+        time_t now = time(NULL);
+#if DATE_LOGGING
+        char *date = ctime(&now);
+        date[19] = '\0';
+        CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
+                                                      CFSTR("%s %@{} %s %@\n"), date + 4,
+                                                      scope ? scope : CFSTR(""), function, message);
+#else
+        CFStringRef logStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
+                                                      CFSTR("%lu %@{} %s %@\n"), now,
+                                                      scope ? scope : CFSTR(""), function, message);
+#endif
+#if ASYNC_LOGGING
+        dispatch_async(show_queue, ^{ CFShow(logStr); CFReleaseSafe(logStr); });
+#else
+        CFShow(logStr);
+        CFReleaseSafe(logStr);
+#endif
+    };
+
+    for (;;) {
+        while (!testcase && (ch = getopt(argc, argv, "bklL1vwqs")) != -1)
+        {
+            switch  (ch)
+            {
+#ifdef NO_SERVER
+            case 'k':
+                keep_scratch_dir = true;
+                break;
+#endif
+            case 's':
+                if (!print_security_logs) {
+                    add_security_log_handler(handle_logs);
+                    print_security_logs = true;
+                }
+                break;
+
+            case 'b':
+                test_strict_bats = 0;
+                break;
+
+            case 'v':
+                test_verbose++;
+                break;
+
+            case 'w':
+                sleep(100);
+                break;
+            case 'l':
+                loop=1;
+                break;
+            case 'L':
+                list=1;
+                break;
+            case '1':
+                test_onebatstest=1;
+                break;
+            case '?':
+            default:
+                printf("invalid option %c\n",ch); 
+                usage(argv[0]);
+            }
+        }
+
+        if (optind < argc) {
+            testix = tests_named_index(argv[optind]);
+            if(testix<0) {
+                printf("invalid test %s\n",argv[optind]); 
+                usage(argv[0]);
+            }
+        }
+
+        if (!list && !initialized && !test_onebatstest)
+            fprintf(stdout, "[TEST] %s\n", getprogname());
+        if (testix < 0) {
+            if (!initialized) {
+                tests_init();
+                initialized = true;
+                (void)initialized;
+                if (!list)
+                    failcount+=tests_run_all(argc, argv);
+            }
+            break;
+        } else {
+            if (!initialized) {
+                tests_init();
+                initialized = true;
+                for (int i = 0; testlist[i].name; ++i) {
+                    testlist[i].off = 1;
+                }
+            }
+            optind++;
+            testlist[testix].off = 0;
+            if (!list) {
+                @autoreleasepool {
+                    failcount+=tests_run_test(&testlist[testix], argc, argv);
+                }
+            }
+            testix = -1;
+        }
+    }
+    if (list) {
+        for (int i = 0; testlist[i].name; ++i) {
+            if (!testlist[i].off) {
+                    fprintf(stdout, "%s\n", testlist[i].name);
+            }
+        }
+    } else {
+        tests_summary(getprogname());
+    }
+    
+    remove_security_log_handler(handle_logs);
+    fflush(stdout);
+
+
+    /* Cleanups */
+    tests_end();
+
+    if (loop) {
+        printf("Looping until key press 'q'. You can run leaks now.\n");
+        while(getchar()!='q');
+    }
+
+    return failcount;
+}
+
index 37360eda91dea40fdee542881cce3f34f0e5a65a..91635b4f099400dc9944b08e237ef29c300c9937 100644 (file)
 @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;
 - (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
index deef754816b5df82a82bc72bf63c2bd8282e4972..bada77e57b084df5f2b40d5ca18114d925d74803 100644 (file)
@@ -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, &notificationToken, _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
index 0b2fe801cfa5653abb3a43ba55ee0306cbea4dab..4b4e2d2418db6b1c03c86ca81ef98b4a57afed52 100644 (file)
@@ -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;
     }
index c77de44d2e259685fb44861dd904ca31eb0cbf27..2288fc561a0251650cd6e18107e7ce554b7a8177 100644 (file)
@@ -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
 
+
index 66dcbf59dc3e169bc1b73619fe45f8589085d61b..5282d8a16793baea59b57167d92f63504b271c96 100644 (file)
@@ -8,7 +8,7 @@
        <true/>
        <key>com.apple.private.ids.force-encryption-off</key>
        <array>
-               <string>com.apple.security.idskeychainsyncingproxy</string>
+               <string>com.apple.private.alloy.keychainsync</string>
        </array>
        <key>com.apple.private.ids.messaging.high-priority</key>
        <array>
index d882635c5c6ae2b5b306ac60392ef3fcacf1f24f..365eedc4975e28e16daf959fe4a89c8e1e2e461b 100644 (file)
@@ -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);
index 28dcbf749068f5a3eecc248815282bf0d9a33af8..21e6d66de3d3b72c577c62a29d964bf44e72ad54 100644 (file)
@@ -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);
 
index 1f9b3dec116834823ffa78d709e4e5f138d76d59..290aa9850e56472b3f801c32c0b113db38f7cb30 100644 (file)
@@ -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;
index 1ff76686e6b5bbd7a8b37eaa6f105d7649ee80c0..913759145492c3bd554776e49c7ee11ecf21896e 100644 (file)
@@ -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);
     });
 }
 
index 006873d149086cdf6639a9f608fc6be309586c51..782222164126e6f443adf9f3cc2d2867d5f4eb93 100644 (file)
@@ -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));
 }
index b04bb7accd7a8ebf9fde760e6e90e07a740e8c2c..5edbc5686b26bde7a41495467e57f722ab288f5c 100644 (file)
@@ -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;
index 97698c4c03e4e92c4387f069f228387fb93448bf..2028f7fe604247e7342eebb4b0f16b8b3c95364b 100644 (file)
@@ -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
 //
index 3cfabdc62665816110f43b2fece1f4c7ff594f1b..c8b24a2c1063090012479e5fd9602a3d793739a9 100644 (file)
@@ -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;
+}
+
index 3b232f3d3b0078a4eda25a15867621af33b8c22e..c7293fe288fd0fa1403d0992fcc9b76abf00c769 100644 (file)
@@ -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) {
index b76a40aa17158ef29352981be1880e01351e4677..037656b808f1bf758043cb0c2337a8fb89cb7844 100644 (file)
@@ -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);
index 9b901c2ffb723bd88a8aab1e549d6e0169aa197f..a405b064b6f2b676297e1313045155353be6b208 100644 (file)
@@ -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
index a6a006c9a6305853ee2ed5eb20990148840ceffa..d3159b9f4ee4dd8b29853be866e2cae9babefeff 100644 (file)
@@ -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)
index bfdd03784dc8de8208e3bbc4e78dcdfdebb613f7..8a36114359c15be84b8939a8d0e7b254567addfa 100644 (file)
@@ -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);
index 152f232b02f0e1074deab244def9c98aaadb89bb..9d86a5f104ee426f7c5011ed9a517d48369ff47a 100644 (file)
@@ -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);
index 8dd9e2b18b51bbc3cf2a950be9035321d010f4fe..b673a2cf5e00a7902c33826457ea4bca3d9164a8 100644 (file)
@@ -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
index 07d4cb3983ac572952b9b26f8d185106664d006a..701b5ad0a5c39bf66ce1cd0984068781a240bfee 100644 (file)
@@ -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)
+}
index 46c7a578f2581ff5c85e21aadf58450dd606ed51..3ce34a300d8fd497961f8cdcd959100f68d5e30e 100644 (file)
@@ -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
 };
 
 //
index 2c467edbf0f1189d4d15f08186db01e1cdce3dad..4deffc24d952070fdbd5e4c69001b35c4eac8bdd 100644 (file)
@@ -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
index 1e6317bffb29f1afe27c4f0b1ea9ebd5b7df1e1f..6d8ff2d5705ad4c8a0abfbb2e1dbe9a2de26cfbd 100644 (file)
@@ -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) {
index 93fdf220c65ad0850915cbc540a083fbf6f96667..d7792daa3eea92204c3cbb2833d12d59b41975b1 100644 (file)
@@ -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);
 }
index 6ebdc0b06552533e32ffe55a6b222a0dbc18c047..2d2777ee5258cd6d515db9b2ff3a110469e8ae57 100644 (file)
@@ -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);
 
index a3b3e507c320683ca86faabf7ba37e6ab7e6c8fd..a7e9b0ea1979aaf0f64da1b070de73d8209e9dcc 100644 (file)
@@ -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);
 
index b05d28b815e5cdf57acbfce5fce545d96c606467..5a14618253e9b55934028aa7197125002325b21f 100644 (file)
@@ -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 (?)
  //
index 40a1b7db0689b1e560983d45e646dbbfa234d6ab..6abe081ef88a9c9534a240b0d2d2c2d1be990372 100644 (file)
@@ -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) {
index d647fb99667e53999f06fd9e4f3d1f66deb674e1..6df8afb7ba6c11c81f59a02edcde32971aa4c1df 100644 (file)
@@ -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);
index d74ef8d0bd9532547c03123b7e8066977fb19130..0cf115825e766f18117aa4031374aeb1e98eb6b8 100644 (file)
@@ -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);
 }
index 8f34dbcc95e9b68667983b2b38961f5ed547a4ae..2e8d660022cd46e2c13a1d1a0ce627de6e9e153a 100644 (file)
 // 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);
index 5b6244c646928954cdd6b6af88be6a19f74bef54..36e2c153c0073d8bfba8001e8c91c262c05b2391 100644 (file)
@@ -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){
index e78897b62c145511dc972225eca4afe3c9eea3e9..8251d7cb132ff8d2e3f0592c123049fbd9f94880 100644 (file)
@@ -1,6 +1,6 @@
 
-#ifndef SOSTransportCoder_h
-#define SOSTransportCoder_h
+#ifndef SOSPeerCoder_h
+#define SOSPeerCoder_h
 #include <Security/SecureObjectSync/SOSTransportMessage.h>
 #include <Security/SecureObjectSync/SOSCoder.h>
 
index 127298f5fffa5eff95bf42ff848be9f12f5ac6e6..ab74681cbb43c9f7f2e0acd89ed40d7ef7d453b3 100644 (file)
@@ -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 (file)
index 0000000..3becdc5
--- /dev/null
@@ -0,0 +1,735 @@
+//
+//  SOSSysdiagnose.c
+//  sec
+//
+//  Created by Richard Murphy on 1/27/16.
+//
+//
+
+
+#include "SOSCloudCircleInternal.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <notify.h>
+#include <pwd.h>
+
+#include <Security/SecItem.h>
+
+#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFString.h>
+
+#include <Security/SecureObjectSync/SOSCloudCircle.h>
+#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
+#include <Security/SecureObjectSync/SOSPeerInfo.h>
+#include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
+#include <Security/SecureObjectSync/SOSPeerInfoV2.h>
+#include <Security/SecureObjectSync/SOSUserKeygen.h>
+#include <Security/SecureObjectSync/SOSKVSKeys.h>
+#include <securityd/SOSCloudCircleServer.h>
+#include <Security/SecOTRSession.h>
+#include <SOSCircle/CKBridge/SOSCloudKeychainClient.h>
+
+#include <utilities/SecCFWrappers.h>
+#include <utilities/debugging.h>
+
+#include <SecurityTool/readline.h>
+
+#include "keychain_log.h"
+#include "secToolFileIO.h"
+
+#include <Security/SecPasswordGenerate.h>
+
+/* Copied from CFPriv.h */
+// #include <CoreFoundation/CFPriv.h>
+
+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 <copyfile.h>
+#include <libgen.h>
+#include <utilities/SecCFWrappers.h>
+
+#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 "<unknown ccstatus>";
+            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;
+}
+
index 76fe9ec5143607a38e01e0224ffcaf92e0c52b4d..e001acb142fc9e2810a11bffaa3dc66cfcb2f81d 100644 (file)
@@ -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 (file)
index b1255f4..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-
-#include <Security/SecureObjectSync/SOSPeer.h>
-#include <Security/SecureObjectSync/SOSTransportCoder.h>
-#include <Security/SecureObjectSync/SOSTransportMessage.h>
-#include <Security/SecureObjectSync/SOSCoder.h>
-#include <Security/SecureObjectSync/SOSAccount.h>
-#include <Security/SecureObjectSync/SOSAccountPriv.h>
-#include <Security/SecureObjectSync/SOSEngine.h>
-
-#include <utilities/debugging.h>
-#include <utilities/SecCFWrappers.h>
-
-#include <AssertMacros.h>
-#include <SOSInternal.h>
-
-
-// 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 (file)
index 0a54625..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-
-#ifndef SOSTransportCoder_h
-#define SOSTransportCoder_h
-#include <Security/SecureObjectSync/SOSTransportMessage.h>
-#include <Security/SecureObjectSync/SOSCoder.h>
-
-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
index 651f1412faf2d20505489bf037005636a152cc0a..9111aa4899834f218492c5c2bd1180e6fd10fb45 100644 (file)
@@ -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 (file)
index 7fab73a..0000000
+++ /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 <Security/SecureObjectSync/SOSViewManager.h>
-#include <Security/SecureObjectSync/SOSInternal.h>
-
-#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("<ViewManager %@ >"), 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/SOSViewManager.h b/OSX/sec/SOSCircle/SecureObjectSync/SOSViewManager.h
deleted file mode 100644 (file)
index 9fe87bf..0000000
+++ /dev/null
@@ -1,54 +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 SOSViewManager.h - View creation and management.
- */
-
-#ifndef _SEC_SOSVIEWMANAGER_H_
-#define _SEC_SOSVIEWMANAGER_H_
-
-#include <Security/SecureObjectSync/SOSChangeTracker.h>
-
-__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);
-
-
-//SOSViewQueryRef SOSViewManagerCopyQueryWithViewName(SOSViewManagerRef vmgr, CFStringRef name);
-
-
-__END_DECLS
-
-#endif /* !_SEC_SOSVIEWMANAGER_H_ */
diff --git a/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c b/OSX/sec/SOSCircle/SecureObjectSync/SOSViewQueries.c
deleted file mode 100644 (file)
index 3571933..0000000
+++ /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 <Security/SecureObjectSync/SOSViewQueries.h>
-
-// 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 (file)
index ead3afd..0000000
+++ /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 <CoreFoundation/CFString.h>
-
-__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/SOSCommands.h b/OSX/sec/SOSCircle/Tool/SOSCommands.h
deleted file mode 100644 (file)
index 6103461..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-
-#include <SecurityTool/security_tool_commands.h>
-
-SECURITY_COMMAND(
-       "sync", keychain_sync,
-       "[options]\n"
-       "Keychain Syncing\n"
-       "    -d     disable\n"
-       "    -e     enable (join/create circle)\n"
-       "    -i     info (current status)\n"
-       "    -m     dump my peer\n"
-       "    -s     schedule sync with all peers\n"
-       "\n"
-       "Account/Circle Management\n"
-       "    -a     accept all applicants\n"
-       "    -l     [reason] sign out of circle + set custom departure reason\n"
-       "    -q     sign out of circle\n"
-       "    -r     reject all applicants\n"
-       "    -E     ensure fresh parameters\n"
-    "    -b     device|all|single Register a backup bag - THIS RESETS BACKUPS!\n"
-    "    -A     Apply to a ring\n"
-    "    -B     Withdrawl from a ring\n"
-    "    -G     Enable Ring\n"
-    "    -F     Ring Status\n"
-    "    -I     Dump Ring Information\n"
-       "    -N     (re-)set to new account (USE WITH CARE: device will not leave circle before resetting account!)\n"
-       "    -O     reset to offering\n"
-       "    -R     reset circle\n"
-       "    -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"
-       "\n"
-       "IDS\n"
-       "    -g     set IDS device id\n"
-       "    -p     retrieve IDS device id\n"
-       "    -x     ping all devices in an IDS account\n"
-       "    -w     check IDS availability\n"
-       "    -z     retrieve IDS id through IDSKeychainSyncingProxy\n"
-       "\n"
-       "Password\n"
-       "    -P     [label:]password  set password (optionally for a given label) for sync\n"
-       "    -T     [label:]password  try password (optionally for a given label) for sync\n"
-       "\n"
-       "KVS\n"
-       "    -k     pend all registered kvs keys\n"
-       "    -C     clear all values from KVS\n"
-       "    -D     [itemName]  dump contents of KVS\n"
-       "    -W     itemNames  sync and dump\n"
-       "\n"
-       "Misc\n"
-       "    -v     [enable|disable|query:viewname] enable, disable, or query my PeerInfo's view set\n"
-       "             viewnames are: keychain|masterkey|iclouddrive|photos|cloudkit|escrow|fde|maildrop|icloudbackup|notes|imessage|appletv|homekit\n"
-    "                            wifi|passwords|creditcards|icloudidentity|othersyncable\n"
-    "    -L     list all known view and their status\n"
-       "    -S     [enable|disable|propertyname] enable, disable, or query my PeerInfo's Security Property set\n"
-       "             propertynames are: hasentropy|screenlock|SEP|IOS\n"
-       "    -U     purge private key material cache\n"
-    "    -V     Report View Sync Status on all known clients.\n"
-    "    -Y     Report yet to initial sync views\n"
-    "    -H     Set escrow record.\n"
-    "    -J     Get the escrow record.\n"
-    "    -M     Check peer availability.\n",
-       "Keychain Syncing controls." )
diff --git a/OSX/sec/SOSCircle/Tool/keychain_log.c b/OSX/sec/SOSCircle/Tool/keychain_log.c
new file mode 100644 (file)
index 0000000..ca9339c
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <Security/SecItem.h>
+
+#include <CoreFoundation/CFNumber.h>
+#include <CoreFoundation/CFString.h>
+
+#include <Security/SecureObjectSync/SOSCloudCircle.h>
+#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
+#include <Security/SecureObjectSync/SOSPeerInfo.h>
+#include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
+#include <Security/SecureObjectSync/SOSPeerInfoV2.h>
+#include <Security/SecureObjectSync/SOSUserKeygen.h>
+#include <Security/SecureObjectSync/SOSKVSKeys.h>
+#include <securityd/SOSCloudCircleServer.h>
+#include <Security/SecOTRSession.h>
+#include <SOSCircle/CKBridge/SOSCloudKeychainClient.h>
+
+#include <utilities/SecCFWrappers.h>
+#include <utilities/debugging.h>
+
+#include <SecurityTool/readline.h>
+#include <notify.h>
+
+#include "keychain_log.h"
+#include "secToolFileIO.h"
+#include <Security/SecPasswordGenerate.h>
+
+#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 "<unknown ccstatus>";
+            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 <CoreFoundation/CFPriv.h>
+
+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 <pwd.h>
+
+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 (file)
index 0000000..f0b98a1
--- /dev/null
@@ -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 <SecurityTool/security_tool_commands.h>
+
+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")
index 98406361e9d45397e89fcf05dc99c20d3c9b7d43..5bd81cf89ccd303467b4febc34dfb945735e88d1 100644 (file)
@@ -28,6 +28,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/stat.h>
+#include <time.h>
 
 #include <Security/SecItem.h>
 
 #include <SecurityTool/readline.h>
 #include <notify.h>
 
-#include "SOSCommands.h"
+#include "keychain_sync.h"
+#include "keychain_log.h"
+#include "secToolFileIO.h"
 
 #include <Security/SecPasswordGenerate.h>
 
-#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/keychain_sync.h b/OSX/sec/SOSCircle/Tool/keychain_sync.h
new file mode 100644 (file)
index 0000000..a36d043
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include <SecurityTool/security_tool_commands.h>
+
+SECURITY_COMMAND(
+       "sync", keychain_sync,
+       "[options]\n"
+       "Keychain Syncing\n"
+       "    -d     disable\n"
+       "    -e     enable (join/create circle)\n"
+       "    -i     info (current status)\n"
+       "    -m     dump my peer\n"
+       "    -s     schedule sync with all peers\n"
+       "\n"
+       "Account/Circle Management\n"
+       "    -a     accept all applicants\n"
+       "    -l     [reason] sign out of circle + set custom departure reason\n"
+       "    -q     sign out of circle\n"
+       "    -r     reject all applicants\n"
+       "    -E     ensure fresh parameters\n"
+    "    -b     device|all|single Register a backup bag - THIS RESETS BACKUPS!\n"
+    "    -A     Apply to a ring\n"
+    "    -B     Withdrawl from a ring\n"
+    "    -G     Enable Ring\n"
+    "    -F     Ring Status\n"
+    "    -I     Dump Ring Information\n"
+       "    -N     (re-)set to new account (USE WITH CARE: device will not leave circle before resetting account!)\n"
+       "    -O     reset to offering\n"
+       "    -R     reset circle\n"
+       "    -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"
+       "    -p     retrieve IDS device id\n"
+       "    -x     ping all devices in an IDS account\n"
+       "    -w     check IDS availability\n"
+       "    -z     retrieve IDS id through IDSKeychainSyncingProxy\n"
+       "\n"
+       "Password\n"
+       "    -P     [label:]password  set password (optionally for a given label) for sync\n"
+       "    -T     [label:]password  try password (optionally for a given label) for sync\n"
+       "\n"
+       "KVS\n"
+       "    -k     pend all registered kvs keys\n"
+       "    -C     clear all values from KVS\n"
+       "    -D     [itemName]  dump contents of KVS\n"
+       "    -W     itemNames  sync and dump\n"
+       "\n"
+       "Misc\n"
+       "    -v     [enable|disable|query:viewname] enable, disable, or query my PeerInfo's view set\n"
+       "             viewnames are: keychain|masterkey|iclouddrive|photos|cloudkit|escrow|fde|maildrop|icloudbackup|notes|imessage|appletv|homekit\n"
+    "                            wifi|passwords|creditcards|icloudidentity|othersyncable\n"
+    "    -L     list all known view and their status\n"
+       "    -S     [enable|disable|propertyname] enable, disable, or query my PeerInfo's Security Property set\n"
+       "             propertynames are: hasentropy|screenlock|SEP|IOS\n"
+       "    -U     purge private key material cache\n"
+    "    -V     Report View Sync Status on all known clients.\n"
+    "    -Y     Report yet to initial sync views\n"
+    "    -H     Set escrow record.\n"
+    "    -J     Get the escrow record.\n"
+    "    -M     Check peer availability.\n",
+       "Keychain Syncing controls." )
diff --git a/OSX/sec/SOSCircle/Tool/secToolFileIO.c b/OSX/sec/SOSCircle/Tool/secToolFileIO.c
new file mode 100644 (file)
index 0000000..233e170
--- /dev/null
@@ -0,0 +1,67 @@
+//
+//  secToolFileIO.c
+//  sec
+//
+//  Created by Richard Murphy on 1/22/16.
+//
+//
+
+#include "secToolFileIO.h"
+
+#include <copyfile.h>
+#include <libgen.h>
+#include <utilities/SecCFWrappers.h>
+
+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 (file)
index 0000000..a73bcd9
--- /dev/null
@@ -0,0 +1,35 @@
+//
+//  secToolFileIO.h
+//  sec
+//
+//  Created by Richard Murphy on 1/22/16.
+//
+//
+
+#ifndef secToolFileIO_h
+#define secToolFileIO_h
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#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 */
index 6cf859a9267aa30d9e158072a629da276f2280fd..5a4d011e8d5cb712a596a32735b96892540fc849 100644 (file)
@@ -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,
 };
 
 
index 5b09c07c94e22d0d915729a7f1889ccdf5a13716..035b3d77d0088edf29e323251f5e775adc2f0955 100644 (file)
@@ -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 (file)
index 0000000..a1521b3
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <Security/SecItemPriv.h>
+#include <utilities/array_size.h>
+#include <utilities/SecCFWrappers.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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 (file)
index 0000000..a0701bf
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <Security/SecItemPriv.h>
+#include <utilities/array_size.h>
+#include <utilities/SecCFWrappers.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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;
+}
index 584030c75c4249d075212cb18c529dcaf02d1dda..f53e135bd0fff86c643486532b22b87257ba7b3d 100644 (file)
@@ -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;
 }
index 4b82fcaed99a5a3f5b4bacf3d842f96ed4e0dfcf..a854cc1dfcfda317aaf9bd9cd2f3e38b1854f0f8 100644 (file)
@@ -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,
+};
index 3816cc9bd972fc2cf657ff82451f8806442c3f33..e28fcf59f91dd600b1d811b483274fa0699ca025 100644 (file)
@@ -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);
index c2df54111f1d4cda0d8aa8b643b364f24863c0d4..05fc5bb3ef3f0e90a8c7c353fd08cab034e458fd 100644 (file)
@@ -25,6 +25,7 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <Security/SecBase.h>
 #include <Security/SecItem.h>
+#include <securityd/SecItemServer.h>
 
 #include <stdlib.h>
 #include <fcntl.h>
@@ -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);
index 49bf6443b6cca19efdecf3706d9dc3be07983057..ecff54fcdf94e91b5a395e9d43d031c834d7aaa6 100644 (file)
@@ -26,6 +26,7 @@
 #include <Security/SecBase.h>
 #include <Security/SecItem.h>
 #include <Security/SecInternal.h>
+#include <securityd/SecItemServer.h>
 
 #include <stdlib.h>
 #include <fcntl.h>
@@ -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);
index cafe5a1419295fe26cceb6151fb4eec170a8260b..4206fb84d201bd23db330c92bb51bd65fc5dba66 100644 (file)
@@ -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;
index 23ea368b410b12de4ddc10c57aa04d9ea913dd5f..368854f78e8be68589bf045ff03c94f985f61ef0 100644 (file)
@@ -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;
 }
index e808f871794044c7a224db430d4d61ccab18f327..519a5ee5ad43ddd47187e7ab3a503d3da2e689a5 100644 (file)
@@ -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 (file)
index 0000000..d611bbf
--- /dev/null
@@ -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 <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <Security/SecCMS.h>
+#include <utilities/SecCFRelease.h>
+
+#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 (file)
index 0000000..8fe4bd9
--- /dev/null
@@ -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 <stdio.h>
+
+/* 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 (file)
index 0000000..771973f
--- /dev/null
@@ -0,0 +1,62 @@
+#define __KEYCHAINCORE__ 1
+
+#include <Foundation/Foundation.h>
+#include <Security/Security.h>
+
+#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 (file)
index 0000000..aa10150
--- /dev/null
@@ -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 <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+#include <Security/SecCertificatePriv.h>
+#include <Security/SecPolicyPriv.h>
+
+#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 (file)
index 0000000..1bccf35
--- /dev/null
@@ -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 <stdio.h>
+
+/* 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 */
index 25ac732ee72983fdf2b7c5cbeccfba0371df1e82..0079cb65fbd88d6d2226a98654b818418482465a 100644 (file)
@@ -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);
index a442f8635fa4446328909536156a5312561c8a32..e08a1a359e7e9ef03941f2fbb59bf3885c700b06 100644 (file)
@@ -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);
         
index b342758c9f1d2fcb0152a3def865f1b74e23cba1..acbd1466401d18db604bc961b8439b5b021584de 100644 (file)
 #include "SecBase64.h"
 #include "AppleBaselineEscrowCertificates.h"
 #include <ipc/securityd_client.h>
+#include <Security/SecKeyInternal.h>
+
+/* 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 =
index 0979efb5102f562dab0d3b6d56e4ac4ae823851d..aea0830a11339ccbdcd29debb596bfa83f40ed8f 100644 (file)
@@ -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);
 
index e038fd1bbc32646eb16fe15348422de216f0ebf7..750faa96edf1e8894b9640f7702459c8a4b09bae 100644 (file)
@@ -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 (file)
index 0000000..1aa1215
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#include <Security/SecBase.h>
+#include <Security/SecBasePriv.h>
+#include <corecrypto/ccpbkdf2.h>
+#include <corecrypto/ccsha2.h>
+#include <corecrypto/ccaes.h>
+#include <corecrypto/ccmode.h>
+#include <corecrypto/ccwrap.h>
+
+#include <utilities/SecCFWrappers.h>
+#include <AssertMacros.h>
+
+#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/Security/SecEMCSPriv.h b/OSX/sec/Security/SecEMCSPriv.h
new file mode 100644 (file)
index 0000000..fc647c8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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 SecEMCS_h
+#define SecEMCS_h
+
+NSData *
+SecEMCSCreateDerivedEMCSKey(NSDictionary *iDMSData, NSString *passcode, NSError **error);
+
+NSDictionary *
+SecEMCSCreateNewiDMSKey(NSDictionary *options,
+                        NSData *oldEMCSKey,
+                        NSString *managedCredential,
+                        NSData **emcsKey,
+                        NSError **error);
+
+
+
+#endif /* SecEMCS_h */
index 6d95a578cb5476489769e9af0c98ac7111b3806e..2a2fb56f2e778965e573229a781338759ba366ee 100644 (file)
@@ -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
index 38fd63d3ac12a900c58e2fe9424a10f705ac75b8..6635514ad1748b86d0902e4386362b53fe772f92 100644 (file)
@@ -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")
index 112335be757d11a7024f3c9ab418b9bdc97566db..1595e0bf683e4b416a1f554287812e2c5fb602f7 100644 (file)
@@ -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:
index e42c11d404701d5a242a608b31a1b54cb876e226..ff08afe6ebda9f5a217ff66da3894c2d715803d7 100644 (file)
@@ -47,7 +47,7 @@
 #include <os/activity.h>
 #include <notify.h>
 
-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;
index 3dbaa10c673fd5451b765b4cc9f0a4dee7b5b91b..18dea32ff3baac7a4130e6156e25fa43f2dff3df 100644 (file)
@@ -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.
index c98df7bfdd94a0633bed7b235b93102f188818d8..d09ce9d44770adfdcf0dc38d8788bcd96f027dec 100644 (file)
@@ -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");
index b2070c44448eeb814d4fcf3885050a64b72cdd6a..71bdb50cd3f72e4bcce29d9e4b96e1ace291cd0b 100644 (file)
@@ -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);
index e477ed06b8f1591d1b5a67493a1fb2c4d630ec8f..e8fab148af76144727767963bdb62b884ae6a28e 100644 (file)
@@ -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_ */
index 4fb761e1e8c4cbd3bf9ee7b52c40f6e69c979330..81dc4409fe71653deeffc0c877ede5ecf50cdee6 100644 (file)
@@ -349,8 +349,8 @@ static inline CFMutableDataRef CFDataCreateMutableFromOTRDATA(CFAllocatorRef all
     CFDataAppendBytes(result, *bytesPtr, (CFIndex)sizeInStream);
     
     *bytesPtr += sizeInStream;
-    *sizePtr += sizeInStream;
-    
+    *sizePtr -= sizeInStream;
+
 exit:
     return result;
 }
index 2d9afceabf6ed3f938f36a8efd3c42c98d5de7be..e3e01d06c5bea4da199ab8e832679a6d8f878aa2 100644 (file)
@@ -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;
index 94053fd102f593f60578c44810df32e957fb2d96..72d35c5199995a7579d8e8f006a18cb47d72d7c5 100644 (file)
@@ -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,
index 03d96ca32c7f32d195c03c390c3d9f3f3febcb68..b1884743e0b2a91d31fe0a513d9f024104c614d9 100644 (file)
@@ -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);
index d0debccc9aca5b8b26747f121e655c2f623d1237..5bfd8f324e884b3a51ca12732d436c1fe23a43fa 100644 (file)
@@ -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)
index 43d77a13fcb1be9bf86e895912bc73b8b844a51d..a1f6963fcff4a813a3a2dbbd69018918b1b69757 100644 (file)
@@ -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) {
index a7e7158d07793ab8390080a7b18c24603f7c65e5..806f8b7626600467103eb2098f221f92e2b6f04d 100644 (file)
@@ -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) {
index 01a29884bc2a6dbfd7714392513425edfbdf9f8a..03e766160ac4bc1a62346fb91f806a951c1cfc5a 100644 (file)
@@ -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)) {
index 31f9254eb0098a5bfa81d6db42d31ad2ddd0e687..bd0b63be744583edd88fd7363cb1c6b598e803e1 100644 (file)
@@ -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);
index 6c1610d324d2c17883f97c323036f8ca8f5f651a..aa526c1ee24363bbfd7aeef23432e3aad20ba91d 100644 (file)
@@ -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")
index a24c7008fafe5249f01a6d2a437bdc479b059c90..f54560d287240d93d6bafbf89cb1563832ffa42c 100644 (file)
@@ -4,6 +4,8 @@
 <dict>
        <key>keychain-cloud-circle</key>
        <true/>
+       <key>restore-keychain</key>
+       <true/>
        <key>keychain-access-groups</key>
        <array>
                <string>test</string>
diff --git a/OSX/sec/SecurityTool/syncbubble.m b/OSX/sec/SecurityTool/syncbubble.m
new file mode 100644 (file)
index 0000000..51eb455
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#import <Security/Security.h>
+#import <Security/SecItemPriv.h>
+#import <err.h>
+
+#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 (file)
index 0000000..d172d73
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#import <Security/Security.h>
+#import <Security/SecItemPriv.h>
+
+#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;
+}
index 5ed20acbb3ebf463529189620ca7f8f2419aaa0b..790d59d775b40c2e64b24dbf6a4097f316a63c9a 100644 (file)
@@ -31,6 +31,8 @@
 #include <Security/SecBasePriv.h>
 #include <Security/SecInternal.h>
 #include <Security/SecuritydXPC.h>
+#include <Security/SecTask.h>
+#include <Security/SecItemPriv.h>
 
 #include <utilities/debugging.h>
 #include <utilities/SecCFError.h>
@@ -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: */
index c190c5d6d4daa740fe4ee48906668282b4580162..af006dedacc3bd97f9ad02650301a60073f0dd88 100644 (file)
@@ -25,7 +25,8 @@
 
 #include <stdint.h>
 
-# include <Security/SecTrust.h>
+#include <Security/SecTrust.h>
+#include <Security/SecTask.h>
 #ifndef MINIMIZE_INCLUDES
 # include <Security/SecTrustStore.h>
 # include <Security/SecCertificatePath.h>
@@ -39,6 +40,10 @@ typedef struct SecCertificatePath *SecCertificatePathRef;
 # endif // _SECURITY_SECCERTIFICATEPATH_H_
 #endif // MINIMIZE_INCLUDES
 
+#if TARGET_OS_EMBEDDED
+#include <libaks.h>
+#endif
+
 #include <CoreFoundation/CFArray.h>
 #include <CoreFoundation/CFDictionary.h>
 #include <CoreFoundation/CFError.h>
@@ -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;
index 4d00857826cb2f80a67cd7f2d100ea3295bcaaec..ff7d1e3fb8349a77656f9792563a8b70dbf59c2d 100644 (file)
 #include <CoreFoundation/CFXPCBridge.h>
 #include <CoreFoundation/CoreFoundation.h>
 // <rdar://problem/22425706> 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 <MobileKeyBag/MobileKeyBag.h>
-#endif // #if (TARGET_OS_MAC && TARGET_OS_EMBEDDED)
+#endif
+#if !TARGET_OS_IPHONE
+#include <Security/SecTaskPriv.h>
+#endif
 #include <asl.h>
 #include <bsm/libbsm.h>
 #include <ipc/securityd_client.h>
 #include <xpc/private.h>
 #include <xpc/xpc.h>
 
-#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
-#include <Security/SecTaskPriv.h>
+#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 <rdar://problem/13315020> 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)
 
 // <rdar://problem/22425706> 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;
 
        // <rdar://problem/22500239> 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) {
-                       // <rdar://problem/22500239> 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)){
+            // <rdar://problem/22500239> 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
+
        // <rdar://problem/22425706> 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();
 
index 337f6fee6abfa34e586cb39204b308787a4906e1..c2a5765e6b8f3992e259dfa076dbe36043f4d868 100644 (file)
@@ -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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 = "<group>"; 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 = "<group>"; };
                0CBF93F6177B7CFC001E5658 /* secd-04-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-04-corrupted-items.c"; sourceTree = "<group>"; };
-               0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-05-corrupted-items.c"; sourceTree = "<group>"; };
+               0CBF93FB177BA9D9001E5658 /* secd-05-corrupted-items.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "secd-05-corrupted-items.m"; sourceTree = "<group>"; };
                0CE7ABDE171383E30088968F /* keychain_backup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_backup.c; sourceTree = "<group>"; };
                18270C9714CF1AAD00B05E7F /* base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
                18270C9814CF1AAD00B05E7F /* debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = debug.xcconfig; sourceTree = "<group>"; };
                44B2606C18F82631008DF20F /* SecAccessControlExports.exp-in */ = {isa = PBXFileReference; lastKnownFileType = text; path = "SecAccessControlExports.exp-in"; sourceTree = "<group>"; };
                4802A59516D711060059E5B9 /* SOSUserKeygen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSUserKeygen.c; sourceTree = "<group>"; };
                4802A59716D711190059E5B9 /* SOSUserKeygen.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSUserKeygen.h; sourceTree = "<group>"; };
+               48279BC31C57FEA20043457C /* keychain_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keychain_log.c; sourceTree = "<group>"; };
+               48279BC41C57FEA20043457C /* keychain_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keychain_log.h; sourceTree = "<group>"; };
                484182601A30F2E300211511 /* SOSCirclePriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCirclePriv.h; sourceTree = "<group>"; };
                484182621A30F38E00211511 /* SOSCircleRings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCircleRings.h; sourceTree = "<group>"; };
                484182631A30F8D300211511 /* SOSPeerInfoPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoPriv.h; sourceTree = "<group>"; };
                48A071CD1AD6AEA900728AEF /* SOSPeerInfoSecurityProperties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoSecurityProperties.c; sourceTree = "<group>"; };
                48A071CE1AD6AEA900728AEF /* SOSPeerInfoSecurityProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoSecurityProperties.h; sourceTree = "<group>"; };
                48A0FEDD1B6046E2001D6180 /* secd-64-circlereset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-64-circlereset.c"; sourceTree = "<group>"; };
+               48C34E911C45EF3000B7F29B /* secd60-account-cloud-exposure.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd60-account-cloud-exposure.c"; sourceTree = "<group>"; };
                48C7DF9217FF2DB500904F1A /* SOSAccountCredentials.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCredentials.c; sourceTree = "<group>"; };
                48C7DF9517FF351A00904F1A /* SOSAccountPeers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountPeers.c; sourceTree = "<group>"; };
                48C7DF9717FF360F00904F1A /* SOSAccountFullPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountFullPeerInfo.c; sourceTree = "<group>"; };
                48C7DF9917FF44EF00904F1A /* SOSAccountCloudParameters.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountCloudParameters.c; sourceTree = "<group>"; };
                48CE733D1731C49A004C2946 /* sc-130-resignationticket.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-130-resignationticket.c"; sourceTree = "<group>"; };
                48E928C4179DD05500A7F755 /* secd-51-account-inflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-51-account-inflate.c"; sourceTree = "<group>"; };
+               48E9CDFB1C597FED00574D6B /* SOSSysdiagnose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSSysdiagnose.c; sourceTree = "<group>"; };
                48F32D7D1777AFA3001B84BA /* secd-59-account-cleanup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-59-account-cleanup.c"; sourceTree = "<group>"; };
                48F7DF241A6DB32900046644 /* SOSViews.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSViews.c; sourceTree = "<group>"; };
                48F7DF251A6DB32900046644 /* SOSViews.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSViews.h; sourceTree = "<group>"; };
                48FB17001A76F56C00B586C7 /* SOSPeerInfoV2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoV2.c; sourceTree = "<group>"; };
                48FB17011A76F56C00B586C7 /* SOSPeerInfoV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoV2.h; sourceTree = "<group>"; };
                48FB17041A77181A00B586C7 /* secd-80-views-basic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-80-views-basic.c"; sourceTree = "<group>"; };
+               48FEA7771C52FFE70020C148 /* secToolFileIO.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = secToolFileIO.c; sourceTree = "<group>"; };
+               48FEA7781C52FFE70020C148 /* secToolFileIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = secToolFileIO.h; sourceTree = "<group>"; };
                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 = "<group>"; };
                4C8BDDA117B4FE9400C20EA5 /* SOSDigestVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSDigestVector.h; sourceTree = "<group>"; };
                4C9DC91915B602760036D941 /* SOSEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSEngine.h; sourceTree = "<group>"; };
                4C9DC91C15B602910036D941 /* SOSEngine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSEngine.c; sourceTree = "<group>"; };
-               4CB292D81A9E881C003598A1 /* SOSViewManager.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSViewManager.c; sourceTree = "<group>"; };
-               4CB292D91A9E881C003598A1 /* SOSViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSViewManager.h; sourceTree = "<group>"; };
                4CB8A83716164B7700B52EC7 /* SOSTestDataSource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTestDataSource.c; sourceTree = "<group>"; };
                4CB8A83916164B8C00B52EC7 /* SOSTestDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSTestDataSource.h; sourceTree = "<group>"; };
                4CBDB30B17B70206002FA799 /* SOSMessage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSMessage.c; sourceTree = "<group>"; };
                528462991AE6FCF0004C1BA2 /* SOSBackupEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSBackupEvent.c; sourceTree = "<group>"; };
                5284629A1AE6FCF0004C1BA2 /* SOSBackupEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSBackupEvent.h; sourceTree = "<group>"; };
                529F46F11AEC759E0002392C /* secd-34-backup-der-parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-34-backup-der-parse.c"; sourceTree = "<group>"; };
-               52A126D31AAF6C86006AC7CB /* SOSViewQueries.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSViewQueries.c; sourceTree = "<group>"; };
-               52A126D41AAF6C86006AC7CB /* SOSViewQueries.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSViewQueries.h; sourceTree = "<group>"; };
                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 = "<group>"; };
                52DD7069160CD40B0027A346 /* libutilities.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libutilities.a; path = ../../build/Release/libutilities.a; sourceTree = "<group>"; };
                CD32777418F8B330006B5280 /* SOSTransportCircleKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCircleKVS.h; sourceTree = "<group>"; };
                CD32777618F8B39B006B5280 /* SOSTransportMessageKVS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportMessageKVS.c; sourceTree = "<group>"; };
                CD32777818F8B3B4006B5280 /* SOSTransportMessageKVS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportMessageKVS.h; sourceTree = "<group>"; };
+               CD35B8291C2650FE00E0852A /* secd-154-engine-backoff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-154-engine-backoff.c"; sourceTree = "<group>"; };
                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 = "<group>"; };
                CD5D34011A80391B00EBF353 /* IDSProxy.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = IDSProxy.h; sourceTree = "<group>"; };
                CDC0DC391AE83E390020BA6C /* SOSRingUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingUtils.h; sourceTree = "<group>"; };
                CDC0DC3A1AE83E390020BA6C /* SOSRingV0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSRingV0.c; sourceTree = "<group>"; };
                CDC0DC3B1AE83E390020BA6C /* SOSRingV0.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSRingV0.h; sourceTree = "<group>"; };
-               CDC0DC3C1AE83E390020BA6C /* SOSTransportCoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSTransportCoder.c; sourceTree = "<group>"; };
-               CDC0DC3D1AE83E390020BA6C /* SOSTransportCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransportCoder.h; sourceTree = "<group>"; };
                CDC0DC941AE842640020BA6C /* SOSAccountRings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountRings.c; sourceTree = "<group>"; };
                CDC0DC951AE842640020BA6C /* SOSAccountRingUpdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSAccountRingUpdate.c; sourceTree = "<group>"; };
                CDC0DC961AE842640020BA6C /* SOSCircleV2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSCircleV2.c; sourceTree = "<group>"; };
                CDF1B82218BD7DDE006309BC /* SOSTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSTransport.h; sourceTree = "<group>"; };
                CDF42C061A884BB10080BB05 /* idksmain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = idksmain.m; sourceTree = "<group>"; };
                CDF9BBE01B03E24D00D1AF0F /* secd-52-offering-gencount-reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-52-offering-gencount-reset.c"; sourceTree = "<group>"; };
+               D40294A71C20A806008CE4B6 /* si-91-sectrust-ast2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-91-sectrust-ast2.c"; sourceTree = "<group>"; };
+               D40294A81C20A806008CE4B6 /* si-91-sectrust-ast2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-91-sectrust-ast2.h"; sourceTree = "<group>"; };
                D4273AA21B5D54CA0007D67B /* nameconstraints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nameconstraints.c; sourceTree = "<group>"; };
                D4273AA31B5D54CA0007D67B /* nameconstraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nameconstraints.h; sourceTree = "<group>"; };
                D445CDDF1B44D372005040AC /* si-84-sectrust-atv-appsigning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-84-sectrust-atv-appsigning.c"; sourceTree = "<group>"; };
                D4B4A9A61B8801960097B393 /* si-85-sectrust-ssl-policy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-85-sectrust-ssl-policy.c"; sourceTree = "<group>"; };
+               D4CBC1461BE9A89E00C5795E /* si-89-cms-hash-agility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-89-cms-hash-agility.c"; sourceTree = "<group>"; };
+               D4CBC1471BE9A89E00C5795E /* si-89-cms-hash-agility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-89-cms-hash-agility.h"; sourceTree = "<group>"; };
                D4DFC9481B9958D00040945C /* si-87-sectrust-name-constraints.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-87-sectrust-name-constraints.c"; sourceTree = "<group>"; };
                D4DFC9491B9958D00040945C /* si-87-sectrust-name-constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "si-87-sectrust-name-constraints.h"; sourceTree = "<group>"; };
                E702E75614E1F3EA00CDE635 /* libSecureObjectSync.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSecureObjectSync.a; sourceTree = BUILT_PRODUCTS_DIR; };
                E777C72515B87544004044A8 /* SOSPeerInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfo.c; sourceTree = "<group>"; };
                E777C72815B9C9F0004044A8 /* sc-30-peerinfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-30-peerinfo.c"; sourceTree = "<group>"; };
                E7850ECE1BB30E6E002A54CA /* secd-65-account-retirement-reset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-65-account-retirement-reset.c"; sourceTree = "<group>"; };
-               E790C0F4169E3D7200E0C0C9 /* SOSCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOSCommands.h; sourceTree = "<group>"; };
+               E790C0F4169E3D7200E0C0C9 /* keychain_sync.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychain_sync.h; sourceTree = "<group>"; };
                E790C108169E4E7900E0C0C9 /* builtin_commands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = builtin_commands.h; sourceTree = "<group>"; };
                E790C109169E4FD200E0C0C9 /* digest_calc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = digest_calc.c; sourceTree = "<group>"; };
                E790C10E169E53DF00E0C0C9 /* leaks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = leaks.c; sourceTree = "<group>"; };
                E7DBB6081AEAAF3700488C1F /* SOSPeerInfoDER.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SOSPeerInfoDER.c; sourceTree = "<group>"; };
                E7DBB6091AEAAF3700488C1F /* SOSPeerInfoDER.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SOSPeerInfoDER.h; sourceTree = "<group>"; };
                E7EBD75619145D6400D0F062 /* so_01_serverencryption.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = so_01_serverencryption.c; sourceTree = "<group>"; };
+               E7EF51911C24C6E3002D0C23 /* si-17-item-system-bluetooth.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "si-17-item-system-bluetooth.m"; sourceTree = "<group>"; };
                E7F0D3E9177BBE35001ACBC1 /* secd-55-account-incompatibility.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-55-account-incompatibility.c"; sourceTree = "<group>"; };
                E7F18554177A44E000177B23 /* secd-60-account-cloud-identity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-60-account-cloud-identity.c"; sourceTree = "<group>"; };
                E7F18556177A502900177B23 /* secd-56-account-apply.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "secd-56-account-apply.c"; sourceTree = "<group>"; };
                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 = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.c; };
+               EB3409AE1C1D5BB300D77661 /* secd-20-keychain_upgrade.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-20-keychain_upgrade.m"; sourceTree = "<group>"; };
+               EB69AB031BF3C42F00913AF1 /* SecEMCS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecEMCS.m; sourceTree = "<group>"; };
+               EB69AB051BF425F300913AF1 /* si-90-emcs.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-90-emcs.m"; sourceTree = "<group>"; };
+               EB69AB081BF4335100913AF1 /* SecEMCSPriv.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecEMCSPriv.h; sourceTree = "<group>"; };
                EB8F48DC1AE4C81400CE93A7 /* si-25-sectrust-apple-authentication.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "si-25-sectrust-apple-authentication.c"; sourceTree = "<group>"; };
                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 = "<group>"; };
+               EB9C1D091BDDBDD500F89272 /* si-13-item-system.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "si-13-item-system.m"; sourceTree = "<group>"; };
+               EBC1B8B61BE96B3200E6ACA6 /* whoami.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = whoami.m; sourceTree = "<group>"; };
                EBDAECBA184D30C3005A18F1 /* sc-31-peerinfo-simplefuzz.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "sc-31-peerinfo-simplefuzz.c"; sourceTree = "<group>"; };
+               EBE32B581BEEC8C900719AA8 /* syncbubble.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = syncbubble.m; sourceTree = "<group>"; };
+               EBE32B9B1BF00DA500719AA8 /* entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = entitlements.plist; sourceTree = "<group>"; };
+               EBF2D7651C1E4823006AB6FF /* secd-21-transmogrify.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "secd-21-transmogrify.m"; sourceTree = "<group>"; };
                F697632118F6CC3F0090438B /* keychain_util.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = keychain_util.c; sourceTree = "<group>"; };
                F697632218F6CC3F0090438B /* keychain_util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keychain_util.h; sourceTree = "<group>"; };
                F953A6A71B43538A006EC5E1 /* si-81-sectrust-appletv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "si-81-sectrust-appletv.c"; sourceTree = "<group>"; };
                                18AD562C14CB6EB9008233F2 /* SecECKey.c */,
                                18AD562D14CB6EB9008233F2 /* SecECKey.h */,
                                E757D42219254B3200AF22D9 /* SecECKeyPriv.h */,
+                               EB69AB031BF3C42F00913AF1 /* SecEMCS.m */,
+                               EB69AB081BF4335100913AF1 /* SecEMCSPriv.h */,
                                18AD562E14CB6EB9008233F2 /* SecFramework.c */,
                                18AD562014CB6EB9008233F2 /* SecCertificate.c */,
                                18AD562F14CB6EB9008233F2 /* SecFramework.h */,
                                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 */,
                                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;
                                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 */,
                                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 */,
                                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 */,
                        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 */,
                                E7B01B5A16532507000485F1 /* SOSCloudCircleInternal.h */,
                                4BD2F7FB1ADCDD8C0037CD5D /* SOSForerunnerSession.c */,
                                4BD2F7FC1ADCDD8C0037CD5D /* SOSForerunnerSession.h */,
+                               48E9CDFB1C597FED00574D6B /* SOSSysdiagnose.c */,
                                E777C71D15B73F9E004044A8 /* SOSInternal.c */,
                                E777C71B15B73F59004044A8 /* SOSInternal.h */,
                                52F8DE4A1AF2E9AE00A2C271 /* SOSTypes.h */,
                                4CC929B215A3957800C6D578 /* SOSPeer.h */,
                                CD32776A18F8AEFD006B5280 /* SOSPeerCoder.c */,
                                CD32776C18F8B06E006B5280 /* SOSPeerCoder.h */,
-                               4CB292D81A9E881C003598A1 /* SOSViewManager.c */,
-                               4CB292D91A9E881C003598A1 /* SOSViewManager.h */,
-                               52A126D31AAF6C86006AC7CB /* SOSViewQueries.c */,
-                               52A126D41AAF6C86006AC7CB /* SOSViewQueries.h */,
                        );
                        name = Engine;
                        sourceTree = "<group>";
                                CDF1B82218BD7DDE006309BC /* SOSTransport.h */,
                                CD773AC21ADDF8C700C808BA /* SOSTransportBackupPeer.c */,
                                CD773AC31ADDF8C700C808BA /* SOSTransportBackupPeer.h */,
-                               CDC0DC3C1AE83E390020BA6C /* SOSTransportCoder.c */,
-                               CDC0DC3D1AE83E390020BA6C /* SOSTransportCoder.h */,
                                CD0F8AF51899BF46003E0C52 /* SOSTransportCircle.c */,
                                CD0F8AF91899BF63003E0C52 /* SOSTransportCircle.h */,
                                CD32777218F8B31E006B5280 /* SOSTransportCircleKVS.c */,
                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 = "<group>";
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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 */,
                                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;
                                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 */,
                                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 */,
                        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;
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               48279BC51C57FEA20043457C /* keychain_log.c in Sources */,
                                E7FEFB91169E36D800E18152 /* keychain_sync.c in Sources */,
+                               48FEA77C1C53000A0020C148 /* secToolFileIO.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 00e76b09f8a58f68cfbd75be446fb340e1d7c0c3..0591aac1dd755c86e1b9eb3aa3fac700b2dff614 100644 (file)
@@ -27,6 +27,8 @@
 #include <test/testmore.h>
 #include <utilities/SecFileLocations.h>
 #include <utilities/SecCFWrappers.h>
+#include <securityd/SecItemServer.h>
+
 
 #include <CoreFoundation/CoreFoundation.h>
 
@@ -35,9 +37,7 @@
 #include <unistd.h>
 #include <sys/stat.h>
 
-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);
 }
index f3e70f9aadb828d0fbecaed144c80262c58417e2..cb25fe2fa49337a14c627c3293753226183c0b10 100644 (file)
@@ -37,7 +37,6 @@
 
 #if USE_KEYSTORE
 #include <libaks.h>
-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.c
deleted file mode 100644 (file)
index 21b9e7a..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-
-#include "secd_regressions.h"
-
-#include <securityd/SecDbItem.h>
-#include <utilities/array_size.h>
-#include <utilities/SecCFWrappers.h>
-#include <utilities/SecFileLocations.h>
-#include <utilities/fileIo.h>
-
-#include <securityd/SOSCloudCircleServer.h>
-#include <securityd/SecItemServer.h>
-
-#include <Security/SecBasePriv.h>
-
-#include <AssertMacros.h>
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <pthread.h>
-
-#include "SecdTestKeychainUtilities.h"
-
-#define N_ITEMS (100)
-#define N_THREADS (10)
-#define N_ADDS (20)
-
-static void *do_add(void *arg)
-{
-    int tid=(int)(arg);
-
-    for(int i=0;i<N_ADDS;i++) {
-        /* Creating a password */
-        SInt32 v_eighty = (tid+1)*1000+i;
-        CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty);
-        const char *v_data = "test";
-        CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data));
-        const void *keys[] = {
-            kSecClass,
-            kSecAttrServer,
-            kSecAttrAccount,
-            kSecAttrPort,
-            kSecAttrProtocol,
-            kSecAttrAuthenticationType,
-            kSecValueData
-        };
-        const void *values[] = {
-            kSecClassInternetPassword,
-            CFSTR("members.spamcop.net"),
-            CFSTR("smith"),
-            eighty,
-            CFSTR("http"),
-            CFSTR("dflt"),
-            pwdata
-        };
-
-        CFDictionaryRef item = CFDictionaryCreate(NULL, keys, values,
-                                                  array_size(keys), NULL, NULL);
-
-        ok_status(SecItemAdd(item, NULL), "add internet password");
-        CFReleaseNull(eighty);
-        CFReleaseNull(pwdata);
-        CFReleaseNull(item);
-    }
-
-    return NULL;
-}
-
-
-int secd_05_corrupted_items(int argc, char *const *argv)
-{
-    plan_tests(1 + N_THREADS*(N_ADDS+1) + N_ITEMS*4 + kSecdTestSetupTestCount);
-    
-    /* custom keychain dir */
-    secd_test_setup_temp_keychain("secd_05_corrupted_items", NULL);
-
-    /* add a password */
-    const char *v_data = "test";
-    CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data));
-    CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
-    CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
-    CFDictionaryAddValue(query, kSecAttrServer, CFSTR("corrupt.spamcop.net"));
-    CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith"));
-    CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP);
-    CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault);
-    CFDictionaryAddValue(query, kSecValueData, pwdata);
-
-    SInt32 i;
-    for(i=1; i<=N_ITEMS; i++) {
-        CFNumberRef port = CFNumberCreate(NULL, kCFNumberSInt32Type, &i);
-        CFDictionarySetValue(query, kSecAttrPort, port);
-        ok_status(SecItemAdd(query, NULL), "add internet password");
-        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 */
-        sqlite3 *db;
-
-        is(sqlite3_open(keychain_path, &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");
-        }
-    });
-
-    /* start the adder threads */
-    pthread_t add_thread[N_THREADS];
-    void *add_err[N_THREADS] = {NULL,};
-
-    for(int i=0; i<N_THREADS; i++)
-        pthread_create(&add_thread[i], NULL, do_add, (void*)(intptr_t)i);
-
-    /* query the corrupted items */
-    CFDictionaryAddValue(query, kSecReturnPersistentRef, kCFBooleanTrue);
-    for(int i=1;i<=N_ITEMS;i++) {
-        CFTypeRef ref = NULL;
-        CFNumberRef port = CFNumberCreate(NULL, kCFNumberSInt32Type, &i);
-        CFDictionarySetValue(query, kSecAttrPort, port);
-        is_status(SecItemCopyMatching(query, &ref), errSecItemNotFound, "Item not found");
-        CFReleaseNull(port);
-        CFReleaseNull(ref);
-    }
-
-    /* collect the adder threads */
-    for(int i=0; i<N_THREADS; i++)
-        pthread_join(add_thread[i], &add_err[i]);
-
-    for(int i=0; i<N_THREADS; i++)
-        ok(add_err[i]==NULL, "add thread");
-
-    CFReleaseNull(pwdata);
-    CFReleaseNull(query);
-    CFReleaseNull(keychain_path_cf);
-    return 0;
-}
diff --git a/OSX/sec/securityd/Regressions/secd-05-corrupted-items.m b/OSX/sec/securityd/Regressions/secd-05-corrupted-items.m
new file mode 100644 (file)
index 0000000..b9427af
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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@
+ */
+
+/*
+ * 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 "secd_regressions.h"
+
+#import <Foundation/Foundation.h>
+#import <securityd/SecDbItem.h>
+#import <utilities/array_size.h>
+#import <utilities/SecCFWrappers.h>
+#import <utilities/SecFileLocations.h>
+#import <utilities/fileIo.h>
+
+#import <securityd/SOSCloudCircleServer.h>
+#import <securityd/SecItemServer.h>
+
+#import <Security/SecBasePriv.h>
+
+#import <AssertMacros.h>
+
+#import <stdio.h>
+#import <unistd.h>
+#import <sys/stat.h>
+#import <pthread.h>
+
+#import "SecdTestKeychainUtilities.h"
+
+#define N_ITEMS (100)
+#define N_THREADS (10)
+#define N_ADDS (20)
+
+static void *do_add(void *arg)
+{
+    int tid=(int)(arg);
+
+    for(int i=0;i<N_ADDS;i++) {
+        /* Creating a password */
+        SInt32 v_eighty = (tid+1)*1000+i;
+        CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty);
+        const char *v_data = "test";
+        CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data));
+        const void *keys[] = {
+            kSecClass,
+            kSecAttrServer,
+            kSecAttrAccount,
+            kSecAttrPort,
+            kSecAttrProtocol,
+            kSecAttrAuthenticationType,
+            kSecValueData
+        };
+        const void *values[] = {
+            kSecClassInternetPassword,
+            CFSTR("members.spamcop.net"),
+            CFSTR("smith"),
+            eighty,
+            CFSTR("http"),
+            CFSTR("dflt"),
+            pwdata
+        };
+
+        CFDictionaryRef item = CFDictionaryCreate(NULL, keys, values,
+                                                  array_size(keys), NULL, NULL);
+
+        ok_status(SecItemAdd(item, NULL), "add internet password");
+        CFReleaseNull(eighty);
+        CFReleaseNull(pwdata);
+        CFReleaseNull(item);
+    }
+
+    return NULL;
+}
+
+
+int secd_05_corrupted_items(int argc, char *const *argv)
+{
+    plan_tests(1 + N_THREADS*(N_ADDS+1) + N_ITEMS*4 + kSecdTestSetupTestCount);
+    
+    /* custom keychain dir */
+    secd_test_setup_temp_keychain("secd_05_corrupted_items", NULL);
+
+    /* add a password */
+    const char *v_data = "test";
+    CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data));
+    CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
+    CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
+    CFDictionaryAddValue(query, kSecAttrServer, CFSTR("corrupt.spamcop.net"));
+    CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith"));
+    CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP);
+    CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault);
+    CFDictionaryAddValue(query, kSecValueData, pwdata);
+
+    SInt32 i;
+    for(i=1; i<=N_ITEMS; i++) {
+        CFNumberRef port = CFNumberCreate(NULL, kCFNumberSInt32Type, &i);
+        CFDictionarySetValue(query, kSecAttrPort, port);
+        ok_status(SecItemAdd(query, NULL), "add internet password");
+        CFReleaseNull(port);
+    }
+
+
+
+    SecKeychainDbReset(^{
+        /* corrupt all the password */
+        NSString *keychain_path = [(NSString *)__SecKeychainCopyPath() autorelease];
+        char corrupt_item_sql[80];
+        sqlite3 *db;
+
+        is(sqlite3_open([keychain_path UTF8String], &db), SQLITE_OK, "open keychain");
+
+        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");
+        }
+    });
+
+    /* start the adder threads */
+    pthread_t add_thread[N_THREADS];
+    void *add_err[N_THREADS] = {NULL,};
+
+    for(int i=0; i<N_THREADS; i++)
+        pthread_create(&add_thread[i], NULL, do_add, (void*)(intptr_t)i);
+
+    /* query the corrupted items */
+    CFDictionaryAddValue(query, kSecReturnPersistentRef, kCFBooleanTrue);
+    for(int i=1;i<=N_ITEMS;i++) {
+        CFTypeRef ref = NULL;
+        CFNumberRef port = CFNumberCreate(NULL, kCFNumberSInt32Type, &i);
+        CFDictionarySetValue(query, kSecAttrPort, port);
+        is_status(SecItemCopyMatching(query, &ref), errSecItemNotFound, "Item not found");
+        CFReleaseNull(port);
+        CFReleaseNull(ref);
+    }
+
+    /* collect the adder threads */
+    for(int i=0; i<N_THREADS; i++)
+        pthread_join(add_thread[i], &add_err[i]);
+
+    for(int i=0; i<N_THREADS; i++)
+        ok(add_err[i]==NULL, "add thread");
+
+    CFReleaseNull(pwdata);
+    CFReleaseNull(query);
+    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 (file)
index 0000000..e75660d
--- /dev/null
@@ -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 <utilities/SecCFWrappers.h>
+
+#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, &current_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 (file)
index 0000000..c33d990
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <Security/SecBase.h>
+#import <Security/SecItem.h>
+#import <Security/SecItemPriv.h>
+#import <Security/SecInternal.h>
+#import <utilities/SecCFWrappers.h>
+#import <utilities/SecFileLocations.h>
+#import <securityd/SecItemServer.h>
+
+#import <stdlib.h>
+
+#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 (file)
index 0000000..97bc756
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <Security/SecBase.h>
+#import <Security/SecItem.h>
+#import <Security/SecItemPriv.h>
+#import <Security/SecInternal.h>
+#import <utilities/SecCFWrappers.h>
+#import <utilities/SecFileLocations.h>
+#import <securityd/SecItemServer.h>
+
+#import <stdlib.h>
+
+#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;
+}
index 794e2aceaefb006f894d00d77a909b7801581795..c153b4cde597bcddcc2cc271f0b6ccf3071b1d1b 100644 (file)
@@ -40,6 +40,7 @@
 #include <libaks_acl_cf_keys.h>
 
 #include <ctkclient_test.h>
+#include <coreauthd_spi.h>
 
 #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) {
index b8d49c89788a203e84ccb9ced9bb4ee0df6a26b9..31f8c3451578f0ecc4c403c535f80ed5dc007554 100644 (file)
@@ -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);
index 72b643dbbe0220c06cff6af59dcf9f3ca33004d4..50cae95ef5907f7f8bba76002469f42183dbaf58 100644 (file)
@@ -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);
index a56bf4945df20610ffcb6e5e2d7b37b676a7f221..58046edb926cea00ce6c344641736010399e563d 100644 (file)
@@ -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
index 80b9c85e3a18d65533f17c73f47e7cd1c2afb051..2d3bfcf9a200000a77424680299932dd58bda101 100644 (file)
@@ -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");
 
index 87bd8e1541734fb7b00d1f8c89254edddaeefe54..2e0ad63859be00c9cd04e467f904c6f7337f9556 100644 (file)
@@ -32,7 +32,6 @@
 #include <MobileKeyBag/MobileKeyBag.h>
 #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
 
index eb0efa3c7bdab667677861b2fc247bcf41c49582..b5c256b3f5e5914cb4171d6aacf57218e3af2f15 100644 (file)
@@ -33,7 +33,7 @@
 #include <MobileKeyBag/MobileKeyBag.h>
 #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 (file)
index 0000000..a23cae5
--- /dev/null
@@ -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 <Security/SecBase.h>
+#include <Security/SecItem.h>
+
+#include <CoreFoundation/CFDictionary.h>
+
+#include <Security/SecureObjectSync/SOSAccount.h>
+#include <Security/SecureObjectSync/SOSPeerInfoPriv.h>
+#include <Security/SecureObjectSync/SOSCloudCircle.h>
+#include <Security/SecureObjectSync/SOSInternal.h>
+#include <Security/SecureObjectSync/SOSUserKeygen.h>
+#include <Security/SecureObjectSync/SOSTransport.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "secd_regressions.h"
+#include "SOSTestDataSource.h"
+
+#include "SOSRegressionUtilities.h"
+#include <utilities/SecCFWrappers.h>
+#include <Security/SecKeyPriv.h>
+
+#include <securityd/SOSCloudCircleServer.h>
+
+#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;
+}
index b4ca0f1e657ad77ffc7b7534c0cf44f315e13408..9f6d66cb0536e005d92f0bd49bb055a9b012659d 100644 (file)
@@ -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)
+
index fbba54506b6ff5b57da4dbba7bd38ae49b725f8c..2647456d1e7f51c8f6151cd759ea7815e6e4ed83 100644 (file)
@@ -68,6 +68,8 @@
 #include <TargetConditionals.h>
 
 #include <utilities/iCloudKeychainTrace.h>
+#include <Security/SecAccessControlPriv.h>
+#include <securityd/SecDbKeychainItem.h>
 
 #if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR
 #include <MobileGestalt.h>
@@ -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;
 
index 2f6631b2a4e11928c63a87299b55ce27df1e47bb..b035524222db54834c2f4f51d0e0f3068f7bd535 100644 (file)
@@ -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);
 
 
 //
index a18a20027d43d604140b5066833a04b5bc4dd655..265aefda8c493fa1f3d38cefabe95e6cfce1b0d2 100644 (file)
@@ -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;
                 }
             }
index c42735e7fc7494447cfb957e2a3dc70660fd107a..6f4565f5f84f8b1e23fff0574b33e2a4076856a4 100644 (file)
@@ -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;
index f7e46130e10a6776bdc6eed340dc466d725aab4d..f0df92ac0f14e2b109667841ff0c3503c63160da 100644 (file)
@@ -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
index 88959c4a7e347563a99b73697bef8666e27f2b7d..d3304a6e3c5d6b52c76dfd22c3ca120651a2f5be 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
  *
 #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)) {
index 9bad114ff9a9c824fa86f009b594ccc8ae166f4b..2a7f84747a203e8954612f88c9ea8ab47227340b 100644 (file)
@@ -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
 
index 9eb50a70ea783bb9a6c9dfb1f5005f2444ddb052..0bdc8d8a9cbe41c02bc03d08f9ed14f0596283d5 100644 (file)
@@ -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;
index b116e3aa4591215f6f941c3006ce03495eeb69e8..9a4f866723f4ad27458349c1d43acc3fc72e5951 100644 (file)
@@ -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, &param, error);
+    }
+
     /* Bind the access group to the sql. */
     if (result) {
         result = sqlBindAccessGroups(stmt, accessGroups, &param, 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);
index 0d9b52ce69620a5e02af7decccf57fa205956bdf..86ed675e89131bdc96e266c436d9fa91aebf8120 100644 (file)
@@ -29,6 +29,7 @@
 #define _SECURITYD_SECITEMDB_H_
 
 #include <securityd/SecDbQuery.h>
+#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
 
index 8fb944055d44d5208c0b962ab08ed9bbcb8ac364..644091b42b9975fc46f5c9a2c8f44aa86218b55c 100644 (file)
@@ -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
 //                                                        / / / / / / / / / / / ,--- 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,
index 523fc96fc29cc0996a45cf8a5674afcb266e9a32..d79fff37e24508a4f2d4711698a369cfc7e04b16 100644 (file)
@@ -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
index 09e4287a7cfb1002fd8b30571ee131634ee063d8..86448f4f7d3131cea25b13309c75968e338a9861 100644 (file)
 // TODO: Make this include work on both platforms. rdar://problem/16526848
 #if TARGET_OS_EMBEDDED
 #include <Security/SecEntitlements.h>
+#include <MobileKeyBag/MobileKeyBag.h>
 #else
 /* defines from <Security/SecEntitlements.h> */
 #define kSecEntitlementAssociatedDomains CFSTR("com.apple.developer.associated-domains")
 #define kSecEntitlementPrivateAssociatedDomains CFSTR("com.apple.private.associated-domains")
 #endif
 
+#if TARGET_OS_EMBEDDED
+#include <AggregateDictionary/ADClient.h>
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
 #include <utilities/array_size.h>
 #include <utilities/SecFileLocations.h>
+#include <utilities/SecTrace.h>
 #include <Security/SecuritydXPC.h>
 #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;
index de9f4a1986388265f07763265eee9e48719117d4..4bc57b9494f5bb3d970b02900a6bb3d76dd120b4 100644 (file)
 #include <Security/SecureObjectSync/SOSCircle.h>
 #include <securityd/SecDbQuery.h>
 #include <utilities/SecDb.h>
+#include <TargetConditionals.h>
+#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;
index 6a48f4ac533c4ac498f1e2db7f6778459ab6b63b..e22897b7d0e9168dd18699500ceebbec70609ef4 100644 (file)
@@ -43,6 +43,9 @@
 #endif
 #endif /* USE_KEYSTORE */
 
+#include <CommonCrypto/CommonCryptor.h>
+#include <CommonCrypto/CommonCryptorSPI.h>
+
 
 /* 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;
 }
+
index cfcc825d4f7946210403efd91a3ffe4af6962c0d..46257024951597fc223169f38b24f507d7b9ac08 100644 (file)
@@ -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);
     }
 
index 5a135130325d31f76484f347396caedf28e473aa..e3e17cb64ab240890551c6c39d0fc45a477c0b5a 100644 (file)
@@ -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);
index 5b29ab98aba16e6a89089771308e0fd2a9bc42f7..a88a34584d278c938c7c7b3cac70f1487aded947 100644 (file)
@@ -18,5 +18,7 @@
        <true/>
        <key>com.apple.private.network.socket-delegate</key>
        <true/>
+       <key>com.apple.mkb.usersession.info</key>
+       <true/>
 </dict>
 </plist>
index 363aaff354846d43b9232c70b547ba4400ddbe6e..8a19f191b30d833482d42c7d673a3c591758d059 100644 (file)
 #include <pwd.h>
 #endif
 #include <utilities/SecCFWrappers.h>
+#include <utilities/SecTrace.h>
 
 
-/* --------------------------------------------------------------------------
-       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);
index 25abfd70309e2b8315002d417bda886a8090ec35..4acf2b6e5b8ece09f8203e170dd15193c2454baa 100644 (file)
@@ -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) {
index 753bee02b2a0658c379ae8138f16fd3fef138849..dd8eb5fb25a354329360bd7a81ebd6af56470c7d 100644 (file)
@@ -12,6 +12,8 @@
        <true/>
        <key>migrate-keychain</key>
        <true/>
+       <key>com.apple.private.system-keychain</key>
+       <true/>
        <key>modify-anchor-certificates</key>
        <true/>
        <key>com.apple.springboard.wipedevice</key>
index 26ae9f35314a65ed2f4f1f7df5e934e1ccf0f2a5..2561235fa45a3cb640c0a0eea3261fd95a4eaa55 100644 (file)
@@ -3,5 +3,6 @@
 #include <libsecurity_keychain/regressions/keychain_regressions.h>
 #include <Breadcrumb/breadcrumb_regressions.h>
 #include <libsecurity_smime/regressions/smime_regressions.h>
+#include <libsecurity_cms/regressions/cms_regressions.h>
 
 
index e018521e395e8d086cabd59e4d9b43ab95ea88a8..36fbe7b5cb5be1c579e05debbdcecf4932af9f5c 100644 (file)
@@ -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"
index 27f409fb326ad0b664abafeb15a6e2b45597fe69..a31995e04daf7d532f10fee86db9baef7cb11ba3 100644 (file)
@@ -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);
index 7e01dfc662fd9eecaa426105eb148d5c1260536b..78ad8e3ab19feba9cc96e8f69c6c2a2848d1e791 100644 (file)
@@ -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);
index 83bed63d9f95ab3764b033847e72e877cbaf44e7..77d2ea91f2e2f46152547d512b50d46e489a0020 100644 (file)
 #  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 */
 }
 
index fd855ce302681303d1570a33ce08a78e9b0e4f90..b4a7ad2388116a89f9561098f0bd8523c81ce225 100644 (file)
@@ -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
index 1a83d100f09611922e8fe5cfe4f3c6d75076bdc7..6384e9fdfe0e6ccdf2877f8b6347fb592fd52ea6 100644 (file)
@@ -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);
index e87fa0bc91d86c4b890daa2837756f4a970e701a..f8c5a4adf498420782d1386ddabb00514f6d3831 100644 (file)
@@ -15,6 +15,7 @@ __BEGIN_DECLS
 
 typedef CF_OPTIONS(uint32_t, SecAppleTrustAnchorFlags) {
     kSecAppleTrustAnchorFlagsIncludeTestAnchors    = 1 << 0,
+    kSecAppleTrustAnchorFlagsAllowNonProduction    = 1 << 1,
 };
 
 /*
index 76d6369a9cd999388fda81117dfa0a3d0e6efecc..8ea52f9d3a268c0dde84c831faafc89c946d8b79 100644 (file)
@@ -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);
+
 }
 
 
index fa6b78e89029151a667df8a3bbb14faf8411b35c..cefa055d24a21c1201868688446e7ad4f5ba135e 100644 (file)
@@ -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 (file)
index 0000000..0acd1e3
--- /dev/null
@@ -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 (file)
index 0000000..de8e368
--- /dev/null
@@ -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 <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+int64_t     SecBucket1Significant(int64_t);
+int64_t     SecBucket2Significant(int64_t);
+
+__END_DECLS
+
+
+#endif /* SecTrace_h */
index e27d6c60ebb0ff545d7cc639f52b296af36c10df..e7302d03770ba865eaa2d6c0b880f8fb4770d1f8 100644 (file)
@@ -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() {
     
index 579a0e068979f0d15e190b4c7c50b9f43c775125..36629478c2df3e9e8f0399db8eedff63260c2125 100644 (file)
 
 #include <CoreFoundation/CoreFoundation.h>
 
+#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
index e0ec9aff00b70ccc20e52d8bd6d853c6014c9e4c..a069e601c95fac8c196eaec1209d4ee3a4767704 100644 (file)
@@ -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 */; };
                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 = "<group>"; };
                E7FC081B161A3038008E0760 /* SecIOFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecIOFormat.h; sourceTree = "<group>"; };
+               EB0BC8F11C3C6E8E00785842 /* SecTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecTrace.c; sourceTree = "<group>"; };
+               EB0BC8F21C3C6E8E00785842 /* SecTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecTrace.h; sourceTree = "<group>"; };
                EB71938E1B0258890066F5E2 /* SecAppleAnchor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecAppleAnchor.c; sourceTree = "<group>"; };
                EB71938F1B0258890066F5E2 /* SecAppleAnchorPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecAppleAnchorPriv.h; sourceTree = "<group>"; };
                EB7193921B02606A0066F5E2 /* SecInternalRelease.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SecInternalRelease.c; sourceTree = "<group>"; };
                                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 */,
                                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 = "<group>";
                                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 */,
                                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 */,
index 62d645eaac993018dd0dc31e6c6119d3754d260d..eee3ecff8ab787da48c5d9dc8eb28c308190b02f 100644 (file)
@@ -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 (file)
index 0000000..b2eb369
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Project</key>
+       <string>Security</string>
+       <key>TestSpecificLogs</key>
+       <array>
+               <string>/var/log/system.log</string>
+               <string>/var/log/module/com.apple.securityd/.*</string>
+               <string>/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/.*security.log.*</string>
+       </array>
+       <key>Tests</key>
+       <array>
+               <dict>
+                       <key>TestName</key>
+                       <string>BackupNegativeTest</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/AppleInternal/CoreOS/tests/Security/secbackupntest</string>
+                       </array>
+               </dict>
+               <dict>
+                       <key>TestName</key>
+                       <string>BackupTest</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/AppleInternal/CoreOS/tests/Security/secbackuptest</string>
+                       </array>
+               </dict>
+               <dict>
+                       <key>TestName</key>
+                       <string>EduModeTest</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/AppleInternal/CoreOS/tests/Security/secedumodetest</string>
+                       </array>
+               </dict>
+               <dict>
+                       <key>TestName</key>
+                       <string>secd_02_upgrade_while_locked</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/usr/local/bin/secdtests</string>
+                               <string>-1</string>
+                               <string>secd_02_upgrade_while_locked </string>
+                       </array>
+               </dict>
+               <dict>
+                       <key>TestName</key>
+                       <string>secd_35_keychain_migrate_inet</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/usr/local/bin/secdtests</string>
+                               <string>-1</string>
+                               <string>secd_35_keychain_migrate_inet</string>
+                       </array>
+               </dict>
+       </array>
+</dict>
+</plist>
diff --git a/RegressionTests/Security_edumode.plist b/RegressionTests/Security_edumode.plist
new file mode 100644 (file)
index 0000000..32e19d8
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>Project</key>
+       <string>Security</string>
+       <key>TestSpecificLogs</key>
+       <array>
+               <string>/var/log/system.log</string>
+               <string>/var/log/module/com.apple.securityd/.*</string>
+               <string>/var/mobile/Library/Logs/CrashReporter/DiagnosticLogs/.*security.log.*</string>
+       </array>
+       <key>Tests</key>
+       <array>
+               <dict>
+                       <key>TestName</key>
+                       <string>BackupNegativeTest</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/AppleInternal/CoreOS/tests/Security/secbackupntest</string>
+                       </array>
+               </dict>
+               <dict>
+                       <key>TestName</key>
+                       <string>si_13_item_system</string>
+                       <key>Command</key>
+                       <array>
+                               <string>/AppleInternal/Applications/SecurityTests.app/SecurityTests</string>
+                               <string>-1</string>
+                               <string>si_13_item_system</string>
+                       </array>
+               </dict>
+       </array>
+</dict>
+</plist>
diff --git a/RegressionTests/secbackupntest/secbackupntest.m b/RegressionTests/secbackupntest/secbackupntest.m
new file mode 100644 (file)
index 0000000..1fc5ecc
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#include <Security/Security.h>
+
+#include <TargetConditionals.h>
+
+#include <Security/SecItemPriv.h>
+#include <err.h>
+
+#if !TARGET_OS_SIMULATOR
+#include <libaks.h>
+
+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 (file)
index 0000000..3776f05
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>com.apple.private.security.no-sandbox</key>
+       <true/>
+       <key>restore-keychain</key>
+       <true/>
+       <key>migrate-keychain</key>
+       <true/>
+       <key>application-identifier</key>
+       <string>com.apple.security.secbackuptest</string>
+</dict>
+</plist>
diff --git a/RegressionTests/secbackuptest/secbackuptest.m b/RegressionTests/secbackuptest/secbackuptest.m
new file mode 100644 (file)
index 0000000..962cb28
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#include <Security/Security.h>
+
+#include <TargetConditionals.h>
+
+#include <Security/SecItemPriv.h>
+#include <sys/stat.h>
+#include <err.h>
+
+#if TARGET_OS_SIMULATOR
+int
+main(void)
+{
+    return 0;
+}
+#else
+
+#include <libaks.h>
+
+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 (file)
index 0000000..f206045
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>com.apple.developer.networking.networkextension</key>
+       <true/>
+       <key>com.apple.private.system-keychain</key>
+       <true/>
+       <key>keychain-access-groups</key>
+       <array>
+               <string>com.apple.vpn-test</string>
+       </array>
+</dict>
+</plist>
diff --git a/RegressionTests/secedumodetest/secedumodetest.m b/RegressionTests/secedumodetest/secedumodetest.m
new file mode 100644 (file)
index 0000000..617a88d
--- /dev/null
@@ -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 <Foundation/Foundation.h>
+#include <Security/Security.h>
+#include <Security/SecItemPriv.h>
+#include <TargetConditionals.h>
+#include <err.h>
+
+
+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;
+    }
+}
+
+
index 3f766e4f1781cc55e24106d3aec242313028dfd1..c1edcc99b82de33f996b4af60276614fff097f3e 100644 (file)
@@ -39,6 +39,7 @@
                                05EF68CA1949167B007958C3 /* PBXTargetDependency */,
                                05EF68C81949166E007958C3 /* PBXTargetDependency */,
                                05EF68C0194915B6007958C3 /* PBXTargetDependency */,
+                               EB93052B1BE1B43700978606 /* PBXTargetDependency */,
                        );
                        name = Security_executables;
                        productName = Security_executables;
                                BE4AC9B418B8020400B84964 /* PBXTargetDependency */,
                                5346481B17331ED800FE9172 /* PBXTargetDependency */,
                                F94E7AE21ACC8E7700F23132 /* PBXTargetDependency */,
+                               EB9C1DB71BDFD51800F89272 /* PBXTargetDependency */,
                        );
                        name = phase2;
                        productName = phase2;
                        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" */;
                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 */
 
                        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 */;
                        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;
                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 = "<group>"; };
+               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 = "<group>"; };
+               EB0BC83E1C3C072C00785842 /* secedumodetest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = secedumodetest.entitlements; path = secedumodetest/secedumodetest.entitlements; sourceTree = "<group>"; };
+               EB3A8DD71BEEC4D6001A89AA /* Security_edumode.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Security_edumode.plist; sourceTree = "<group>"; };
+               EB69AB091BF4347700913AF1 /* SecEMCSPriv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecEMCSPriv.h; sourceTree = "<group>"; };
+               EB9B37A31C646F070027E2F9 /* secbackuptest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = secbackuptest.m; path = secbackuptest/secbackuptest.m; sourceTree = "<group>"; };
+               EB9B37A41C646F5F0027E2F9 /* secbackuptest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = secbackuptest.entitlements; path = secbackuptest/secbackuptest.entitlements; sourceTree = "<group>"; };
+               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 = "<group>"; };
+               EB9C1DAD1BDFD49400F89272 /* Security.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Security.plist; sourceTree = "<group>"; };
                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 = "<group>"; };
                        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 */,
                                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 */,
                                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;
                        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 */,
                        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 */,
                        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 */,
                                4C32C1A60A497A21002891BD /* Security.framework in Frameworks */,
                                4CAE95DC0F3D6E020075278E /* CFNetwork.framework in Frameworks */,
                                4C0CC642174C580200CC799A /* SystemConfiguration.framework in Frameworks */,
+                               EBC1B8E11BE96FE600E6ACA6 /* Foundation.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        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 */,
                        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 */,
                        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 */,
                                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 */,
                        );
                        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 */,
                        );
                        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 */
                                5E10992719A5E55800A60E2B /* ISACLProtectedItems */,
                                5EBE247B1B00CCAE0007DB0E /* secacltests */,
                                4381690E1B4EDCBD00C54D58 /* SOSCCAuthPlugin */,
+                               EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */,
                                E7FCBE401314471B000DE34E /* Frameworks */,
                                4C35DC36094F9120002917C4 /* Products */,
                                4C8BC620097DBC1B00C781D5 /* Libraries */,
                                CD276C271A83F60C003226BC /* IDSKeychainSyncingProxy.bundle */,
                                5EBE247A1B00CCAE0007DB0E /* secacltests */,
                                4381690C1B4EDCBD00C54D58 /* SOSCCAuthPlugin.bundle */,
+                               EB9C1D7A1BDFD0E000F89272 /* secbackupntest */,
+                               EB0BC8151C3C064400785842 /* secedumodetest */,
+                               EB9B37AD1C64705F0027E2F9 /* secbackuptest */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                4AF7FFF715AFB73800B9D400 /* SecOTRMath.h */,
                                4AF7FFF915AFB73800B9D400 /* SecOTRPacketData.h */,
                                4AF7FFFA15AFB73800B9D400 /* SecOTRPackets.h */,
+                               EB69AB091BF4347700913AF1 /* SecEMCSPriv.h */,
                                4AF7FFFB15AFB73800B9D400 /* SecOTRSession.h */,
                                4AF7FFFC15AFB73800B9D400 /* SecOTRSessionPriv.h */,
                                CDDE9BC31729AB910013B0E8 /* SecPasswordGenerate.h */,
                        name = Frameworks;
                        sourceTree = "<group>";
                };
+               EB0BC83C1C3C069500785842 /* secedumodetest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               EB0BC83D1C3C06CA00785842 /* secedumodetest.m */,
+                               EB0BC83E1C3C072C00785842 /* secedumodetest.entitlements */,
+                       );
+                       name = secedumodetest;
+                       sourceTree = "<group>";
+               };
+               EB9B377C1C646ED10027E2F9 /* secbackuptest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               EB9B37A31C646F070027E2F9 /* secbackuptest.m */,
+                               EB9B37A41C646F5F0027E2F9 /* secbackuptest.entitlements */,
+                       );
+                       name = secbackuptest;
+                       sourceTree = "<group>";
+               };
+               EB9C1D7C1BDFD0E100F89272 /* secbackupntest */ = {
+                       isa = PBXGroup;
+                       children = (
+                               EB9C1D7D1BDFD0E100F89272 /* secbackupntest.m */,
+                       );
+                       path = secbackupntest;
+                       sourceTree = "<group>";
+               };
+               EB9C1DAA1BDFD0FE00F89272 /* RegressionTests */ = {
+                       isa = PBXGroup;
+                       children = (
+                               EB9C1DAD1BDFD49400F89272 /* Security.plist */,
+                               EB3A8DD71BEEC4D6001A89AA /* Security_edumode.plist */,
+                               EB9C1D7C1BDFD0E100F89272 /* secbackupntest */,
+                               EB9B377C1C646ED10027E2F9 /* secbackuptest */,
+                               EB0BC83C1C3C069500785842 /* secedumodetest */,
+                       );
+                       path = RegressionTests;
+                       sourceTree = "<group>";
+               };
                F93C49391AB8FF530047E01A /* ckcdiagnose */ = {
                        isa = PBXGroup;
                        children = (
                                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 */,
                        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 */
                                        CD276C261A83F60C003226BC = {
                                                CreatedOnToolsVersion = 7.0;
                                        };
+                                       EB9C1D791BDFD0E000F89272 = {
+                                               CreatedOnToolsVersion = 7.1;
+                                       };
+                                       EB9C1DAE1BDFD4DE00F89272 = {
+                                               CreatedOnToolsVersion = 7.1;
+                                       };
                                        F93C49021AB8FCE00047E01A = {
                                                CreatedOnToolsVersion = 6.3;
                                        };
                                F93C49021AB8FCE00047E01A /* ckcdiagnose.sh */,
                                5EBE24791B00CCAE0007DB0E /* secacltests */,
                                4381690B1B4EDCBD00C54D58 /* SOSCCAuthPlugin */,
+                               EB9C1DAE1BDFD4DE00F89272 /* SecurityBatsTests */,
+                               EB9C1D791BDFD0E000F89272 /* secbackupntest */,
+                               EB0BC80D1C3C064400785842 /* secedumodetest */,
+                               EB9B37A51C64705F0027E2F9 /* secbackuptest */,
                        );
                };
 /* End PBXProject section */
                        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 */
                        );
                        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 */
                        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 */;
                                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;
                                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;
                        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)",
                        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)",
                                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;
                                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 = (
                        };
                        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 = {
                        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 = (
index c32b0529bfc8af28bfa23026659e03774706b16d..dc2d7b05ef655608906939617bd85a075049680d 100644 (file)
@@ -11,7 +11,8 @@
             buildForRunning = "YES"
             buildForProfiling = "YES"
             buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
+            buildForAnalyzing = "YES"
+            hideIssues = "NO">
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "4C91273D0ADBF46200AF202E"
@@ -25,7 +26,8 @@
             buildForRunning = "YES"
             buildForProfiling = "YES"
             buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
+            buildForAnalyzing = "YES"
+            hideIssues = "NO">
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "4C711D5813AFCD0900FE865D"
             argument = "si_12_item_stress"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_13_item_system"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "si_14_dateparse"
             isEnabled = "NO">
             argument = "si_16_ec_certificate"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_17_item_system_bluetooth"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "si_20_sectrust_activation"
             isEnabled = "NO">
          </CommandLineArgument>
          <CommandLineArgument
             argument = "si_33_keychain_backup"
-            isEnabled = "NO">
+            isEnabled = "YES">
          </CommandLineArgument>
          <CommandLineArgument
             argument = "si_40_seckey"
             argument = "si_88_sectrust_vpnprofile"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_89_cms_hash_agility"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_90_emcs"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_91_sectrust_ast2"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "sc_30_peerinfo"
             isEnabled = "NO">
             argument = "otr_packetdata"
             isEnabled = "NO">
          </CommandLineArgument>
-         <CommandLineArgument
-            argument = "pcs_shareprotection"
-            isEnabled = "NO">
-         </CommandLineArgument>
       </CommandLineArguments>
       <EnvironmentVariables>
          <EnvironmentVariable
index 003d415011d3c27c7e297d1c7c4c641e26d14f87..2975e13d6ff0b9e17b9e115ad6fd08b9e2a743c8 100644 (file)
             argument = "si_16_ec_certificate"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_17_item_system_bluetooth"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "si_20_sectrust_activation"
             isEnabled = "NO">
             argument = "si_88_sectrust_vpnprofile"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_89_cms_hash_agility"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "si_91_sectrust_ast2"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "sd_10_policytree"
             isEnabled = "NO">
index acbfe3f073193af4445465dde441de94b3cf5743..280d9d48777ce97656d17adb412eee3b977c96e8 100644 (file)
             argument = "secd_05_corrupted_items"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "secd_20_keychain_upgrade"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "secd_21_transmogrify"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "secd_30_keychain_upgrade"
             isEnabled = "NO">
             argument = "sc_140_hsa2"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "secd_154_engine_backoff"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "secd_95_escrow_persistence"
             isEnabled = "NO">
index c966c0101e1dd67c01735daa7cf8d78aef6956f3..3363c039e34af5cae6c20831125f6004321403db 100644 (file)
@@ -20,6 +20,8 @@
        <true/>
        <key>com.apple.springboard.wipedevice</key>
        <true/>
+       <key>com.apple.private.system-keychain</key>
+       <true/>
        <key>application-identifier</key>
        <string>com.apple.security.regressions</string>
        <key>keychain-access-groups</key>
index 544cdf0b851d72ca7711788a97eeeba73792e90b..5d97e419ee19518a876e2cb12f2c8862980153e7 100644 (file)
                        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;
                };
                        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;
                };
index 4d4bad7a3a62894f9d5ef3fa78a7fffcc5883bab..ac3d1b60d597c36267ed9fa68919c2af241868eb 100644 (file)
        <true/>
        <key>restore-keychain</key>
        <true/>
+       <key>com.apple.private.syncbubble-keychain</key>
+       <true/>
+       <key>com.apple.private.system-keychain</key>
+       <true/>
        <key>application-identifier</key>
        <string>com.apple.security</string>
 </dict>
index 23f568591ae1ad398320155bd3086f4d0a64bc5e..da00ab89355873a79df88ee1e9ab6f2fa758fe99 100644 (file)
 #include <string.h>
 #include <unistd.h>
 #include <libkern/OSByteOrder.h>
+#include <Security/SecACL.h>
+#include <Security/SecItem.h>
+#include <Security/SecItemPriv.h>
 #include <Security/SecKeychainItem.h>
+#include <Security/SecKeychainItemPriv.h>
 #include <Security/SecKeychainSearch.h>
 #include <Security/SecCertificate.h>
 #include <CoreFoundation/CFString.h>
@@ -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)
index db6b6848d34864620bb272a9641b419e76101dbc..53e64259fe3389b6683a054ea235eab52e8e7150 100644 (file)
@@ -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);
index eda345856acd5f5446423c65b25fd52354025f13..eb89a7f73eb373e9cefb166eeccb00d70e56299e 100644 (file)
@@ -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;
index ae9fcc20045395b0a553268318d6c875d3b6d4a5..4d1bf2ef81ba7531db2ece75c6b7068706fec20f 100644 (file)
@@ -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, "<NULL>");
 }
 
-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;
+}
index f291bb4fde2eec4cc57fbffa3e870715e258fab1..09da8a822034245ae55b5ba499580fb765035ba0 100644 (file)
@@ -29,6 +29,8 @@
 #include <Security/SecKeychain.h>
 
 #include <stdio.h>
+#include <CoreFoundation/CFData.h>
+#include <CoreFoundation/CFDictionary.h>
 
 #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
index c1e9f0d93f0f36c89730dece8372873c6cd8f5bc..15b8bacdc4d33d78c6114010aaf5128e40fe3264 100644 (file)
@@ -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"
index 39fd218c79062f80671900983c5313c32b6a4396..da20e5f106d5f1fd036efb13488fcb4d71e7a9a4 100644 (file)
@@ -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"
index 87f1a6295db21ce2d982f3346529368a41c260b6..3b0283b701a8a13aa0f44adcea069887fc15ce11 100644 (file)
@@ -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;
 }
index 0381c22933157c5a9af2dd37be2cc302675e59dd..eeb5ad82f097501468a1d75161379f4d97aa94fb 100644 (file)
@@ -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;
index 98b76f1398192e8bc64ddaf858d0289e309da6b3..19cb5737e65b1fb8cf77da8e608bd86b9cb35f59 100644 (file)
@@ -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.
index 90b927e50dbfba4d311927bba77c04011a4366de..05d0033b9ef05400ed1ad7f8ab5edde42c357673 100644 (file)
@@ -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;
index 77f4814db9bc6f5665e3f71083a457887985b861..f43e9bf5f919fadb94f67b70b39108ee90b6ca97 100644 (file)
@@ -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;
index 02dd9d61cbf9a5ac0a93e089b9cc9cec2a3689d3..3ae7c0f319f0e26446f656c8b55706c27fb0590d 100644 (file)
@@ -59,6 +59,7 @@
 #include <Security/SecKeyPriv.h>
 #include <utilities/SecCFWrappers.h>
 #include <CoreFoundation/CFTimeZone.h>
+#include <Security/SecBasePriv.h>
 
 
 #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
index e6fc277d4a544948ac43c425d50769104c377c0b..e8d1e33d0af04c5e8bde45d13060849f525ada44 100644 (file)
@@ -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* */
index 3bee76835033070fc2774d31b48f2646404d320a..77bf3006a3c0cf00fc37ba3e5b6bebaf42c7e490 100644 (file)
@@ -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 <stdio.h>
@@ -28,6 +42,7 @@
 #include <Security/oidsalg.h>
 #include <Security/SecPolicy.h>
 #include <Security/SecItem.h>
+#include <Security/SecItemPriv.h>
 #include <Security/SecIdentity.h>
 #include <Security/SecCertificateInternal.h>
 #include <Security/SecKeyPriv.h>
@@ -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)
index 5976887b73ad1abad8371905f485e6a744e8db9c..1eed5d7ba10ca98b2c660f1bf8da7bd23e24f73b 100644 (file)
 #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
 /* { 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),
+
 };
 
 /*
index 8290ccdc2f364c53233141c24c117cdcfc1ebc96..c677ee5f0803c3b647ee7c320f4b0d6b31c79181 100644 (file)
@@ -98,6 +98,7 @@ _SecCmsSignerInfoAddMSSMIMEEncKeyPrefs
 _SecCmsSignerInfoAddSMIMECaps
 _SecCmsSignerInfoAddSMIMEEncKeyPrefs
 _SecCmsSignerInfoAddSigningTime
+_SecCmsSignerInfoAddAppleCodesigningHashAgility
 _SecCmsSignerInfoCreate
 _SecCmsSignerInfoCreateWithSubjKeyID
 _SecCmsSignerInfoGetCertList
@@ -107,6 +108,7 @@ _SecCmsSignerInfoGetSignerCommonName
 _SecCmsSignerInfoGetSignerEmailAddress
 _SecCmsSignerInfoGetSigningCertificate
 _SecCmsSignerInfoGetSigningTime
+_SecCmsSignerInfoGetAppleCodesigningHashAgility
 _SecCmsSignerInfoGetVerificationStatus
 _SecCmsSignerInfoIncludeCerts
 _SecCmsSignerInfoSaveSMIMEProfile
index 89cd83768fe28777baf22af67af66ba4d8bd8a36..4e891e665b0b9139fa3a845da873fdd2bfbf5428 100644 (file)
                        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;
                79BDD2B10D60CA06000D84D3 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               COPY_PHASE_STRIP = NO;
                                GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
                                HEADER_SEARCH_PATHS = (
                                        "$(PROJECT_DIR)",
                                PRODUCT_NAME = CMS;
                                PUBLIC_HEADERS_FOLDER_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/Security";
                                SKIP_INSTALL = YES;
+                               STRIP_INSTALLED_PRODUCT = NO;
                        };
                        name = Debug;
                };
                79BDD2BD0D60CA0A000D84D3 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               COPY_PHASE_STRIP = YES;
                                GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
                                HEADER_SEARCH_PATHS = (
                                        "$(PROJECT_DIR)",
                                PRODUCT_NAME = CMS;
                                PUBLIC_HEADERS_FOLDER_PATH = "$(INDIGO_INSTALL_PATH_PREFIX)/usr/local/include/Security";
                                SKIP_INSTALL = YES;
+                               STRIP_INSTALLED_PRODUCT = YES;
                        };
                        name = Release;
                };
index 9ecdbc5d04df5c357776765a7a623840f8c53084..12f1d28bf28e26fa74981507b7b20ed7396d1755 100644 (file)
Binary files a/resources/English.lproj/CloudKeychain.strings and b/resources/English.lproj/CloudKeychain.strings differ
index d71695e98d1c8a0e86b597d1a20f354a87b12ac7..fdc1323e75b73acf0fade3f5542daeb42be59f3a 100644 (file)
@@ -14,6 +14,8 @@
        <true/>
        <key>migrate-keychain</key>
        <true/>
+       <key>com.apple.private.system-keychain</key>
+       <true/>
        <key>modify-anchor-certificates</key>
        <true/>
        <key>com.apple.springboard.wipedevice</key>
index 17fd61428dffe2f5ab0511144c77f18451e324dd..c7117da5cbfad282c632cdb9e5ec65ddde3e9439 100644 (file)
@@ -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_ */
index d2cb04e36f3dcb179ab65e953e64c3fbeafe2da4..ee97e49a977f86f9727c3448095900dfec85f83e 100644 (file)
                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 */
 
                C2CB75A90CE26A3600727A2B /* securityd-watch.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; name = "securityd-watch.d"; path = "dtrace/securityd-watch.d"; sourceTree = "<group>"; };
                C2D425F105F3C07400CB11F8 /* tokendatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = tokendatabase.cpp; sourceTree = "<group>"; };
                C2D425F205F3C07400CB11F8 /* tokendatabase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokendatabase.h; sourceTree = "<group>"; };
+               C2E8FBA31B8FABFE00156D36 /* acl_partition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = acl_partition.cpp; sourceTree = "<group>"; };
+               C2E8FBA41B8FABFE00156D36 /* acl_partition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acl_partition.h; sourceTree = "<group>"; };
                C2FDCABD0663CD5B0013F64C /* pcscmonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = pcscmonitor.cpp; sourceTree = "<group>"; };
                C2FDCABE0663CD5B0013F64C /* pcscmonitor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pcscmonitor.h; sourceTree = "<group>"; };
                C2FDCABF0663CD5B0013F64C /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = "<group>"; };
                                C28654B006DBC2A30021E6E5 /* tokenacl.cpp */,
                                4C9264990534866F004B0E72 /* acl_keychain.h */,
                                4C9264980534866F004B0E72 /* acl_keychain.cpp */,
+                               C2E8FBA41B8FABFE00156D36 /* acl_partition.h */,
+                               C2E8FBA31B8FABFE00156D36 /* acl_partition.cpp */,
                        );
                        name = ACLs;
                        sourceTree = "<group>";
                                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 */,
                                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 */,
                        );
                        buildSettings = {
                                HEADER_SEARCH_PATHS = (
                                        "$(inherited)",
+                                       ../OSX/include,
+                                       "$(SDKROOT)/usr/local/include",
                                        "$(BUILT_PRODUCTS_DIR)/derived_src",
                                        "$(SRCROOT)",
                                        "$(SRCROOT)/securityd",
                                        "\"$(SRCROOT)/../../../build/Products\"",
                                        "\"$(SRCROOT)/securityd/../../../build/Products\"",
                                );
-                               ORDER_FILE = "$(SRCROOT)/securityd/src/securityd.order";
+                               ORDER_FILE = src/securityd.order;
+                               SDKROOT = macosx.internal;
                        };
                        name = Debug;
                };
                        buildSettings = {
                                HEADER_SEARCH_PATHS = (
                                        "$(inherited)",
+                                       ../OSX/include,
+                                       "$(SDKROOT)/usr/local/include",
                                        "$(BUILT_PRODUCTS_DIR)/derived_src",
                                        "$(SRCROOT)",
                                        "$(SRCROOT)/securityd",
                                        "\"$(SRCROOT)/../../../build/Products\"",
                                        "\"$(SRCROOT)/securityd/../../../build/Products\"",
                                );
-                               ORDER_FILE = "$(SRCROOT)/securityd/src/securityd.order";
+                               ORDER_FILE = src/securityd.order;
+                               SDKROOT = macosx.internal;
                        };
                        name = Release;
                };
index 97052db90545f063085d489a4fe1ac141a35a1f9..e79d5ea2c571621abdcdbc919abf3df3a621565f 100644 (file)
@@ -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<SecurityServerEnvironment>()) {
+                       Process& process = env->database->process();
+                       StLock<Mutex> _(process);
+                       RefPointer<OSXCode> clientXCode = new OSXCodeWrap(process.currentGuest());
+                       RefPointer<AclSubject> 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<SecurityServerEnvironment>()) {
                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<Mutex> _(process);
-                               RefPointer<OSXCode> clientXCode = new OSXCodeWrap(clientCode);
-                               RefPointer<AclSubject> subject = new CodeSignatureAclSubject(OSXVerifier(clientXCode));
-                               SecurityServerAcl::addToStandardACL(context, subject);
+                               alwaysAllow();
                        }
 
                        // finally, return the actual user response
index 6a143151743f0baccf56404d524735ab73c0c9e7..755e6970e8e8ef05e8461b41f9f5e3e66c91299d 100644 (file)
@@ -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 (file)
index 0000000..056743b
--- /dev/null
@@ -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 <security_cdsa_utilities/cssmwalkers.h>
+#include <security_cdsa_utilities/cssmlist.h>
+#include <algorithm>
+
+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<CFDataRef> 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 (file)
index 0000000..b43a58e
--- /dev/null
@@ -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 <security_cdsa_utilities/cssmacl.h>
+#include <security_utilities/cfutilities.h>
+
+
+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
index f4df094022a14fc30e3439b4e6daef95171a1f3c..6eacafb62658f9f9e5ed7272f9186d2da4f61f29 100644 (file)
 #include "agentquery.h"
 #include "tokendatabase.h"
 #include "acl_keychain.h"
+#include "acl_partition.h"
 
 // ACL subjects whose Environments we implement
 #include <security_cdsa_utilities/acl_any.h>
 #include <security_cdsa_utilities/acl_password.h>
-#include <security_cdsa_utilities/acl_threshold.h>
+#include "acl_keychain.h"
 
 #include <sys/sysctl.h>
 #include <security_utilities/logging.h>
+#include <security_utilities/cfmunge.h>
 
 //
 // SecurityServerAcl is virtual
@@ -71,7 +73,27 @@ void SecurityServerAcl::changeAcl(const AclEdit &edit, const AccessCredentials *
 {
        StLock<Mutex> _(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<Mutex> objectSequence(aclSequence);
        StLock<Mutex> 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<CFDictionaryRef> partition = this->createPartitionPayload()) {
+               CFArrayRef partitionList;
+               if (cfscan(partition, "{Partitions=%AO}", &partitionList)) {
+                       CFRef<CFStringRef> partitionDebug = CFCopyDescription(partitionList);   // for debugging only
+                       secdebugfunc("integrity", "ACL partitionID = %s", cfString(partitionDebug).c_str());
+                       if (env.database) {
+                               CFRef<CFStringRef> 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<ThresholdAclSubject *>(subject.get())) {
+                       unsigned size = threshold->count();
+                       if (KeychainPromptAclSubject* last = dynamic_cast<KeychainPromptAclSubject *>(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<EntryMap::const_iterator, EntryMap::const_iterator> 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<PartitionAclSubject*>(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<CFDictionaryRef> payload("{Partitions=[%s]}", partitionID.c_str());
+       ObjectAcl::AclSubjectPointer subject = new PartitionAclSubject();
+       static_cast<PartitionAclSubject*>(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<CFDictionaryRef> payload = subject->createDictionaryPayload()) {
+                       CFArrayRef partitionList;
+                       if (cfscan(payload, "{Partitions=%AO}", &partitionList)) {
+                               CFTemp<CFDictionaryRef> 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
 //
index 5df4ba25555a3cad95bc8f5dcbaffa31d6d29e6e..845c70542038c50cce5390b1d929690944a8dda8 100644 (file)
 #include <security_cdsa_utilities/acl_preauth.h>
 #include <security_cdsa_utilities/acl_prompted.h>
 #include <security_cdsa_utilities/acl_threshold.h>
+#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);
 };
 
 
index 8c84a05fdee79f70c31d440acaf217a36ada0a87..d75b2494de7e981683b9766aeb2a741a4706d34a 100644 (file)
@@ -26,6 +26,8 @@
 #include "clientid.h"
 #include "server.h"
 #include <Security/SecCodePriv.h>
+#include <Security/oidsattr.h>
+#include <Security/SecCertificatePriv.h>
 
 
 //
@@ -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<CFDictionaryRef> 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<CFDictionaryRef> 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<CFStringRef> 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<CFDictionaryRef> info;
+       MacOSError::check(SecCodeCopySigningInformation(processCode(), kSecCSDefaultFlags, &info.aref()));
+       CFCopyRef<CFDictionaryRef> entitlements = (CFDictionaryRef)CFDictionaryGetValue(info, kSecCodeInfoEntitlementsDict);
+       if (entitlements && entitlements.is<CFDictionaryRef>()) {
+               CFTypeRef value = CFDictionaryGetValue(entitlements, CFTempString(name));
+               if (value && value != kCFBooleanFalse)
+                       return true;            // have entitlement, it's not <false/> - bypass partition construction
+       }
+       return false;
+}
+
+
 //
 // Bonus function: get the path out of a SecCodeRef
 //
index 57d9caf7b0ab2f65e26af1cd792f46ebf01bcbc4..cc28a8df2418f0bf1edce8b006ade6aa042d98ab 100644 (file)
@@ -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<SecGuestRef, GuestState> GuestMap;
        mutable GuestMap mGuests;
        
+       mutable std::string mClientPartitionId;
+       mutable bool mGotPartitionId;
+       
        GuestState *current() const;
+       static std::string partitionIdForProcess(SecStaticCodeRef code);
 };
 
 
index 3fddcf64f43f4cb48703edd980b7197a2f11ef9b..d0f2ed034999b6a8573f868855991f49c5e7fe2c 100644 (file)
@@ -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);
index 0ab8faa8da2ee7abd169d2099600bfeb6f31a100..311b9e0fbab0cbf627c50ac7475e2646acfa4f4d 100644 (file)
@@ -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<Key> &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<DbCommon>(); }
        virtual const char *dbName() const = 0;
        virtual void dbName(const char *name);
+
+    virtual uint32 dbVersion() { return common().dbVersion(); }
 };
 
 
index 22180f63188dc20b8c81028d0cb1588b267bfe17..b009f0036c55c46d9b930626d500960b2c308629 100644 (file)
@@ -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;
index fdbc7f4b754268156ba96ac6bddd870d6bbb39e7..d00648d21381571247c083fe3a65a99d650cb613 100644 (file)
@@ -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)
index 4bae65a50b0295edef445edd723d6665a4a82088..4326b29d47340462e5ab0fdecc2e7f5ed0eba05a 100644 (file)
@@ -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<CssmSample> samples;
+    if (cred && cred->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, samples)) {
+        for (list<CssmSample>::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<Mutex, Mutex> 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<KeychainDbCommon> newCommon = new KeychainDbCommon(proc.session(), ident);
+    StLock<Mutex> _(*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<Mutex, Mutex> 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<CssmSample> samples;
+    if (creds && creds->samples().collect(CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, samples)) {
+        for (list<CssmSample>::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);
        }
index 3e774497d6b339605223b4fff2684e2b7d915a83..b34da0cd0485df375d7a64761f95dc9f9ce1d497 100644 (file)
@@ -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<Key> extractMasterKey(Database &db, const AccessCredentials *cred,
                const AclEntryPrototype *owner, uint32 usage, uint32 attrs);
index cd4cd039bcf33a6a01c223f59521d4a436e81ae6..d5917c8ee480beefa4230e31024c4b2fe0ff4d6d 100644 (file)
@@ -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);
     }
index 7543ded371b60415e3435ebb917f298b2510fb6a..734d16a6331f31c44561addcb0b8930b56cf6c0f 100644 (file)
@@ -29,6 +29,8 @@
 #include "server.h"
 #include "database.h"
 #include <security_cdsa_utilities/acl_any.h>
+#include <security_utilities/cfmunge.h>
+#include <security_utilities/logging.h>
 
 
 //
@@ -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());
+    }
 }
 
 
index 77e3077ceaecdfda6adcad6c298a55cd80ae6b83..722edac7e07d0d0c08ce8dbc01115bcff68c8b33 100644 (file)
@@ -58,6 +58,7 @@
 #include <security_cdsa_utilities/acl_comment.h>
 #include <security_cdsa_utilities/acl_preauth.h>
 #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
index 941408010c1821d13f8e3e552e0af7499e0f038f..990eab78cec1127771cd78a6e952b6b05bbb64a8 100644 (file)
@@ -32,6 +32,7 @@
 #include <security_utilities/machserver.h>
 #include <security_utilities/powerwatch.h>
 #include <security_utilities/ccaudit.h>
+#include <security_utilities/threading.h>
 #include <security_cdsa_client/cssmclient.h>
 #include <security_cdsa_client/cspclient.h>
 #include <security_utilities/devrandom.h>
index ed08fd1cf5d0ce8f4341d8eb611f8d46bbe8cd08..ddb8f5d450eb1cd5bb430580fe47a12734c4ea71 100644 (file)
@@ -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;
index 10195543e1186ee25bcdf90d15d95b9b0bbe3fdc..88c0c23bac899cf3eac303f1adaef6c819628e32 100644 (file)
@@ -46,6 +46,7 @@ public:
        TempDatabase(Process &proc);
 
        const char *dbName() const;
+    uint32 dbVersion();
        bool transient() const;
        
        RefPointer<Key> makeKey(const CssmKey &newKey, uint32 moreAttributes,
index e48a9a3bcb2d23e84c9623c698a4f310ee89cdef..566df264f96f9d7bd9943f1567c7e3a6e722e5ec 100644 (file)
@@ -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();
index 1512fd96f4e9539ba2ec5fc75fa908713458521a..7f722634942032070468918bd24c0945828f9128 100644 (file)
@@ -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<KeychainDatabase> 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)
 }